Данные списка Django из разных моделей в режиме просмотра списка с правильным упорядочением - PullRequest
0 голосов
/ 20 марта 2019

Привет, ребята. Я делаю проект Django, который является простым клоном Twitter. Получил идею из курса Udemy Джастина Митчелла.
Итак, я реализовал модель Tweet и модель Retweet, которая имеет ForeignKey для исходного Tweet и пользователя.
Дело в том, что на главной странице я хочу, чтобы и твиты, и ретвиты показывались, и в порядке их создания ..
Я использую Django Rest Framework для функциональности CRUD Tweet, используя ModelViewSet
Любая идея о том, как мне добиться этого с помощью 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 голосов
/ 20 марта 2019

Поскольку данные 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 и Retweet представления и сериализаторы для создания и обновления.

...