Прямое присваивание прямой стороне множества «многие ко многим» запрещено. Вместо этого используйте emails_for_help.set()

Я новичок в Django и не нашел ссылок по этой проблеме. Я получаю эту ошибку, когда использую поле «многие ко многим» в модели Django (models.py). Я предполагаю, что проблема заключается в назначении поля m2m в представлении (views.py) из формы (forms.py).

Как назначить поле m2m в поле зрения? (Django version 2.0, python - 3.5)

models.py

class User(AbstractUser):
 username=models.CharField(max_length=20)
 email = models.EmailField(_('email address'), unique=True)


class Setupuser(models.Model):
 organization=models.CharField(max_length=200,blank=False,null=True)
 emails_for_help = models.ManyToManyField(User)

views.py

class Set_user(FormView):
 template_name="pkm_templates/set_up_user.html"
 form_class = Set_User_Form
 success_url = '/thanks/'

 def form_valid(self, form):
    org = form.cleaned_data.get('organization')
    emails = form.cleaned_data.get("emails_for_help")
    instance = Setupuser(organization=org,emails_for_help=emails)
    instance.save()
    return redirect("/")

forms.py

class Set_User_Form(ModelForm):
  emails_for_help = forms.ModelMultipleChoiceField(
    queryset=User.objects.all(),
    widget=forms.CheckboxSelectMultiple
  )

  class Meta:
    model = Setupuser
    fields = ["organization","emails_for_help"]

person conf    schedule 25.04.2018    source источник


Ответы (4)


Вам нужно получить объект User, а затем добавить его в поле emails_for_help. Вы не можете добавить объект в ManyToManyField при создании экземпляра. Ознакомьтесь с документом.

class Set_user(FormView):
    template_name="pkm_templates/set_up_user.html"
    form_class = Set_User_Form
    success_url = '/thanks/'

    def form_valid(self, form):
        org = form.cleaned_data.get('organization')
        emails = form.cleaned_data.get("share_email_with")

        users = User.objects.filter(email__in=emails)
        instance = Setupuser.objects.create(organization=org)

        for user in users:
            instance.emails_for_help.add(user)

        return redirect("/")

ИЗМЕНИТЬ

Другой способ сделать это — использовать .set().

class Set_user(FormView):
    template_name="pkm_templates/set_up_user.html"
    form_class = Set_User_Form
    success_url = '/thanks/'

    def form_valid(self, form):
        org = form.cleaned_data.get('organization')
        emails = form.cleaned_data.get("share_email_with")

        users = User.objects.filter(email__in=emails)
        instance = Setupuser.objects.create(organization=org)

        instance.emails_for_help.set(users)

        return redirect("/")

Или вы можете просто использовать .add() для добавления произвольного количества объектов.

class Set_user(FormView):
    template_name="pkm_templates/set_up_user.html"
    form_class = Set_User_Form
    success_url = '/thanks/'

    def form_valid(self, form):
        org = form.cleaned_data.get('organization')
        emails = form.cleaned_data.get("share_email_with")

        users = User.objects.filter(email__in=emails)
        instance = Setupuser.objects.create(organization=org)

        instance.emails_for_help.add(*users)

        return redirect("/")
person MD. Khairul Basar    schedule 25.04.2018
comment
У меня есть исключение: значение QuerySet для точного поиска должно быть ограничено одним результатом с использованием нарезки. - person conf; 25.04.2018
comment
У вас есть несколько адресов электронной почты в emails? - person MD. Khairul Basar; 25.04.2018
comment
Наиболее желанный. И ознакомьтесь с документом для более подробной информации. - person MD. Khairul Basar; 25.04.2018

Я пробовал все вышеперечисленные решения, и они не работают на Django 3.0. Итак, я провел собственное исследование и нашел решение. Решение будет довольно простым. Мой ответ в общем. Допустим, существует поле формы specialFieldName, которое определено как ManyToManyField в models.py.

Почему возникла эта ошибка?

Параметры этого поля, введенные пользователем через «форму django», сохраняются как Queryset. В этом сценарии мы просто не можем присвоить этому набору запросов атрибут ManyToManyField во время создания объекта на основе этого набора запросов. Это причина, по которой вы получаете вышеуказанную ошибку.

Итак, мы сначала создаем объект на основе всей информации, полученной из django-формы, кроме specialFieldName, а затем используем метод add() для добавления всех элементов этого набора запросов в только что созданный объект.

Итак, нам нужно перебрать этот набор запросов.

 returnedQueryset = form.cleaned_data.get('specialFieldName')
    dummyObject = ObjectModel.objects.create(..using all the info except specialFieldname..)
    for member in returnedQueryset:
        dummyObject.add(member)

К сожалению, цикл не повторяется по всем элементам возвращаемого набора запросов (Читайте Почему?< /а>). Таким образом, вышеуказанная вещь не работает. Мы должны стать немного более продвинутыми и вместо этого использовать метод iterator().

for member in returnedQueryset.iterator():
    dummyObject.add(member)

Теперь он работает нормально.

(P.S. Это был мой первый ответ на Stackoverflow. Благодарность всем моим наставникам ;-))

person Animesh Kumar    schedule 17.05.2020

Я получал ту же ошибку Direct assignment to the forward side of a many-to-many set is prohibited. Use plan_options.set() instead при обновлении с более старой версии Django до Django 2.2 LTS.

Однако, когда я использовал .set(), я получил SyntaxError: can't assign to function call. Для меня проблема была исправлена ​​добавлением _set:

existing_plan.plan_options_set = [x.pk for x in old_plan.plan_options.all()]
person SaeX    schedule 19.03.2021

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

class Set_user(FormView):
 template_name="pkm_templates/set_up_user.html"
 form_class = Set_User_Form
 success_url = '/thanks/'

 def form_valid(self, form):
    org = form.cleaned_data.get('organization')
    instance = Setupuser(organization=org,emails_for_help=emails)
    instance.save()
    instance.email.add(request.user.email)
    instance.save()
    return redirect("/")
person RAKESH GOMBI    schedule 28.07.2021