我有一个带有ManyToManyField
的Django模型。我需要要求用户在此字段中选择至少一个M2M值。
我尝试将blank=False
设置为M2M字段,但没有帮助。
class Skill(models.Model):
name = models.CharField(max_length=200)
class PersonSkills(models.Model):
person = models.ForeignKey('Person')
skill = models.ForeignKey('Skill')
class Person(models.Model):
name = models.CharField(max_length=200)
skills = models.ManyToManyField('Skill', through='PersonSkills')
p = Person(name='Bob')
p.save()
# success, but I expect that this should throw ValidationError, because I didn't select at least one Skill for this person
我可以使用自定义Form
定义或使用save()
模型的覆盖Person
方法解决此问题。
是否可以阻止创建Person
而不选择至少一个Skill
,并设置ManyToManyField
个选项?或者我需要创建自定义逻辑来处理这种情况?感谢。
我使用Django 1.7
和Python 3.4
更新1。如何创建ModelForm
来控制M2M?因为在cleaned_data
中我只有Person
形式传递的字段,并且没有我作为M2M字段传递的数据。我尝试在管理站点中创建对象并控制Skills
选择的对象。我通过Skill
输入了inline
。
# admin.py
class PersonSkillsInline(admin.TabularInline):
model = Person.skills.through
extra = 2
class PersonAdmin(admin.ModelAdmin):
inlines = [PersonSkillsInline]
admin.site.register(Person, PersonAdmin)
答案 0 :(得分:8)
在数据库级别......不,那是不可能的。任何强制执行都必须来自您的应用程序逻辑。
原因是每个m2m关系都有一个记录,其中一个外键到 m2m关系的两边。 SQL不能强制存在关系的引用方,只能存在关系的引用方。
此外,您也无法在模型中强制执行此操作,因为必须先创建并保存Person
,然后才能分配任意多对多关系。
您唯一的选择是在表单或视图中强制执行。
在InlineModelAdmin
中,可以通过指定min_num
(1.7 +)轻松完成此操作:
class PersonSkillsInline(admin.TabularInline):
model = Person.skills.through
min_num = 1
extra = 2