Почему можно создать модель с полем 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 и Tags.

По сути, это означает, что ManyToManyField имеет дело с дополнительной моделью. Вы даже можете работать с этой моделью напрямую. Действительно, если у вас есть модель:

class Tag(models.Model):
    pass


class Post(models.Model):
    tags = models.ManyToManyField(Tag)

Вы можете получить эту модель как:

Post.tags.through

и, например, удалите все связи между всеми Posts и всеми Tags с помощью:

Post.tags.through.objects.all().delete()
Вернуться на верх