2011-11-02 35 views
30

Tôi có một mô hình với một ManyToManyField tương tự với trang này (mô hình Word có một ngôn ngữ, quá):Django ManyToMany mô hình xác nhận

class Sentence(models.Model): 
    words = models.ManyToManyField(Word) 
    language = models.ForeignKey(Language) 
    def clean(self): 
     for word in self.words.all(): 
      if word.language_id != self.language_id: 
       raise ValidationError('One of the words has a false language') 

Khi cố gắng để thêm một câu mới (ví dụ như thông qua django admin) Tôi nhận được 'Sentence' instance needs to have a primary key value before a many-to-many relationship can be used. Điều này có nghĩa là tôi không thể truy cập self.words trước khi lưu nó, nhưng đây chính là điều tôi đang cố gắng làm. Có cách nào để làm việc xung quanh này để bạn có thể xác nhận mô hình này tuy nhiên? Tôi thực sự muốn xác nhận trực tiếp các trường của mô hình.

Tôi đã tìm thấy nhiều câu hỏi liên quan đến ngoại lệ này, nhưng tôi không thể tìm thấy trợ giúp cho vấn đề của mình. Tôi sẽ đánh giá cao bất kỳ lời đề nghị!

+0

Nếu bạn muốn tạo một từ, bạn sẽ xác nhận rằng nó được liên kết với một câu như thế nào? Nó không có trường 'câu' trong định nghĩa mô hình của nó. – johnklawlor

+0

Không phải ai cũng sử dụng biểu mẫu. Tôi coi đây là một lỗ hổng lớn ở Django. Có ai có câu trả lời tốt hơn không? –

Trả lời

44

Không thể thực hiện xác thực này theo phương pháp clean của mô hình, nhưng bạn có thể tạo biểu mẫu mô hình có thể xác thực lựa chọn words.

from django import forms 

class SentenceForm(forms.ModelForm): 
    class Meta: 
     model = Sentence 

    def clean(self): 
     """ 
     Checks that all the words belong to the sentence's language. 
     """ 
     words = self.cleaned_data.get('words') 
     language = self.cleaned_data.get('language') 
     if language and words: 
      # only check the words if the language is valid 
      for word in words: 
       if words.language != language: 
        raise ValidationError("The word %s has a different language" % word) 
     return self.cleaned_data 

Sau đó, bạn có thể tùy chỉnh lớp quản trị mô hình Sentence, để sử dụng biểu mẫu của mình trong quản trị viên Django.

class SentenceAdmin(admin.ModelAdmin): 
    form = SentenceForm 

admin.register(Sentence, SentenceAdmin) 
+6

Thật đáng tiếc khi thấy không có khả năng xác nhận nó trực tiếp trong mô hình. Nhưng cho đến nay một ModelForm tùy chỉnh là đủ cho tôi. Cảm ơn bạn vì câu trả lời! – purefanatic

+0

Ngoài ra, nếu biểu mẫu Câu của bạn cũng có thể được xem là nội tuyến trong mô hình khác (ví dụ: Đoạn), bạn cũng sẽ muốn thêm dòng 'form = SentenceForm' vào lớp SentenceInline. –

+0

@purefanatic 'Model.save()' không được dự kiến ​​sẽ tăng 'ValidationErrors' do đó không có cách nào để xác nhận nó trực tiếp. – jnns

1

Bạn không thể làm điều đó từ phương thức clean trên mô hình. Nó chỉ đơn giản là không thể với cách quan hệ M2M làm việc trong Django. Tuy nhiên, bạn có thể thực hiện loại xác thực này trên các biểu mẫu được sử dụng để tạo một Sentence chẳng hạn như trong quản trị viên hoặc biểu mẫu trên trang web của bạn.

Các vấn đề liên quan