代码之家  ›  专栏  ›  技术社区  ›  grigy

如何正确地使用ManyToManyField重写模型的ModelForm的save()方法

  •  2
  • grigy  · 技术社区  · 14 年前

    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
    

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

    我看到了 this 已经有问题了,但看起来不一样。在我的例子中,我只需要保存标记,其余的应该可以使用ModelForm的默认save()。

    我举了一个简单的例子。在实际中,我在条目中有更多的字段。

    2 回复  |  直到 8 年前
        1
  •  1
  •   Pavel Shvedov    13 年前

    最好且正确的选择是将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
    
        2
  •  3
  •   OmerGertel    14 年前

    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)