Django以正确的顺序在列表视图中列出来自不同模型的数据

时间:2019-03-20 10:53:35

标签: django django-models django-rest-framework django-templates django-views

嗨,大家好。我正在制作一个Django项目,它是Twitter的简单克隆版本。 因此,我实现了一个Tweet模型和一个Retweet模型,该模型具有原始Tweet和用户的ForeignKey。.
事实是,我希望在主页中同时显示推文和转发,并按创建顺序显示它们。.
我正在使用ModelViewSet
将Django Rest Framework用于Tweet的CRUD功能。 关于如何使用Rest Framework实现此目标的任何想法,或者如果无法实现,请给我一些其他想法。
谢谢你。

models.py

class Tweet(models.Model):
   content = models.CharField(max_length=140)
   user = models.ForeignKey(User, on_delete=models.CASCADE)
   created_on = models.DateTimeField(auto_now_add=True)
   updated_on = models.DateTimeField(auto_now=True)

   class Meta:
       ordering = "-created_on", "content", "user",

   def __str__(self):
       return self.content

   def get_absolute_url(self):
       return reverse("tweet_api:tweet-detail", args=[self.id])


class Retweet(models.Model):
    tweet = models.ForeignKey(Tweet, on_delete=models.CASCADE, related_name="retweet")
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = "-created_on", "user",

    def __str__(self):
        return self.tweet.content

serializers.py

class TweetSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    created_on = serializers.SerializerMethodField()
    date_display = serializers.SerializerMethodField()

    class Meta:
        model = models.Tweet
        fields = "id", "content", "created_on", "date_display", "user",

    def get_created_on(self, obj):
        return obj.created_on.strftime("%I:%M %p - %d %b %Y")

    def get_date_display(self, obj):
        obj_date = obj.created_on
        days = (timezone.datetime.now() - obj_date).days
        if days > 0:
            return obj_date.strftime("%d %b")
        else:
            return naturaltime(obj_date)

class RetweetSerializer(serializers.ModelSerializer):
    tweet = TweetSerializer()
    user = UserSerializer(read_only=True)
    date_display = serializers.SerializerMethodField()

    class Meta:
        model = models.Retweet
        fields = "id", "tweet", "user", "created_on", "date_display",

    def get_date_display(self, obj):
        obj_date = obj.created_on
        days = (timezone.datetime.now() - obj_date).days
        if days > 0:
            return obj_date.strftime("%d %b")
        else:
            return naturaltime(obj_date)

views.py

class TweetViewSet(ModelViewSet):
    serializer_class = serializers.TweetSerializer
    queryset = models.Tweet.objects.all()
    pagination_class = DefaultPagination
    filter_backends = filters.SearchFilter,
    search_fields = "content", "user__username", "user__first_name", "user__last_name",

    def perform_create(self, serialiazer):
        return serialiazer.save(user=self.request.user)


class RetweetViewSet(ModelViewSet):
    serializer_class = serializers.RetweetSerializer
    queryset = models.Retweet.objects.all()
    pagination_class = DefaultPagination
    filter_backends = filters.SearchFilter,
    search_fields = "tweet__content", "user__username", "user__first_name", "

1 个答案:

答案 0 :(得分:0)

由于Tweet和Retweet数据驻留在完全不同的模型上,因此要使用当前模型结构进行操作并不容易。要将它们组合到一个视图中,您需要重写ViewSet上的许多内容,并执行诸如在内存中排序这样的操作,这些操作不可伸缩。一种可能的解决方案是使用模型继承,为Tweet和Retweet建立一个基本模型,并在该模型上构建您的serialzier和视图集。可以使用类似以下的模型结构:

class Post(models.Model):
    """
    Base model for user posts
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

class Tweet(Post):
    content = models.CharField(max_length=140)
    updated_on = models.DateTimeField(auto_now=True)

class Retweet(Post):
    tweet = models.ForeignKey(Tweet, on_delete=models.CASCADE, related_name="retweet")

使用这些模型后,您可以创建 PostSerializer PostViewSet ,并将它们仅用于列出帖子,您可以继续使用 Tweet 转推视图和序列化程序,用于创建和更新。