如何使用ManyToManyField正确覆盖ModelForm的save()方法

时间:2010-10-19 19:30:11

标签: django django-models django-forms

考虑我已经定义了以下模型:

class Tag(models.Model):
  name = models.CharField(max_length=20)

class Entry(models.Model):
  title = models.CharField(max_length=100)
  date = models.DateField()
  tags = models.ManyToManyField(Tag)

以及以下模型形式:

class EntryForm(forms.ModelForm):
  tags =  CharField(max_length=100, label='Tags', required=False)
  class Meta:
    model = Entry

基本上我有一个带标签的条目。标签不一定已经创建。我需要收到填写的参赛表格并用标签保存。

如果我在Entry中没有ManyToMany关系,我可以轻松地做到这一点。但有了它我首先需要保存标签,然后将保存的标签添加到条目,然后保存条目。这意味着我必须覆盖EntryForm的save()方法。

我已经看到了this的问题,但看起来有所不同。在我的情况下,我只需要保存标签,其余的应该能够使用ModelForm的默认save()。

我提出了一个简化的例子。在真实的一个中,我在Entry中有更多的字段。 你有什么建议以django方式编写EntryForm的save()方法?

2 个答案:

答案 0 :(得分:3)

我认为您可以在保存标签后调用super。也许您需要在创建条目后附加到条目。

def save(self, commit=True):
    # do custom stuff
    tags =[]
    for t in self.cleaned_data['tags'].split(','):
         tags.append(Tag.objects.get_or_create(name=t))
    # save entry
    e = super(EntryForm, self).save(commit=commit)

    for t in tags:
        e.tags.add(t)

答案 1 :(得分:1)

这里最好和正确的选择是将clean_tags方法添加到表单中,而不是覆盖模型中的save()。

def clean_tags(self):
    tags = self.cleaned_data.get('tags', None)

    clean_tags = []


    tags = [tag.strip() for tag in tags.split(',') if tags]

    for tag in tags:
        t, created = Tag.objects.get_or_create(title=tag)
        t.count = F('count') + 1
        t.user.add(self.cleaned_data['user'])
        t.save()
        clean_tags.append(t)

    return clean_tags