Модельки и формы в django
Учу джанго и вопрос у меня в принципе простой, но нагуглить ответ у меня не получилось. В чем дело: У меня есть model класса календарь:
class Calendar(models.Model):
name = models.CharField(max_length=63, name="name", help_text="Название")
description = models.TextField(max_length=255, name="description", help_text="Описание")
creator = models.CharField(max_length=63, name='author', help_text='Автор')
path = models.CharField(max_length=63, name='path', help_text='Путь по которому получают этот календарь',
unique=True)
Мне нужно создавать объекты этого класса и записывать в бд. Все поля кроме пути получать из формы а path генерировать случайно.
Ответы (3 шт):
Очевидное решение с наследованием и перегрузкой __init__ является неверным!!!
class Calendar(models.Model):
def __init__(self, *args, **kwargs):
super(Calendar, self).__init__(*args, **kwargs)
self.path = self.generate_path()
def generate_path(self) -> str:
return str(randint(10 ** 6, 9 * 10 ** 6))
name = models.CharField(max_length=63, name="name", help_text="Название")
description = models.TextField(max_length=255, name="description", help_text="Описание")
creator = models.CharField(max_length=63, name='author', help_text='Автор')
path = models.CharField(max_length=63, name='path', help_text='Путь по которому получают этот календарь',
unique=True)
def __str__(self):
return f"{self.name} {self.description[:25]}"
Так как каждый раз при выгрузке из бд в память будет создаваться instance этого класса и path будет меняться. (наглядно видно при обновление страницы в админке, каждый раз новый path)
Решение вот такое (файл views.py)
if request.method == "POST":
form = NewCalendarForm(request.POST)
form.instance.path = Calendar.generate_path() // Тут генерируем путь
if form.is_valid():
form.save()
__ models.py __
class Calendar(models.Model):
def __init__(self, *args, **kwargs):
super(Calendar, self).__init__(*args, **kwargs)
@staticmethod
def generate_path() -> str:
return str(randint(10 ** 6, 9 * 10 ** 6))
Не согласен с ответом @BlueScreen. Используйте вариант с переопределением __init__ метода:
class Calendar(models.Model):
# ... Ваши поля
def __init__(self, name, description, creator, path=None):
self.name = name
self.description = description
self.creator = creator
if path:
self.path = path
else:
self.path = generate_random_path()
generate_random_path - ваша функция, которая будет генерировать рандомный path. При загрузке из базы в self.path будет попадать значение из базы, иначе генерироваться случайное. Для надёжности можете добавить NOT NULL правило в БД для поля
Не согласен с другими ответами )))
Юзайте save или pre_save.
# model.save()
def save(self, *args, **kwargs):
if not self.path:
self.path = generate_path
return super().save(*args, **kwargs)
# receiver
@receiver(pre_save, sender=Calendar, dispatch_uid='calendar.pre_save_gen_path')
def pre_save_gen_path(sender, instance, **kwargs):
if not instance.path:
instance.path = instance.generate_path()
Если поле можно будет менять, то в форме в методе get_object если новый объект - вызывайте сигнал.
В общем, сигнал - более гибкое решение и эта логика будет располагаться рядом с моделью.
Вариант с save менее гибкий, вам придется убирать поле из формы, если поле обязательное.