2011-09-09 48 views
28

Tôi có mô hình Django với phạm vi ngày bắt đầu và ngày kết thúc. Tôi muốn thực thi xác thực để không có hai bản ghi nào có phạm vi ngày trùng lặp. Cách đơn giản nhất để thực hiện điều này để tôi không phải lặp lại bản thân mình bằng cách viết logic này là gì?Thêm Xác thực Mẫu Django Tùy chỉnh

ví dụ: Tôi không muốn triển khai lại logic này trong Biểu mẫu a ModelForm biểu mẫu quản trị ghi đè của mô hình save().

Theo như tôi biết, Django không làm cho việc thực thi các loại tiêu chí này trở nên dễ dàng trên toàn cầu.

Googling không hữu ích lắm, vì "xác thực mẫu" thường đề cập đến việc xác thực các trường mô hình cụ thể chứ không phải toàn bộ nội dung mô hình hoặc mối quan hệ giữa các trường.

Trả lời

27

Các mô hình cơ bản tôi thấy hữu ích là đưa tất cả các xác nhận tùy chỉnh của tôi trong clean() và sau đó chỉ cần gọi full_clean() (trong đó kêu gọi clean() và một vài phương pháp khác) từ bên save(), ví dụ:

class BaseModel(models.Model): 

    def clean(self, *args, **kwargs): 
     # add custom validation here 
     super(BaseModel, self).clean(*args, **kwargs) 

    def save(self, *args, **kwargs): 
     self.full_clean() 
     super(BaseModel, self).save(*args, **kwargs) 

này không được thực hiện theo mặc định, như được giải thích here, bởi vì nó ảnh hưởng đến một số tính năng nhất định, nhưng đó không phải là vấn đề đối với ứng dụng của tôi.

8

Tôi nghĩ rằng bạn nên sử dụng này: https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects

Chỉ cần xác định phương pháp sạch() trong mô hình của bạn như thế này: (ví dụ từ các liên kết tài liệu)

def clean(self): 
    from django.core.exceptions import ValidationError 
    # Don't allow draft entries to have a pub_date. 
    if self.status == 'draft' and self.pub_date is not None: 
     raise ValidationError('Draft entries may not have a publication date.') 
    # Set the pub_date for published items if it hasn't been set already. 
    if self.status == 'published' and self.pub_date is None: 
     self.pub_date = datetime.datetime.now() 
+0

Kết thúc quá trình này. Tôi cũng đã phải ghi đè lên mô hình tiết kiệm của tôi(), và gọi clean() từ đó. – Cerin

+1

Nhưng để làm gì? AdminSite (ModelForm) gọi clean() tự động. Nhưng gọi clean() từ phương thức save() có thể tạo ra ValidationError trong một thời điểm bất ngờ và nó sẽ không được như mong đợi. – alTus

+6

Không phải mọi thứ đều sạch sẽ. Điều này cần phải được xác nhận bất kể nó được lưu ở đâu. Một trang web bị hỏng là thích hợp hơn để dữ liệu bị hỏng. – Cerin

16

tôi sẽ ghi đè lên các phương pháp validate_unique trên ngươi mâu. Để đảm bảo bạn bỏ qua các đối tượng hiện tại khi xác nhận, bạn có thể sử dụng như sau:

from django.db.models import Model, DateTimeField 
from django.core.validators import NON_FIELD_ERRORS, ValidationError 

class MyModel(Model): 
    start_date = DateTimeField() 
    end_date = DateTimeField() 

    def validate_unique(self, *args, **kwargs): 
     super(MyModel, self).validate_unique(*args, **kwargs) 

     qs = self.__class__._default_manager.filter(
      start_date__lt=self.end_date, 
      end_date__gt=self.start_date 
     ) 

     if not self._state.adding and self.pk is not None: 
      qs = qs.exclude(pk=self.pk) 

     if qs.exists(): 
      raise ValidationError({ 
       NON_FIELD_ERRORS: ['overlapping date range',], 
      }) 

ModelForm sẽ tự động gọi này cho bạn thông qua một full_clean(), mà bạn có thể sử dụng bằng tay quá.

PPR có một cuộc thảo luận tốt đẹp về đơn giản, chính xác range overlap condition.

+0

Trên django 1.3.1 Tôi đang gặp sự cố khi tăng ValidationError theo cách bạn mô tả.Tôi đã có thể khắc phục nó bằng cách chuyển một {field: (error_msg,)} dict thay vì một chuỗi error_msg khi tăng ngoại lệ. – adam

+5

'từ django.core.exceptions nhập ValidationError, NON_FIELD_ERRORS' ' tăng ValidationError ({NON_FIELD_ERRORS: ('phạm vi ngày trùng lặp',)}) ' – adam

+2

Có bất kỳ lợi ích nào trong việc mở rộng' validate_unique' thay vì chỉ định nghĩa 'sạch' ? Chỉ là một câu hỏi về việc tổ chức mã? – lajarre

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