Quantcast
Channel: Active questions tagged feed - Stack Overflow
Viewing all articles
Browse latest Browse all 547

Django: making an evenly distributed mixed item feed

$
0
0

Let's say I want to generate a feed consisting of ItemA and ItemB, each item has a "published_date" field and newer items should appear at the top of the feed. However I want to further ensure that the feed always has 2 of ItemA, followed by 1 of ItemA, followed by 2 of ItemA,....regardless of the absolute publish date (i.e. even if the 10 most recent published items were all A, I'd still see B as the third item if there is an instance of it).

How can I achieve something like this in Django?

I was originally doing this something like

# models.pyclass FeedItem(models.Model):    id = HashidAutoField(primary_key=True, min_length=8, alphabet="0123456789abcdefghijklmnopqrstuvwxyz")    created = models.DateTimeField(auto_now_add=True)    updated = models.DateTimeField(auto_now=True, db_index=True)    # When is this scheduled to be published    publish_date = models.DateTimeField(db_index=True)    # Type of Feed Item    ITEM_TYPES = Choices((1, 'A', 'ItemA'),                         (2, 'B', 'ItemB'))    # item_type    item_type = models.PositiveSmallIntegerField(db_index=True, choices=ITEM_TYPES)    def save(self, force_insert=False, force_update=False, using=None, update_fields=None, **kwargs):"""        Ensure that when we save each subclass then we get the correct item_type        :param force_insert:        :param force_update:        :param using:        :param update_fields:        :param kwargs:        :return:"""        if (self.__class__.__name__ == 'FeedItemA'           and self.item_type != self.ITEM_TYPES._identifier_map['A']):            self.item_type = self.ITEM_TYPES._identifier_map['A']        elif (self.__class__.__name__ == 'FeedItemB'              and self.item_type != self.ITEM_TYPES._identifier_map['B']):            self.item_type = self.ITEM_TYPES._identifier_map['B']    class Meta:        ordering = ['-publish_date', ]class FeedItemA(FeedItem):    ...class FeedItemB(FeedItem):    ...

Then a view like

# views.pyclass FeedItemViewSet(viewsets.ReadOnlyModelViewSet):    queryset = FeedItem.objects.all()    permission_classes = ()    serialization_info = {'ItemA': FeedSerializationInfo(FeedItemASerializer, 'a', 'artworkfeeditema'),'ItemB': FeedSerializationInfo(FeedItemBSerializer, 'b', 'blogpostfeeditemb'),    }    filter_backends = (filters.DjangoFilterBackend, rest_filters.OrderingFilter)    ordering_fields = ['publish_date', 'updated']    def list(self, request, *args, **kwargs):        queryset = self.filter_queryset(self.get_queryset())        page = self.paginate_queryset(queryset)        data = []        for item in page:            info = self.serialization_info[item.get_item_type_display()]            related_item = getattr(item, info.related_name)            data.append(info.serializer_class(related_item, context={'request': request}).data)        return self.get_paginated_response(data)

This achieves the mixing of the 2 different types, but their order will be solely determined by the publish_date and we don't get the even mixing of 2 of A, 1 of B etc...

Maybe there is some way to generate a new queryset by popping 2 from the ordered list of A, then 1 from B and so on until both lists are exhausted? then use that queryset for the list viewset?


Viewing all articles
Browse latest Browse all 547

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>