Django Activity Feed (Feedly Integration?)
我已经构建了一个简单的django照片应用程序。用户可以上传照片,跟踪其他用户并喜欢照片。为了处理用户之间的关系(在&unfollowing之后),我使用了一个由coliefer编写的名为django relationships的包。这是一个很好的包装和非常简单的使用。
一切正常。我目前有一个工作活动源。
我将提要过滤为两部分:跟踪(我跟踪的用户的所有活动)和您(发生在我身上的所有活动)。我在iOS应用程序上发布了以下两张图片,它们使用我的django照片应用程序作为后端:
。氧化镁
我要做的是向以下提要添加聚合。如你所见,用户Alexperri喜欢5张照片。我想把所有这些项目汇总成一行。我不需要为"你"提要添加聚合,因为我希望看到每个单独的操作发生在我身上。但是对于下面的提要,添加聚合是有意义的。有几个应用程序可以很好地进行聚合。FashionLista、Pinterest和Instagram都做得很好。以下是Instagram的一个示例,展示了我正在努力实现的目标:
氧化镁
在上面的示例中,您可以看到下面的提要,LoveToronto喜欢5张照片。我开始玩Instagram,看看它是如何工作的。提要后的Instagram最多显示35个活动条目,每个条目最多可以有5个该操作类型的活动。"LoveToronto喜欢5张照片"是一个活动条目,它显示了他最喜欢的5张照片。因为洛夫托罗多最新的表演,他是第一名。
我想实现相同的设置。
以下是我当前的模型设置:
型号.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from django.db import models from django.contrib.auth.models import User class Photographer(models.Model): user = models.OneToOneField(User, primary_key=True likes = models.ManyToManyField('Photo', through = 'Likes', related_name = 'likedby', blank = True) class Photo(models.Model): photographer = models.ForeignKey(Photographer, related_name = 'shot_owner') created = models.DateTimeField(auto_now_add=True) url = models.CharField(max_length=128) class Likes(models.Model): liked_at = models.DateTimeField(auto_now_add=True, blank=True, null=True) photographer = models.ForeignKey(Photographer, related_name = 'liked_by') photo = models.ForeignKey(Photo, null=True) class Activity(models.Model): actor = models.ForeignKey(Photographer, related_name = 'actor') receiver = models.ForeignKey(Photographer, related_name = 'receiver') action = models.CharField(max_length=12) post = models.ForeignKey(Photo, null=True, blank=True) time = models.DateTimeField(auto_now_add=True) |
每次创建"like"对象时,我也创建一个活动对象,参与者是执行操作的人,接收者是执行操作的人,操作(在本例中是字符串"liked"),发布(照片)以及创建活动对象的时间。
我使用django tastypie获取和创建"like"和"activity"对象。
Ap.Py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | from tastypie.resources import ModelResource, ALL, ALL_WITH_RELATIONS from tastypie.authentication import BasicAuthentication from tastypie.authorization import DjangoAuthorization, Authorization from photoapp.photodb.models import * from tastypie.serializers import Serializer from relationships.utils import positive_filter from relationships.models import Relationship from relationships.models import RelationshipStatus class LikeResource(ModelResource): user = fields.ForeignKey(BasicUserResource, 'user', full=True) class Meta: queryset = Photographer.objects.all() allowed_methods = ['put'] resource_name = 'like' fields = ['user'] default_format = 'application/json' authorization = Authorization() authentication = BasicAuthentication() serializer = Serializer(formats=['json']) always_return_data = True include_resource_uri = False def hydrate(self, bundle): shot = Photo.objects.all().get(id = bundle.data['photo id']) user = Photographer.objects.all().get(user = bundle.request.user) if(bundle.obj.likes.filter(id = bundle.data['photo id']).exists()): Likes.objects.all().filter(photographer=user).filter(photo=shot).delete() Activity.objects.filter(actor__user = bundle.request.user, post = shot, action = 'liked').delete() else: like = Likes(photographer = user, photo=shot) like.save() user_doing_the_liking = User.objects.get( username=bundle.request.user.username) user = Photographer.objects.all().get(user = bundle.request.user) user_getting_liked = shot.photographer.user photographer_getting_liked = shot.photographer newActivity = Activity() newActivity.actor = user newActivity.receiver = photographer_getting_liked newActivity.action = 'liked' newActivity.post = shot newActivity.save() return bundle class FollowingFeed(ModelResource): actor = fields.ForeignKey(BasicPhotographerResource, 'actor', full=True) receiver = fields.ForeignKey(BasicPhotographerResource, 'receiver', full=True) post = fields.ForeignKey(BasicPostResource, attribute = 'post', full=True, null=True) class Meta: queryset = Activity.objects.all() allowed_methods = ['get'] resource_name = 'following-feed' fields = ['actor', 'receiver', 'action', 'post', 'id', 'time'] default_format ="application/json" authorization = Authorization() authentication = BasicAuthentication() serializer = Serializer(formats=['json']) always_return_data = True include_resource_uri = False def get_object_list(self, request): return super(FollowingFeed, self).get_object_list(request)\ .filter(actor__user__in = request.user.relationships.following())\ .exclude(receiver__user = request.user)\ .exclude(actor__user = request.user).order_by('-time') |
号
如何修改以下源资源,使其聚合活动对象?我遇到了一个饲料项目。如何在当前设置中使用它?
我认为您不想进行任何数据库级的聚合,因为您可能希望显示个人的详细信息以及计数,例如"x喜欢5张照片",并显示5张照片。根据定义,聚合将排除单个数据。
相反,您应该用python代码(或者javascript)进行分组和排序,因为我认为您使用的是HTTP API,但是我更喜欢已经组织好了的服务器端API。
itertools.groupby可能会有所帮助。我认为你需要按(用户和动作)分组,然后按每组第一个项目的时间戳排序,这样你就可以看到"乔喜欢5张照片"、"安妮贴了2张照片"、"乔贴了一张照片"、"克莱尔喜欢3张照片"等。
设置聚合时间,例如,是否要在10分钟内或过去24小时内聚合所有"赞"?
然后你可以按这个时间范围过滤你的对象。
然后可以使用.values("model_uu field")方法应用分组。Django生成包含"group by"的SQL
最后添加一个聚合限制,这样当喜欢的数量超过这个限制时,您将显示聚合视图而不是单个活动视图。
以下示例(伪,非实际):
1 2 3 4 | if (activity.object.filter(time__gt=yourlowertime, time__lt=youruppertime).values(‘activity__action').count() > aggregation_limit) : # show aggregated view else: # show normal view |
号
我认为最好的方法是修改活动表来存储分组的活动。当发生新操作时,请检查是否存在相同类型的现有操作,然后编辑记录使其"分组",或者添加新记录。您可以向包含相关记录的所有潜在表添加许多关系,或者只将数据存储在JSON字段中,该字段包含足够的信息,以便在不查询其他表对象的情况下在提要中呈现活动。
如果资源太密集,可以对新活动的添加/编辑进行排队。最好将活动表保持为一个直接的提要,在呈现时不需要任何处理。这不是最容易实现的解决方案,但我认为从长远来看是有意义的。
在您的feed资源中,您已经覆盖了get_object_列表,我建议您更改逻辑以执行聚合逻辑的原始查询。
1 2 3 4 | def get_object_list(self, request): query ="Your aggregation query logic here" feed_model = self._meta.object_class return feed_model.objects.raw(query) |
这应该做所需要的。但是,您需要考虑您的查询逻辑。如果你还面临其他问题,请告诉我。
谢谢!