Django活动提要(Feedly集成?)

Django活动提要(Feedly集成?),django,tastypie,feed,django-aggregation,Django,Tastypie,Feed,Django Aggregation,我已经建立了一个简单的Django照片应用程序。用户可以上传照片,跟随其他用户和喜欢的照片。为了处理用户之间的关系(以下和以下),我使用了一个名为coleifer的包。这是一个很棒的软件包,使用非常简单 一切正常。我目前有一个工作活动提要 我将提要分为两个部分:Following(我关注的用户的所有活动)和You(发生在我身上的所有活动)。我在下面发布了两张来自我的iOS应用程序的图片,该应用程序使用我的Django照片应用程序作为后端: 我想做的是向以下提要添加聚合。如您所见,用户alex

我已经建立了一个简单的Django照片应用程序。用户可以上传照片,跟随其他用户和喜欢的照片。为了处理用户之间的关系(以下和以下),我使用了一个名为coleifer的包。这是一个很棒的软件包,使用非常简单

一切正常。我目前有一个工作活动提要

我将提要分为两个部分:Following(我关注的用户的所有活动)和You(发生在我身上的所有活动)。我在下面发布了两张来自我的iOS应用程序的图片,该应用程序使用我的Django照片应用程序作为后端:

我想做的是向以下提要添加聚合。如您所见,用户alexperri喜欢5张照片。我想把所有这些项目汇总成一行。我不需要为“You”提要添加聚合,因为我希望看到每个动作都发生在我身上。但是,对于下面的提要,添加聚合是有意义的。有几个应用程序可以很好地进行聚合。Fashionlista、Pinterest和Instagram在这方面做得很好。以下是Instagram的一个例子,展示了我正在努力实现的目标:

在上面的示例中,您可以看到下面的提要和5张照片。我开始玩Instagram,看看它是如何工作的。Instagram Follow feed显示最多35个活动条目,每个条目最多可以有5个该动作类型的活动。“lovetoronto喜欢5张照片”是一个活动条目,它显示了他喜欢的最新5张照片。因为洛夫多伦多表演了最新的动作,他是最棒的

我想实现相同的设置

以下是我当前的模型设置:

型号.py

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)
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') 
每次创建一个“Like”对象时,我也会创建一个活动对象,参与者是执行操作的人,接收者是执行操作的人,操作(在本例中是字符串“liked”)、post(照片)以及活动对象的创建时间

我使用django tastypie获取并创建“Like”和“Activity”对象

api.py

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)
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') 

如何修改以下提要资源,使其聚合活动对象?我偶然发现了这个项目。如何在当前设置中使用它?

在提要资源中,您已经覆盖了get\u object\u列表,我建议更改逻辑以执行聚合逻辑的原始查询

def get_object_list(self, request):
        query = "Your aggregation query logic here"
        feed_model = self._meta.object_class
        return feed_model.objects.raw(query)
这应该是必需的。但是,您需要考虑查询逻辑。如果你还有其他问题,请告诉我


谢谢

我认为最好的方法是修改活动表以存储分组的活动。当新操作发生时,请检查相同类型的现有操作,并编辑记录使其“分组”,或添加新记录。您可以向包含相关记录的所有潜在表中添加许多关系,或者只将数据存储在json字段中,该字段包含足够的信息,可以在提要中呈现活动,而无需查询其他表对象


如果资源过于密集,您可以将新活动的添加/编辑排队。您最好将活动表保持为一个在呈现时不需要任何处理的直接提要。这不是最容易实现的解决方案,但我认为从长远来看,它是有意义的。

设置聚合时间,例如,您希望在10分钟内聚合所有“喜欢的”还是在过去的24小时内聚合

然后可以按此时间帧过滤对象

然后,您可以使用.values('model\u field')方法应用分组。Django生成包含“分组依据”的sql

然后,最后添加一个聚合限制,以便当喜欢的数量超过此限制时,显示聚合视图,而不是单个活动视图

以下示例(伪,非实际):


我认为您不希望进行任何数据库级聚合,因为您可能希望显示单个细节以及计数,例如“X喜欢5张照片”并显示5张照片。根据定义,聚合将排除单个数据

相反,您应该使用Python代码(或者Javascript)进行分组和排序,因为我认为您使用的是HTTP API,但我更喜欢已经组织好的服务器端API


也许会有帮助。我认为您需要按(用户和操作)分组,然后按每组中第一个项目的时间戳排序,这样您可能会看到“Joe喜欢5张照片”、“Anne发布2张照片”、“Joe发布一张照片”、“Claire喜欢3张照片”等。

@Rahual Tanwani,感谢您的快速响应,这是让我挠头的查询逻辑,这就是我要找的,你是否也需要按
操作进行分组?除了
喜欢的
,还有其他动作类型吗?@mariodev感谢您的快速回复。是的,我想按用户分组,然后按他们所做的操作分组。此外,还有其他行动。有以下内容、评论和提及。差不多就是这样。因此,我不想让提要显示alexperri的每一个类似活动,而是将它们聚合起来。“阿列克斯佩里喜欢5张照片”(在最后一个小时里展示了最新的5张照片……即使阿列克斯佩里在最后一个小时里喜欢5张以上的照片,我也只想展示最新的5张)。@mariodev,如果阿列克斯佩里喜欢10张照片,而阿列克斯佩里在最后一个小时跟随鲍勃和凯尔。我想对最近采取的行动进行分类。因此,如果阿列克斯佩里最近做的动作是“喜欢”,并且他是我跟踪的所有人中最新做动作的人,我会检查我跟踪的所有人的最后100项活动,从列表中抓取阿列克斯佩里最近的5项喜欢的动作,并将其汇总(阿列克斯佩里喜欢5张照片)。然后我会检查下一个我跟随的人是谁