J'ai une application pour laquelle je souhaite créer un flux "Activité récente" / Firehose de 2 ou 3 types d'activités combinées telles que des publications, des commentaires et des articles similaires, et autre chose + peut-être plus tard. Je suppose que cela se fait avec une requête consistant à prendre le dernier objet approprié ajouté à la base de données et à le combiner avec le dernier de l'autre type d'objet et à ordonner la nouvelle liste combinée d'objets par leurs horodatages. Quelle est la meilleure façon de faire quelque chose comme ça? Pour l'instant, j'ai quelque chose comme ça à chaque fois que quelqu'un actualise la page:

NewPost.objects.all().order_by('-postdate')[0:10] #takes the last 16 recently added posts
Comment.objects.all().order_by('-commentdate')[0:10] #takes equal number of comments site wide ordered by timestamp

Alors, quelle est la meilleure façon de prendre ces deux ensembles de requêtes et de rendre les différents modèles dans une liste triée par leur horodatage? Je suppose que le type de logique sera le même pour l'ajout de types d'objets supplémentaires, donc je veux juste savoir comment le faire avec seulement 2. Merci!

1
EazyC 13 juil. 2015 à 09:02

2 réponses

Meilleure réponse

Je n'aime pas vraiment votre approche car lorsque vous voulez mettre un autre objet sur le tuyau d'incendie, vous devez ajouter une troisième ligne (AnotherObject.objects.all ... etc) à tous les endroits où vous besoin d'afficher ce firehose!

Pour moi, la meilleure façon de faire est de créer un modèle Firehose avec des champs comme: date, action (ajouter / supprimer / mettre à jour, etc.) et object (a clé étrangère générique de l'objet qui a été modifié). Désormais, chaque fois que vous apportez une modification à un objet que vous souhaitez ajouter au Firehose, vous ajoutez une nouvelle instance de FirehoseClass avec les valeurs de champ correctes. Enfin, chaque fois que vous souhaitez afficher le Firehose, vous n'afficherez que tous les objets Firehose.

1
Serafeim 13 juil. 2015 à 06:24

Pour combiner les listes, vous pouvez utiliser créer une liste en utilisant chain () depuis itertools , puis les trier en utilisant sorted () :

from itertools import chain
combined_lists = list(chain(new_post_list, comment_list))
sorted_combinened_list = sorted(combined_list, key=lambda instance: instance.postdate)

Cependant, comme vous le voyez, le tri se fait uniquement à l'aide d'une seule clé. Je ne connais aucune méthode pour utiliser deux clés différentes lors du tri. Vous pouvez résoudre ce problème en ajoutant simplement une propriété à la classe Comment , nommée postdate qui renvoie simplement commentdate . Ou, mieux encore, vous devriez utiliser le même nom pour l'heure de création pour tous vos modèles, par exemple created_at .

Cela a été répondu plus tôt et plus en détail ici: Comment combiner 2 ensembles de requêtes ou plus dans une vue Django?

1
Community 23 mai 2017 à 12:30