Django: Как обновить поле Integer и уменьшить его значение - PullRequest
0 голосов
/ 28 апреля 2020

Эта, казалось бы, безобидная проблема оказалась довольно трудной для поиска какой-либо информации. Я просто хочу уменьшить значение столбца Integerfield на 1 в моей базе данных, вызвав функцию.

вызов функции views.py

StudentProfile.objects.add_lesson(student_id)

Manager.py

class StudentQuerySet(models.QuerySet):

    def add_lesson(self, sid):          
        self.filter(student_id=sid).update(remaining_lessons=remaining - 1)

class StudentProfileManager(models.Manager):
    def add_lesson(self, sid):
        self.get_queryset().add_lesson(sid)

Полная модель StudentProfile

class StudentProfile(models.Model):
    student = models.OneToOneField(
        User, related_name='student', primary_key=True, parent_link=True, on_delete=models.CASCADE)
    portrait = models.ImageField(
        upload_to='studentphotos', verbose_name=_('Student Photo'))
    about_me = models.TextField(verbose_name=_("About Me"))
    spoken_languages = models.CharField(max_length=255)
    teacher_default = models.OneToOneField(
        'teachers.TeacherProfile', related_name='teacher_default', parent_link=True, 
on_delete=models.CASCADE, default=None, blank=True, null=True)
    membership_start = models.DateTimeField(
        verbose_name="Membership Start Date", default=now, editable=False)
    membership_end = models.DateTimeField(
        verbose_name="Membership End Date", default=now, editable=False)
    remaining_lessons = models.IntegerField(
        verbose_name="Membership remaining lessons", default=0)

    objects = StudentProfileManager()

    def __str__(self):
        return User.objects.get_student_name(self.student_id)

Я знаю, что это совершенно неправильно, любая помощь приветствуется.

Ответы [ 3 ]

0 голосов
/ 28 апреля 2020

Django предоставляет F выражений именно для того типа задач, которые у вас есть. Обновление выполняется относительно исходного значения поля в базе данных.

Вам необходимо изменить Manager.py следующим образом (плюс операторы return :))

from django.db.models import F

class StudentQuerySet(models.QuerySet):
    def add_lesson(self, sid):
        return self.filter(student_id=sid).update(remaining_lessons=F('remaining_lessons')-1)


class StudentProfileManager(models.Manager):
    def add_lesson(self, sid):
        return self.get_queryset().add_lesson(sid)

Вы можете go еще дальше, и ради DRY подхода используйте QuerySet.as_manager(), чтобы создать экземпляр Manager с копией пользовательских методов QuerySet вместо повторив метод дважды в вашем пользовательском менеджере и QuerySet. Например:

class StudentProfile(models.Model):
    ...
    objects = StudentQuerySet().as_manager()

Надеюсь, это поможет!

0 голосов
/ 28 апреля 2020

Я пытался использовать выражение F, и я понятия не имею, почему, но оно уменьшалось на 3, а не на 1. Возможно, Django запускает этот код 3 раза, когда он вызывается в представлении. Я нашел решение, которое выполняет это без функции, по мнению, он делает именно то, что я ожидаю, с уменьшением 1:

student_id = request.user.id
student_queryset = StudentProfile.objects.get(student_id=student_id)
student_queryset.remaining_lessons = student_queryset.remaining_lessons - 1
student_queryset.save()
0 голосов
/ 28 апреля 2020

Если вы хотите сохранить текущие настройки и иметь возможность add_lesson() для уменьшения «оставшихся_уроков», наименьшее изменение, которое вы можете сделать, чтобы достичь его, это использовать выражение F ():

from django.db.models import F

class StudentQuerySet(models.QuerySet):
    def add_lesson(self, sid):
        self.filter(student_id=sid).update(remaining_lessons=F('remaining_lessons') - 1)

Ссылка: https://docs.djangoproject.com/en/3.0/ref/models/expressions/

Хотя я лично считаю, что если ваша цель состоит только в том, чтобы иметь метод, который уменьшает значение «Остаток_счет» на 1, вам, вероятно, следует просто сделать его методом модели. Вот так:

class StudentProfile(models.Model):
    # ... your model field ...

    def add_lesson(self):
        self.remaining_lesson -= 1
        self.save()

# and in your Views.py
StudentProfile.objects.get(student_id=sid).add_lesson()

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...