django feed tastypie news-feed django-aggregation

Django Activity Feed(Integración Feedly?)



tastypie news-feed (4)

Creo que la mejor manera de hacer esto sería modificar la tabla de Actividad para almacenar actividades agrupadas. Cuando se produce una nueva acción, compruebe las existentes del mismo tipo y edite el registro para que esté ''agrupado'', o agregue un nuevo registro. Puede agregar relaciones ManyToMany a todas las tablas potenciales que contienen registros relacionados, o simplemente almacenar los datos en un campo json que contenga suficiente información para representar la actividad en la fuente sin hacer consultas a otros objetos de la tabla.

Si requiere demasiados recursos, puede poner en cola la adición / edición de nuevas actividades. Probablemente sea mejor mantener la tabla de actividades solo como una alimentación directa que no requiere ningún procesamiento cuando se procesa. No es la solución más fácil de implementar, pero creo que a largo plazo tiene sentido.

He construido una aplicación de fotos Django simple. Los usuarios pueden subir fotos, seguir a otros usuarios y como fotos. Para manejar las relaciones entre los usuarios (seguir y dejar de seguir), uso un paquete llamado django-relationships por coleifer. Es un gran paquete y muy simple de usar.

Todo funciona como deberia. Actualmente tengo un feed de actividad laboral.

Filtré la fuente en dos secciones: Siguiente (todas las actividades de los usuarios que sigo) y Tú (todas las actividades que me sucedieron). He publicado dos fotos a continuación desde mi aplicación de iOS que usa mi aplicación de fotos Django como back-end:

Lo que me gustaría hacer es agregar agregación a la siguiente fuente. Como puedes ver, al usuario alexperri le han gustado 5 tiros. Me gustaría agregar todos estos elementos en una línea. No necesito agregar agregación para el feed "Tú", ya que me gustaría que cada acción individual me sucediera. Sin embargo, para el siguiente feed, tiene sentido agregar agregación. Hay varias aplicaciones que hacen muy bien la agregación. Fashionlista, Pinterest e Instagram hacen esto bien. Aquí hay un ejemplo de Instagram para mostrar lo que estoy tratando de lograr:

En el ejemplo anterior, puedes ver el siguiente feed y a lovetoronto le han gustado 5 fotos. Comencé a jugar con el siguiente feed de Instagram para ver cómo funciona. La siguiente fuente de Instagram muestra un máximo de 35 entradas de actividad y cada entrada puede tener un máximo de 5 actividades de ese tipo de acción. "lovetoronto likes 5 photos" es una entrada de actividad y muestra las 5 últimas fotos que le gustaron. Desde que lovetoronto realizó la última acción, él está en la cima.

Me gustaría lograr la misma configuración.

Aquí está mi configuración de modelo actual:

modelos.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)

Cada vez que se crea un objeto ''Me gusta'', también creo un objeto de Actividad, siendo el actor la persona que realizó la acción, el receptor la persona a la que se realizó la acción, la acción (en este caso, una cadena, '' me gustó ''), la publicación (la foto) y la hora de creación del objeto de actividad.

Uso django-tastypie para obtener y crear objetos ''Me gusta'' y ''Actividad''.

api.py

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

¿Cómo puedo modificar el recurso FollowingFeed de tal manera que agregue los objetos de actividad? Me encontré con el proyecto Feedly . ¿Cómo puedo usarlo con mi configuración actual?


En su recurso de alimentación, ya está anulando get_object_list, sugeriría cambiar la lógica para realizar una consulta sin formato para la lógica de agregación.

def get_object_list(self, request): query = "Your aggregation query logic here" feed_model = self._meta.object_class return feed_model.objects.raw(query)

Esto debería hacer lo que se requiere. Sin embargo, debe pensar en su lógica de consulta. Déjame saber si te enfrentas a cualquier otro problema.

¡Gracias!


Establezca el tiempo de agregación, por ejemplo, ¿desea agregar todos los "me gusta" dentro de un período de 10 minutos o durante las últimas 24 horas?

Entonces puedes filtrar tu objeto por este período de tiempo.

Luego puede aplicar la agrupación utilizando el método .values ​​(''model__field''). Django genera sql que contiene ''GROUP BY''

Y finalmente, agregue un límite de agregación para que cuando la cantidad de "me gusta" supere este límite, se muestre la vista agregada en lugar de la vista de actividad única.

Ejemplo abajo (pseudo, no real):

if (activity.object.filter(time__gt=yourlowertime, time__lt=youruppertime).values(‘activity__action'').count() > aggregation_limit) : # show aggregated view else: # show normal view


No creo que quieras hacer una agregación de nivel de base de datos, porque presumiblemente quieres mostrar los detalles individuales así como los conteos, por ejemplo, "X como 5 fotos" y mostrar las 5 fotos. La agregación, por definición, excluirá los datos individuales.

En su lugar, deberías agrupar y ordenar en código Python (o Javascript, ya que creo que estás usando una API HTTP, pero preferiría una API del lado del servidor que ya tuviera las cosas organizadas).

itertools.groupby podría ayudar. Creo que necesitas agrupar por (usuario y acción), y luego ordenar por la marca de tiempo del primer elemento en cada grupo, para que puedas ver "Joe le gustaron 5 fotos", "Anne publicó 2 fotos", "Joe publicó un foto "," a Claire le gustaron 3 fotos "etc.