Я не могу сохранить 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, как вы сделали, более понятно и просто, когда у вас есть дополнительные поля в промежуточной таблице.

Вернуться на верх