1

I'm really really confused about how django handles database relationships.

Originally I had an article model that contained a simple IntegerField for article_views, recently I'm trying to expand the definition of a article_view to contain it's own fields so I created a model for it. (IP, SESSION KEY etc..)

I'm at a bit of a loss regarding how to make the relationship, to me it makes the most sense to have a one-to-many field inside the article model, because an article can have many different views, but a view can only be part of one article.

all the implementations I'm seeing have this set up in a really weird reverse manner, what gives?

davegri
  • 2,206
  • 2
  • 26
  • 45
  • Can you show us your model code? I think what you want to do is to create the relation as a foreignkey field to `Article` in the `ArticleView` model. That will create a one-to-many relation to Article. You don't need to define a field or attribute in the Article model itself. – Håken Lid Jul 12 '15 at 11:57
  • Thats what I've done it just seemed really weird and counter intuitive that the field that defines how many views my article has isn't actually inside my article, thought maybe I was missing something but I guess not. Up until know when my article views were an IntegerField inside the article model I could easily show the views in the template, sort by the amount of views in the admin panel and so forth.. now I'm not really sure how to do all that. – davegri Jul 12 '15 at 12:00
  • You can create a property in Article that is called `article_views` and calculates that number on demand. If you post your model code, someone can probably show you how to do that. When accessing that property in templates, it doesn't matter if it's a modelfield or a method. But you might want to use some tricks to avoid slow and unnecessary database queries, if you need to access `article_views` a lot. – Håken Lid Jul 12 '15 at 12:08

1 Answers1

4

Unfortunately Django does not have a One-to-Many field. This is achieved by creating a ForeignKey on in this case the ArticleView model. When you want to easily access the article views in your template you can set the related_name on the ForeignKey.

class Article(models.Model):
    # Article definition

class ArticleView(models.Model):
    article = models.ForeignKey(Article, related_name='views')

In the template you can now use article.views.count() to get the number of views coupled to an account.

Please note that this creates a database query for each count you want. It would probably be better to have a queryset with annotate: Article.objects.annotate(num_views=Count('views'))

jgadelange
  • 2,482
  • 1
  • 13
  • 10
  • thanks for the great explanation! any chance for clarification on what annotate does here? – davegri Jul 12 '15 at 13:54
  • Maybe it is best if you read the [documentation](https://docs.djangoproject.com/en/1.8/topics/db/aggregation/#generating-aggregates-for-each-item-in-a-queryset). Basically it adds a `COUNT()` expression and a `JOIN` to your SQL-query – jgadelange Jul 12 '15 at 14:01