2015-01-26 84 views
1

我对用户的活动模式:Django的 - 通过模型类的不同字段筛选

class Activity(models.Model): 
    actor = models.ForeignKey(User) 
    action = models.CharField(max_length=100) 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False) 

    class Meta: 
     verbose_name = 'Activity' 
     verbose_name_plural = 'Activities' 
     ordering = ['-pub_date'] 

    def __unicode__(self): 
     return ("%s %s") % (self.actor.username, self.action) 

观点:

def home(request): 
    if request.user.is_authenticated(): 
     user = request.user 
     userP = Person.objects.get_or_create(user=user) 
     userP = userP[0] 
     following = userP.get_following() 
     users = [] 
     actors = list(following.values_list('user', flat=True)) + [user.id] 
     activities = Activity.objects.filter(actor__in=actors)    

更新

假设3个用户喜欢相同的状态和user3是最后一个喜欢这种状态。现在,这将创建3个活动,说“User1喜欢状态”,“User2喜欢状态”,“User3喜欢状态”。我想要的只是每个状态是最近一次的活动。所以在这种情况下,它会是“User3喜欢的状态”。

状态模型:

class Status(models.Model): 
    body = models.TextField(max_length=200) 
    image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name) 
    privacy = models.CharField(max_length=1,choices=PRIVACY, default='F') 
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False) 
    user = models.ForeignKey(User) 
    hearts = generic.GenericRelation(Heart, null=True, blank=True) 

class Heart(models.Model): 
    user = models.ForeignKey(User) 
    pub_date = models.DateTimeField(auto_now_add=True, auto_now=False) 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

更新

这是signals.py创建每个对象的活动(心脏或状态):如果你的数据库

def create_activity_item(sender, instance, signal, *args, **kwargs): 
    if kwargs.get('created', True): 
     ctype = ContentType.objects.get_for_model(instance) 
     if ctype.name == 'Status': 
      action = ' shared ' 

      activity = Activity.objects.get_or_create(
       actor = instance.user, 
       action = action, 
       content_type = ctype, 
       object_id = instance.id, 
       pub_date = instance.pub_date 
      ) 

     if ctype.name == 'Heart': 
      action = ' gave heart to ' 

      activity = Activity.objects.get_or_create(
       actor = instance.user, 
       action = action, 
       content_type = ctype, 
       object_id = instance.id, 
       pub_date = instance.pub_date 
      ) 

for modelname in [Status, Heart]: 
    post_save.connect(create_activity_item, sender=modelname, 
        dispatch_uid="create_activity_item") 
+0

您正在使用什么数据库? – almalki 2015-02-04 12:09:16

回答

0
activities = Activity.objects.filter(actor__in=users).distinct('content_type', 'object_id', 'action') 

不支持DISTINCT ON查询,你可以做查询通过查找不同值的对象手动运行:

unique_activities = [] 
activities = Activity.objects.filter(actor__in=users) 
for activity in activities: 
    unseen = True 
    for unique_activity in unique_activities: 
     if (activity.action == unique_activity.action and activity.content_type == unique_activity.content_type and activity.object_id == unique_activity.object_id): 
      unseen = False 
      break 
    if unseen: 
     unique_activities.append(activity) 

print unique_activities 
+0

它现在没有显示我任何活动。 – Kakar 2015-01-26 19:47:53

+0

真的吗?和'Activity.objects.filter(actor__in = users)'给你活动? – 2015-01-26 19:59:24

+0

我改变它来指定'content_type'和'object_id'作为独立的字段(而不是GenericForeignKey)。它现在工作吗? – 2015-01-26 20:01:26

0

这听起来像是一个greatest-per-group问题。你可以试试这个:

activities = Activity.objects.filter(
    id__in=Activity.objects.values('content_type') \ 
     .annotate(max_id=Max('id')) \ 
     .values_list('max_id', flat=True) \ 
) 
0

这将PostgreSQL只工作:

Activity.objects.order_by('action', 'content_type_id', 'object_id', '-pub_date').distinct('action', 'content_type_id', 'object_id').filter(actor__in=actors)