I have a model with articles, events and people:
class Person(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=30)
class Event(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=200)
class Article(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=200)
publishDate = models.DateTimeField(blank=True, null=True)
event = models.ForeignKey(Event, blank=False, null=False)
persons = models.ManyToManyField(Person)
An article belongs to an event, and events consist of many articles. Persons appear in many articles and articles contain many persons. The idea is to see which events were most written about inside a given time interval. I did this in a single query:
topEvents = Article.objects.filter(publishDate__gt=dateStart)
.filter(publishDate__lt=dateEnd)
.values('event').annotate(count=Count('id'))
.order_by('-count')[:topN]
I found that this takes significantly less time than calculating the top N server-side.
Now, the question is, how do I do the same with the ManyToMany relation I have with the Persons? Also, is this the best way to do this?
To simplify your example:
Note that there are no
idfields as Django creates them automatically. Also, botheventandpersonson theArticleclass haverelated_nameset to ‘articles’ which allows us to refer to articles simply by usingevent.articlesandperson.articles.Now, to get the events and people that are written about most often, you can query directly on their model managers: