我有两个模型Book
和Page
,其中Page
与Book
具有外键关系。在admin.py中,修改图书的网页包含Page
个对象的内联元素。
models.py:
class Book(models.Model):
# ...
class Page(models.Model):
book = models.ForeignKey(Book, editable=False)
number = models.IntegerField('Page number')
# ...
admin.py:
class PageAdminInline(admin.TabularInline):
model = Page
extra = 1
class BookAdmin(admin.ModelAdmin):
inlines = [PageAdminInline]
admin.site.register(Book, BookAdmin)
在内联表单中,字段允许设置每个页面的页码。使用此配置,如何验证全局条件,即书籍的所有页面编号应该不同,并从1编号到与书籍关联的Page
个对象的数量?
我想我必须覆盖与书籍模型或某个地方相关的clean()
方法,但我不知道如何从那里访问与用户输入的页面相关的数据。< / p>
修改
根据Emett的建议,我试图覆盖clean()
模型的Page
方法:
class Page(models.Model):
book = models.ForeignKey(Book, editable=False)
number = models.IntegerField('Page number')
def clean():
book_pages = Page.objects.filter(book=self.book)
# ... [apply condition on the book_pages QuerySet]
super(Page, self).clean()
这不起作用:如果我修改管理网站中所有页面的页码,book_pages
将包含具有旧页码的对象。
此外,在Page
中检查条件也意味着如果我有n页,它将被测试n次,而只检查一次就足够了。
答案 0 :(得分:0)
更简单的解决方案是将unique_together放在django模型中。 IE
class Page(models.Model):
book = models.ForeignKey(Book, editable=False)
number = models.IntegerField('Page number')
class Meta:
app_label = 'page'
db_table = 'pages'
verbose_name = 'Page'
verbose_name_plural = 'Pages'
unique_together = (('book', 'number'),)
如果您不想使用unique_together
,然后创建表单,在内联中使用它,则另一种解决方法,即:
class PageForm(forms.ModelForm):
class Meta:
model = Page
fields ='__all__'
def clean():
cleaned_data = self.cleaned_data
book = cleaned_data.get('book')
number = cleaned_data.get('number')
page_qset = Page.objects.filter(book=book, number=number)
if len(page_qset) > 0: # inefficient solution, using it for forcibly executing query
raise forms.ValidationError('Already exists')
return super().clean()
class PageAdminInline(admin.TabularInline):
form = PageForm