Este problema aparentemente inocuo resultó ser bastante difícil de encontrar información. Solo quiero disminuir el valor de una columna Integerfield en 1 en mi base de datos, llamando a una función.
llamada a la función views.py
StudentProfile.objects.add_lesson(student_id)
managers.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)
Modelo completo de perfil del alumno
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)
Sé que esto está totalmente mal, cualquier ayuda es apreciada.
3 respuestas
Intenté usar la expresión F, y no tengo idea de por qué, pero disminuyó en 3 en lugar de en 1. Quizás Django ejecuta ese código 3 veces cuando se invoca en la vista. Encontré una solución que logra esto sin una función, en la vista, hace exactamente lo que espero, una disminución de 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()
Si desea mantener su configuración actual y poder add_lesson()
para disminuir "resto_lessons", el cambio más pequeño que puede hacer para lograrlo es mediante la expresión 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)
Ref: https://docs.djangoproject.com/en/3.0/ref / modelos / expresiones /
Aunque personalmente creo que si su objetivo es tener un método que disminuya "resto_lessons" en 1, probablemente debería convertirlo en un método modelo. Me gusta esto:
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()
Espero que esto ayude.
Django proporciona expresiones F para exactamente el tipo de tarea que tienes. Realiza la actualización en relación con el valor del campo original en la base de datos.
Debería cambiar sus managers.py de la siguiente manera (más las declaraciones 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)
Podría ir aún más lejos, y por el enfoque DRY, use QuerySet.as_manager()
para crear una instancia de Manager con una copia de los métodos de QuerySet personalizados en lugar de repetir el método dos veces en su Manager y QuerySet personalizados. P.ej.:
class StudentProfile(models.Model):
...
objects = StudentQuerySet().as_manager()
¡Espero que ayude!
Preguntas relacionadas
Nuevas preguntas
django
Django es un marco de aplicación web del lado del servidor de código abierto escrito en Python. Está diseñado para reducir el esfuerzo requerido para crear sitios web y aplicaciones web complejos basados en datos, con un enfoque especial en menos código, sin redundancia y siendo más explícito que implícito.