2012-02-09 33 views
6

Hãy nói rằng tôi có hai mô hình:Validate inlines trước khi lưu mô hình

class Distribution(models.Model): 
    name = models.CharField(max_length=32) 

class Component(models.Model): 
    distribution = models.ForeignKey(Distribution) 
    percentage = models.IntegerField() 

Và tôi đang sử dụng một đơn giản TabularInline để hiển thị Component s bên trong các hình thức Distribution admin:

class ComponentInline(admin.TabularInline): 
    model = Component 
    extra = 1 

class DistributionAdmin(admin.ModelAdmin): 
    inlines = [ComponentInline] 

Vì vậy, mục tiêu của tôi là xác thực nếu tỷ lệ phần trăm của tất cả các số Component s của số tiền Distribution tổng 100 trước khi lưu. Nghe có vẻ đơn giản, vì vậy tôi đã làm:

# ... Inside the Distribution model 
def clean(self): 
    # Sum of components must be 100 
    total_sum = sum(comp.percentage for comp in self.component_set.all()) 
    if total_sum != 100: 
     raise ValidationError('Sum of components must be 100%') 

Nhưng điều này sẽ không bao giờ làm việc làm việc, bởi vì trong Django tất cả các đối tượng được lưu trước khi lưu đối tượng nước ngoài-key hoặc many2many liên quan của nó, đây không phải là một lỗ hổng, nó có một lí do: nó không thể lưu các đối tượng liên quan trước tiên, bởi vì đối tượng mà chúng liên quan chưa được xác định id (idNone cho đến khi đối tượng được lưu lần đầu tiên trong DB).

Tôi chắc chắn tôi không phải là người đầu tiên gặp phải sự cố này. Vậy, có cách nào để hoàn thành những gì tôi đang cố gắng làm không? Tôi đã nghĩ có thể một quản trị viên đang hack bằng cách sử dụng TabularInline hoặc ModelAdmin ...?

Trả lời

3

Dưới đây là một (chưa được kiểm tra) ý tưởng, nếu bạn hài lòng để di chuyển các xác nhận từ mô hình đến formset inline:

Subclass BaseInlineFormSet và ghi đè lên các phương pháp sạch để kiểm tra tổng các tỷ lệ phần trăm.

from django.forms.models import BaseInlineFormSet 
from django.core.exceptions import ValidationError 

class ComponentInlineFormSet(BaseInlineFormSet): 

    def clean(self): 
     """Check that sum of components is 100%""" 
     if any(self.errors): 
      # Don't bother validating the formset unless each form is valid on its own 
      return 
     total_sum = sum(form.cleaned_data['percentage'] for form in self.forms) 
     if total_sum != 100: 
      raise ValidationError('Sum of components must be 100%') 

Sau đó, sử dụng biểu mẫu nội tuyến của bạn trong ComponentInline.

class ComponentInline(admin.TabularInline): 
    model = Component 
    extra = 1 
    formset = ComponentInlineFormSet 
+0

Đây là một ý tưởng hay! Tôi biết Inlines có rất nhiều thứ để cung cấp. Tôi sẽ cố gắng này đúng biết – juliomalegria

+0

tuyệt vời! Nó hoạt động tốt với một vài thay đổi. Cảm ơn, thực sự :) – juliomalegria

+0

Vui vì nó đã hoạt động :) – Alasdair

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