Django | <title> object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used

huangapple go评论70阅读模式
英文:

Django | <title> object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used

问题

我在使用form.save(commit=False)时遇到了一个错误,我无法弄清楚我做错了什么。

我的视图看起来像这样:

views.py

def make_electable(request, election_id):
    election = get_object_or_404(CommissionElection, id=election_id)
    if request.method == 'POST':
        form = MakeElectable(request.POST)
        if form.is_valid():
            electable = form.save(commit=False)
            electable.election.set(election)
            form.save()

forms.py

class MakeElectable(forms.ModelForm):
    class Meta:
          model = ElectablePerson
          fields = ['commission',]
    commission = forms.ModelChoiceField(queryset=Commissie.objects.all(), widget=forms.RadioSelect())

models.py

class CommissionElection(models.Model):
    title = models.CharField(max_length=64)
    commission = models.ManyToManyField(Commissie)
    electable_time = DateRangeField()
    voting_time = DateRangeField()


class ElectablePerson(models.Model):
    commission = models.CharField(max_length=128)
    election = models.ManyToManyField(CommissionElection)

我遇到的错误是:

"ElectablePerson: ElectablePerson object (None)" 需要在此多对多关系可用之前有一个 "id" 字段的值。

我不明白为什么对象是 None。我怀疑这与 manytomanyfield 有关。

英文:

I get an error using with using form.save(commit=False) and I cannot figure out what I'm doing wrong.

My view looks something like this:

views.py

def make_electable(request, election_id):
    election = get_object_or_404(CommissionElection, id=election_id)
    if request.method == &#39;POST&#39;:
        form = MakeElectable(request.POST)
        if form.is_valid():
            electable = form.save(commit=False)
            electable.election.set(election)
            form.save()

forms.py

class MakeElectable(forms.ModelForm):
    class Meta:
          model = ElectablePerson
          fields = [&#39;commission&#39;,]
    commission = forms.ModelChoiceField(queryset=Commissie.objects.all(), widget=forms.RadioSelect())

models.py

class CommissionElection(models.Model):
    title = models.CharField(max_length=64)
    commission = models.ManyToManyField(Commissie)
    electable_time = DateRangeField()
    voting_time = DateRangeField()


class ElectablePerson(models.Model):
    commission = models.CharField(max_length=128)
    election = models.ManyToManyField(CommissionElection)

The error I get is:

> "<ElectablePerson: ElectablePerson object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used.

I don't see why the object is None. I suspect it has something to do with the manytomanyfield.

答案1

得分: 2

一个多对多字段是一个使用'id_electable'和'id_election'作为键的表,其中commit=false,不会持久化,因此不会得到ID。以下代码应该解决您的问题。

if form.is_valid():
    electable = form.save()
    electable.election.add(election)

还可以参考 https://docs.djangoproject.com/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.add 了解多对多关系。

英文:

A many to many field is a table which uses 'id_electable, id_election' as keys, with commit=false, you don't persist which gives you no id. Following code should fix your issue.

if form.is_valid():
    electable = form.save()
    electable.election.add(election)

Also see https://docs.djangoproject.com/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.add for many to many relations.

答案2

得分: 0

不能添加或设置多对多字段,如果你要链接的两个对象中的一个尚未在数据库中创建,因为这些对象需要一个令牌来彼此关联,所以:

def make_electable(request, election_id):
    election = get_object_or_404(CommissionElection, id=election_id)
    if request.method == 'POST':
        form = MakeElectable(request.POST, request.FILES)
        if form.is_valid():
            electable = form.save()
            electable.election.set(election)
            return redirect('name-of-some-view')
    # ...

注意: 通常最好不要在保存表单时使用 commit=False,使用 **.save(&hellip;) 方法[Django-doc] 时,这样会阻止保存多对多关系,因为只有在提交了项目后才能保存这些关系。通常最好修改表单中包装的 .instance。有关更多信息,请参阅我的文章[Django-反模式]

注意: 虽然大多数表单不处理媒体文件,但最好仍然将 **request.FILES[Django-doc] 传递给表单,以便如果您稍后添加额外的媒体字段,使用该表单的所有视图将正确处理这些文件。

英文:

You can not add or set a many-to-many field if one of the two objects you link has not been created in the database first, since the objects need a token to get linked to each other, so:

<pre><code>def make_electable(request, election_id):
election = get_object_or_404(CommissionElection, id=election_id)
if request.method == 'POST':
form = MakeElectable(request.POST, request.FILES)
if form.is_valid():
electable = <b>form.save()</b>
electable.election.set(election)
return redirect('<em>name-of-some-view</em>')
# &hellip;</code></pre>


> Note: Usually it is better not to work with commit=False when saving the form with the <code>.save(&hellip;)</code> method&nbsp;<sup>[Django-doc]</sup>: this will revent saving many-to-many relations since these can only be saved if the item is committed. Usually it is better to alter the .instance wrapped in the form. For more information, see my article<sup>[Django-antippaterns]</sup> on this.


> Note: While most forms do not process media files, it is probably better to pass request.FILES&nbsp;<sup>[Django-doc]</sup> to the form anyway, such that if you later add an extra media field, all views that use the form will indeed handle the files properly.

huangapple
  • 本文由 发表于 2023年6月13日 16:35:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76463079.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定