Wednesday, October 5, 2011

Re: Combining Querysets from different, but similar models

I had a similar need and solved it with a separate table of activity feed
items. Here's the code for the Item model:

class Item(models.Model):

object_id = models.PositiveIntegerField(db_index=True)
content_type = models.ForeignKey(ContentType)
content_object = generic.GenericForeignKey('content_type', 'object_id')
...
[your common feed item fields go here]

Then I ensured that each model that could show up in the activity feed
added a new Item object in its save() method. The result is that you can
pull the feed with one query, which could help a lot if you're mashing
together several models. The downside is that you need to make sure the
items table stays in sync with the data from the models it is merging
together.


Brett


On 10/5/11 8:37 AM, "Steven Smith" <steven@stevenlsmith.com> wrote:

>I'm working on a site that has a requirement for a "recent activity"
>feed on the homepage. Usually, I'd just do a MyFoo.objects.order_by('-
>created') and all would be well. But "activity" is actually from
>several models. They all have some fields in common, like the
>timestamp, since they all have the same abstract base class, but
>they're definitely different things.
>
>What's the cheapest way to do my queries and mix the results into one
>feed? Ideally, the name of the model, or some other differentiating
>attribute would be exposed so that I can use it in my template loop as
>a style hook. Models in question are below...
>
>
>class TrackableModel(models.Model):
> created = models.DateTimeField(auto_now_add=True)
> modified = models.DateTimeField(auto_now=True)
> created_by = models.ForeignKey(User, blank=True, null=True)
> history = models.TextField(blank=True)
> notes = models.TextField(blank=True)
> is_active = models.BooleanField(blank=True, default=True)
>
> class Meta:
> abstract = True
>
>
>class Review(TrackableModel):
> book = models.ForeignKey('Textbook')
> course = models.ForeignKey('TaughtCourse', blank=True, null=True)
> should_buy = models.BooleanField(blank=True)
> rating_prep = models.DecimalField(blank=True, null=True,
>max_digits=2, decimal_places=1)
> rating_hw = models.DecimalField(blank=True, null=True,
>max_digits=2, decimal_places=1)
> rating_inclass = models.DecimalField(blank=True, null=True,
>max_digits=2, decimal_places=1)
> can_share = models.BooleanField(blank=True, default=True)
> comments = models.TextField(blank=True)
>
>
>class MarketplacePosting(TrackableModel):
> book = models.ForeignKey('Textbook', blank=True, null=True)
> school = models.ForeignKey('School', blank=True, null=True)
> location = models.CharField(max_length=255, blank=True,
>verbose_name="Sale location")
> condition = models.CharField(max_length=15, blank=True,
>choices=CONDITION_CHOICES)
> contains_highlighting = models.BooleanField(blank=True)
> price = models.DecimalField(blank=True, null=True, max_digits=6,
>decimal_places=2)
> comments = models.TextField(blank=True)
> is_sold = models.BooleanField(blank=True)
>
>--
>You received this message because you are subscribed to the Google Groups
>"Django users" group.
>To post to this group, send email to django-users@googlegroups.com.
>To unsubscribe from this group, send email to
>django-users+unsubscribe@googlegroups.com.
>For more options, visit this group at
>http://groups.google.com/group/django-users?hl=en.
>

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment