Я не могу сохранить Many to Many с помощью модели, используя ModelMultipleChoiceField
Я застрял, пытаясь сохранить отношения "многие ко многим" через пользовательскую модель, используя ModelMultipleChoiceField. Django показывает эту ошибку: Cannot assign "<QuerySet [<Project: MARKETING 7>]>": "ProjectEmployee.project" must be a "Project" instance.
Я не могу найти решение для этого.
models.py
class Department(models.Model):
name = models.CharField('Name', max_length=200, unique=True)
class Employee(models.Model):
department = models.ManyToManyField(Department, through='DepartmentEmployee')
name = models.CharField('Name', max_length=200, unique=True)
lastname = models.CharField('Last Name', max_length=200, unique=True)
class DepartmentEmployee(models.Model):
department = models.ForeignKey(Department, on_delete=models.PROTECT)
employee = models.ForeignKey(Employee, on_delete=models.PROTECT)
date_joined = models.DateField()
forms.py
class ProjectEmployeeForm(forms.ModelForm):
project = forms.ModelMultipleChoiceField(
required=True,
queryset=Project.objects.all(),
)
class Meta:
model = ProjectEmployee
fields = '__all__'
views.py
def project_employee(request, id):
employee = get_object_or_404(Employee, id = id)
if request.method == 'POST':
form = ProjectEmployeeForm(
request.POST or None,
)
if form.is_valid():
f = form.save(commit=False)
f.employee = employee
f.save()
redirect('employe:list')
else:
form = ProjectEmployeeForm()
template = 'prject_employee.html'
context = {
'form': form,
}
return render(request, template, context)
urls.py
path('<int:id>/project_employee/', project_employee, name='project_employee'),
Как гласит ошибка, вы пытаетесь присвоить значение типа <QuerySet [<Project>]>
значению, ожидающему тип Project
.
Где бы вы ни устанавливали значение, вы, похоже, используете результаты запроса, который может вернуть или не вернуть несколько ответов.
Может быть, вместо использования all()
есть возможность возвращать один объект Project
.
Когда вы устанавливаете отношения "многие ко многим", например, сотрудники и проекты, база данных не может хранить одну запись с несколькими сотрудниками или несколькими проектами. Она должна использовать промежуточную таблицу, также известную как объединенная таблица или сквозная таблица. В промежуточной таблице хранится одно отношение за раз (один сотрудник и один проект).
Поэтому, когда вы задаете ProjectEmployeeForm
, он ожидает, что вы выберете один project
, выберете один employee
и введете date_joined
. Полем формы по умолчанию для ForeignKey
является ModelChoiceField
, которое позволяет выбрать один объект. Если переопределить его на ModelMultipleChoiceField
, виджет обработает ввод и позволит вам выбрать любое количество объектов, но при отправке формы, как вы обнаружили, у него нет способа сохранить несколько объектов в одном поле внешнего ключа. Чтобы использовать форму, вам нужно использовать виджеты по умолчанию ModelChoiceField
и отправить форму снова для каждой пары проект-сотрудник, которую вам нужно ввести.
Альтернативой является использование EmployeeForm
. В нем, конечно же, будет ManyToManyField
для проектов. Django ожидает использовать для этого ModelMultipleChoiceField
и будет знать, как сохранить соответствующие значения в промежуточной таблице ProjectEmployee
за кулисами. Недостатком является то, что стандартный EmployeeForm
не будет знать о поле date_joined
, и вам потребуется дополнительный код для его обработки. Я лично думаю, что использование ProjectEmployeeForm
, как вы сделали, более понятно и просто, когда у вас есть дополнительные поля в промежуточной таблице.