Почему можно создать модель с полем ManyToManyField без указания значения для поля ManyToManyField?
Поскольку
каждое поле в модели django является обязательным. Как же при создании объекта модели, имеющей поле с отношением "многие-ко-многим" к другой модели. Мы можем создать этот объект модели, не указывая значение поля многие-ко-многим ?Я говорю о том, когда пишу запрос типа ModelName.objects.create(), а не о работе с формами или modelforms.
Поскольку каждое поле в модели Django является обязательным.
I reject this premise. Not every field is required. A field with blank=True
[Django-doc] means you don't have to write a value in the form. But even if blank=False
, this applies to model forms, serializers, model admin, not the model layer itself. For a BooleanField
model field [Django-doc] this is by default not the case, since that would require that you always check the checkbox (which is what required=True
means for a BooleanField
form field [Django-doc]). This is indeed implemented like [GitHub]:
class BooleanField(Field): # … def formfield(self, **kwargs): if self.choices is not None: include_blank = not (self.has_default() or 'initial' in kwargs) defaults = {'choices': self.get_choices(include_blank=include_blank)} else: form_class = ( forms.NullBooleanField if self.null else forms.BooleanField ) # In HTML checkboxes, 'required' means "must be checked" which is # different from the choices case ("must select some value"). # required=False allows unchecked checkboxes. defaults = {'form_class': form_class, 'required': False} return super().formfield(**{**defaults, **kwargs})
Для ManyToManyField
сделать его обязательным означает, что вы должны выбрать как минимум один элемент. Но это часто не то, что подразумевается: ManyToManyField
означает, что элемент может указывать на ноль, один или больше элементов. Он также не устанавливает что-то в NULL
в случае отсутствия элементов, NULL
и пустая коллекция - это две разные вещи.
Что еще более важно для слоя модели, вы не можете легко предоставить значение для него. Это результат того, как Django реализует поля "многие-ко-многим": с помощью таблицы-перехода . Таким образом, она создает дополнительную таблицу с ForeignKey
для первой и второй модели. Это означает, что она может заполнить таблицу перекрестка только после того, как будет создана первая запись. Эта логика заключена в ModelForm
, который выполняет и модель, и ее ManyToManyField
, и таким образом в случае создания сначала создает запись, а затем сохраняет записи в таблице стыковки; или в случае обновления обновляет не только запись Post
, но и таблицу стыковки между Post
и Tag
s.
По сути, это означает, что ManyToManyField
имеет дело с дополнительной моделью. Вы даже можете работать с этой моделью напрямую. Действительно, если у вас есть модель:
class Tag(models.Model):
pass
class Post(models.Model):
tags = models.ManyToManyField(Tag)
Вы можете получить эту модель как:
Post.tags.through
и, например, удалите все связи между всеми Post
s и всеми Tag
s с помощью:
Post.tags.through.objects.all().delete()