2017-01-04 19 views
2

BookPageの2つのモデルがあります。ここでPageBookと外部キーの関係にあります。 admin.pyでは、書籍を変更するWebページにPageオブジェクトのインライン要素があります。Djangoの外部キーに依存する条件を検証するadmin

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()メソッドをオーバーライドする必要があると思いますが、そこからユーザーが入力したページに関連するデータへのアクセス方法はわかりません。

編集

Emettの提案に基づいて、私はPageモデルのclean()方法上書きしようとしている:私はすべてのページのページ番号を変更した場合:これは動作しません

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

これはあなたの 'models.py'に行われる必要があるに。あなたはモデルを提供してもらえますか? –

+0

@EmettSpeer本当ですか? models.pyでは、検証時にデータベースに保存されていない '' Page''オブジェクトの '' Book''メソッドインスタンスにアクセスする必要があります。 – mimo

+0

データベースに新しいページを保存するときに、ページにブックが添付されている必要があります。これは、システムがこのロジックをプリフォームにするのが適切な時期になります。この問題のためには、「一人暮らし」が正しい選択肢になるようです。 https://docs.djangoproject.com/en/1.10/ref/models/options/#unique-together –

答えて

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 
+0

独自のチェックがモデルフォームに組み込まれています。だからあなたは、カスタマイズされたクリーンメソッドを必要としません – e4c5

+0

モデルは 'unique_together'を持っていない場合の回避策:) – ruddra

+0

あなたの答えを再び読んで、私はあなたが意味するものを参照してください。あなたの最初の提案は、ユニークなものを使用して優れたものです。制約は常にデータベースレベルで実装する必要があります。オリジナルの質問とあなたのフォームのアプローチは、実際には非常に悪い考えです。それは最初から車輪を再発明しています。我々が持っているホイールはロープロファイルタイヤを備えたアロイホイールです。そしてそれは競争条件に取り組むのに何もしません – e4c5

関連する問題