Как изменить значение поля в модели только для текущего пользователя?

У меня есть поле «прогресс» на уровне

class Level(models.Model):
    level = models.CharField(max_length=50, unique=True)
    helper = models.TextField(null=True, blank=True)
    progress = models.IntegerField(default=0)

Мне нужно добавить 1 к «прогрессу». Все, что мне нужно, это хранить другое значение для каждого пользователя. Я действительно не могу понять, как это уладить. Теперь у меня есть класс LevelProgress в views.py, который добавляет 1 к области прогресса, но он добавляет 1 глобально.

class LevelProgress(APIView):

    def get(self, request, id):
        queryset_ = Level.objects.get(pk=id)
        queryset_.progress += 1
        queryset_.save()
        serializer = LevelFullSerializer(queryset_)
        return Response(serializer.data)

Как добавить 1 для текущего пользователя?

Всего 2 ответа


Ну, моделирование неверно. Вы не можете сохранить прогресс на этом объекте Level , вам нужно добавить дополнительную модель, например UserLevel с ForeignKey s для User и Level , и UserLevel ForeignKey :

from django.conf import settings

class Level(models.Model):
    level = models.CharField(max_length=50, unique=True)
    helper = models.TextField(null=True, blank=True)

class UserLevel(models.Model):
    level = models.ForeignKey(Level, on_delete=models.CASCADE)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )
    progress = models.IntegerField(default=0)

Итак, теперь мы создаем для User определенный объект UserLevel , и мы можем обновить этот прогресс. Мы можем даже сделать это с помощью одной функции update_or_create(..) :

class LevelProgress(APIView):

    def get(self, request, id):
        ul, created = UserLevel.objects.get_or_create(
           level_id=id,
           user_id=request.user.pk
           defaults={'progress': 1}
        )
        if not created:
            ul.progress += 1
            ul.save()
        serializer = LevelFullSerializer(ul.level)
        return Response(serializer.data)

Вы также можете изменить LevelFullSerializer для сериализации прогресса этого пользователя.

При этом запрос GET с «побочными эффектами» на самом деле не разрешен в соответствии с рекомендациями HTTP. Обычно один из них меняет объекты в базе данных с запросами POST, PUT, PATCH и т. Д.


Вы можете добавить поле OneToOneField к модели Level следующим образом:

from django.conf import settings

class Level(models.Model):
    level = models.CharField(max_length=50, unique=True)
    helper = models.TextField(null=True, blank=True)
    progress = models.IntegerField(default=0)
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

Теперь, на ваш взгляд, вы можете получить уровень для текущего пользователя:

class LevelProgress(APIView):

    def get(self, request, id):
        queryset_ = Level.objects.get(user=request.user)
        queryset_.progress += 1
        queryset_.save()
        serializer = LevelFullSerializer(queryset_)
        return Response(serializer.data)

Есть идеи?

10000