我正在尝试在Django中使用ModelForms向我的数据库添加内容,其中包含ManyToManyField。这是我模型的相关部分:
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
def __unicode__(self):
return self.name
class Recipe(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
user = models.ForeignKey(User)
image = models.ImageField(upload_to='images/recipethumbs/', null = True, blank=True)
ingredients = models.ManyToManyField(Ingredient, through="IngredientMap")
categories = models.ManyToManyField(Category)
citation = models.CharField(max_length=200)
def __unicode__(self):
默认情况下,ManyToManyFields由多项选择表示。这允许用户从类别对象中的预先存在的字段中选择。我想更改此设置,以便用户可以选择当前存在的类别,或者如果不存在则添加新类别。看起来,这可以通过将窗口小部件更改为TextInput来完成。
class RecipeForm(ModelForm):
class Meta:
model = Recipe
widgets = {
'categories': TextInput(attrs={'size': 40,}),
'ingredients': Textarea,
}
但是如果用户输入Categories表中当前不存在的类别,那么Django会抱怨我需要“输入值列表”。如果表单尚未存在,如何将表单添加到添加新类别?
我在Ilvar建议的自定义.save()中的解决方案:
categories = re.findall(r'\w+[\w\s]+', self.cleaned_data.get('categories')) #returns an array
if commit:
m.save()
# You can only assign m2m if the Recipe object has been saved.
for category in categories:
try:
category_in_db = Category.objects.get(name=category)
except:
category_in_db = None
if category_in_db:
m.categories.add(category_in_db)
else:
m.categories.create(name=category)
return m
答案 0 :(得分:1)
您需要从表单中exclude
m2m字段并手动添加CharField
表单类本身。然后覆盖__init__
以在initial
和save
中设置此字段。在save
中,您可以对cleaned_data
中的文字执行任何操作。我想,在你的情况下,它将用逗号分割,为每个值获取一个类别,并在返回结果之前将类别列表分配给对象中的字段后保存父表单。也许还要添加一些autocomplete以避免在客户端上输入错误。