Показывайте разные страницы в зависимости от пользователя - django

Я создаю веб-приложение, подобное IMDB. Каждый (зарегистрированный) пользователь просматривает одну и ту же домашнюю страницу, но он может отметить/отметить каждый фильм, который он хочет сохранить в "списке просмотренных". Я сделал это, но заметил, что каждый зарегистрированный пользователь может просматривать фильмы, отмеченные другим пользователем. Конечно, это проблема, поэтому я хотел бы создать страницу относительно каждого пользователя, чтобы у каждого была своя страница "просмотренных фильмов", основанная на фильмах, отмеченных как просмотренные. Основная идея заключается в том, что каждый раз, когда пользователь добавляет фильм в базу данных, он может отметить его как просмотренный с помощью простого models.BooleanField в модели фильма. Затем у меня есть еще одна модель "Seen", где находятся все фильмы, отмеченные как просмотренные.

models.py

class Films(models.Model):
    ...
    seen = models.BooleanField(default=False)
class Seen(models.Model):
    ...

views.py

    films = Films.objects.all()
    for film in films:
    flag = 0
    seen_films = Seen.objects.all()
    for _ in seen_films:
        if film.name == _.name:
            flag = 1
            break
    if not flag and film.seen:
        act_seen = Seen(image=film.image, name=film.name, description=film.description)
        act_seen.save()

Нужно добавить, что для пользователя я использую класс по умолчанию, предоставляемый django:

from django.contrib.auth.models import User

Я понял, что ошибка в том, что каждый может отметить/отметить фильм и поэтому каждый может видеть фильмы других пользователей, но я понятия не имею, как это исправить. Также я думаю, что код в views.py очень сырой, но это был скорее тест, чем конечный продукт. Спасибо!

Вы можете расширить стандартный класс User (проверьте документацию, есть несколько способов сделать это, и тот, который использую я, может не быть лучшим для вас) и использовать много-ко-многим для сохранения всех фильмов, которые пользователь видел:

# models.py
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    films_seen = models.ManyToManyField(Films, related_name='seen_by')

Тогда вы можете использовать ListAPIView и переопределить метод get_queryset():

# views.py
from rest_framework.generics import ListAPIView

class FilmsSeenList(ListAPIView):
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        return self.request.user.profile.films_seen.all()

Обратите внимание, что вы должны быть уверены, что каждый пользователь имеет связанный профиль (например, с сигналом docs here), иначе get_queryset() вызовет ошибку Profile.DoesNotExist:

# handlers.py
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver

from accounts.models import Profile  # Define where your Profile model is here

User = get_user_model()


@receiver(post_save, sender=User, dispatch_uid="create_profile")
def post_save_user(sender, instance, created, **kwargs):
    # Making sure that a profile is assigned for new users
    if created:
        Profile.objects.create(user=instance)

Вы также можете реализовать представление, возвращающее все фильмы и флаг, чтобы узнать, видел ли пользователь фильм:

# views.py
from rest_framework.generics import ListAPIView

class AllFilmsList(ListAPIView):
    permission_classes = (IsAuthenticated,)
    serializer_class = FilmsSeenFlagSerializer

    def get_queryset(self):
        return Films.objects.all()


# serializers.py
class FilmsSeenFlagSerializer(serializers.ModelSerializer):
    seen = serializers.SerializerMethodField()

    def get_seen(self, instance):
        return instance.seen_by.filter(pk=self.context['request'].user.pk).exists()

    class Meta:
        model = Films
        fields = [..., 'seen']
Вернуться на верх