我有一个Django模型ManyToManyField.我需要要求用户在此字段中选择至少一个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
Run Code Online (Sandbox Code Playgroud)
我可以使用自Form定义定义或使用模型的覆盖save()方法来解决这种情况Person.
是否可以通过设置选项阻止创建Person没有至少一个Skill选定的ManyToManyField?或者我需要创建自定义逻辑来处理这种情况?谢谢.
我用Django 1.7和Python 3.4
更新1.如何创建ModelForm控制M2M?因为在cleaned_data我只有Person表格中传递的字段,并且没有我作为M2M字段传递的数据.我尝试在管理站点中创建对象并控制Skills所选对象.我进入了Skill's via inline.
# admin.py
class PersonSkillsInline(admin.TabularInline):
model = Person.skills.through
extra = 2
class PersonAdmin(admin.ModelAdmin):
inlines = [PersonSkillsInline]
admin.site.register(Person, PersonAdmin)
Run Code Online (Sandbox Code Playgroud)
在数据库级别......不,这是不可能的.任何强制执行都必须来自您的应用程序逻辑.
原因是每个m2m关系都有一个记录,其中一个外键到 m2m关系的两边.SQL不能强制存在关系的引用方,只能引用关系的引用方.
此外,您也无法在模型中强制执行它,因为Person必须先创建并保存它,然后才能分配任何多对多关系.
您唯一的选择是在表单或视图中强制执行它.
在InlineModelAdmin这可以通过指定min_num(1.7+)轻松完成:
class PersonSkillsInline(admin.TabularInline):
model = Person.skills.through
min_num = 1
extra = 2
Run Code Online (Sandbox Code Playgroud)