2010-12-14 2 views
108

django의 orm이 모델에서 'full_clean'을 호출하지 않는 좋은 이유가 누구인지 아는 경우에만 궁금합니다. 모델 양식의 일부로 저장되지 않은 경우입니다.django의 model.save()가 full_clean()을 호출하지 않는 이유는 무엇입니까?

모델의 save() 메서드를 호출 할 때 full_clean()이 자동으로 호출되지 않습니다. 수동으로 생성 한 모델에 대해 원스텝 검증을 실행하려면 수동으로 호출해야합니다. django's full clean doc

(참고 : 인용 이전 장고 문서뿐만 아니라 ModelForms에 대한 경고를했다 ... 장고 1.6 업데이트.)

사람들이이 동작을 원하지 않을 이유가 좋은 이유가 있습니까? 모델에 유효성 검사를 추가 할 시간이 있다면 모델이 저장 될 때마다 유효성 검사가 실행되기를 바랄 것입니다.

모든 것이 제대로 작동하는 방법을 알고 있습니다. 설명을 찾고 있습니다.

+6

이 질문을 주셔서 대단히 감사합니다. 내 머리를 벽에 더 부딪 히지 않게했습니다. 다른 사람들을 도울 믹스 인을 만들었습니다. 요점을 확인하십시오 : https://gist.github.com/glarrain/5448253 – glarrain

+0

그리고 마지막으로 'pre_save' 후크를 잡아 내고 모든 잡힌 모델에 대해'full_clean '을하기 위해 신호를 사용합니다. –

답변

44
+2

두 번째 참조에서 가장 유용한 발췌 부분 (IMHO) : "모두 자동으로 유효성 검사 옵션을 개발하는 것입니다. 실제로 유용하고 충분히 강력 할 정도로 충분합니다. 사례 - 가능한 경우에도 - - 장황한 시간에 1.을 수행 할 수 있습니다. 따라서 지금 장고는 1.3에서 작동 할 수 있다고 생각한다면, 가장 좋은 방법은 최소한 샘플 코드와 함께 을 간단하고 견고하게 유지하는 방법에 대한 설명과 함께 제안서를 작성하는 것입니다. " – Josh

+1

시도해보십시오 https://github.com/danielgatis/django-smart-save – danielgatis

18

: 당신이 intrested하는 수도 등

소스 제외 필드 ModelForms 문제, 기본값 모델, pre_save() 신호도있다 고려 사항이기 때문에, 자동 저장시 django 커널에서는 저장 기능을 사용할 수 없습니다.

새 프로젝트를 시작하고 모델의 save 메소드를 자동으로 치료하려면 다음 모델을 사용하여 모든 모델을 저장하기 전에 다음과 같은 신호를 사용하십시오.

from django.dispatch import receiver 
from django.db.models.signals import pre_save, post_save 

@receiver(pre_save) 
def pre_save_handler(sender, instance, *args, **kwargs): 
    instance.full_clean() 
+0

왜이 방법을 사용하면 일부 BaseModel (다른 모든 상속자가 상속받는)의 save 메서드를 재정의하여 full_clean을 먼저 호출하는 것보다 좋고 (또는 나쁜) super()를 호출합니까? –

+0

@J__ 분명히이 방법은 특정 모델이 아닌 모든 모델에 적용되므로 한번 쓰고 어디서나 쓸 수 있습니다. 일부 BaseModel을 재정의하는 경우 각 모델에 대해 작성해야합니다. –

+0

그러나 신호는 나중에 예외가 발생할 가능성을 배제합니다. 나는 왜 내가 예외를 만들어야하는지 알지 못한다. 그러나 그것은 단점이다. –

0

대신 수신기를 선언 코드 조각을 삽입하는, 우리가 그 전에 settings.py

INSTALLED_APPS = [ 
    # ... 
    'django_fullclean', 
    # your apps here, 
] 

INSTALLED_APPS 섹션 같은 응용 프로그램을 사용할 수 있습니다, 당신은 PyPI 사용 django-fullclean를 설치해야 할 수 있습니다 :

pip install django-fullclean 
+8

왜 4 라인의 코드로 일부 응용 프로그램을'pip 설치 '할까요? ([소스 코드] (https://github.com/fishball/django-fullclean/blob/master/django_fullclean/__init__.py))를 작성하는 대신이 줄을 직접 작성 하시겠습니까? –

6

full_clean 메서드를 호출하는 가장 간단한 방법은 save 메서드를 재정의하는 것입니다. R model :

def save(self, *args, **kwargs): 
    self.full_clean() 
    return super(YourModel, self).save(*args, **kwargs) 
+0

왜 신호를 사용하는 것보다이 방법이 좋을까 (또는 나쁜가?)? –

+0

@J__ 대답을 참조하십시오 http://stackoverflow.com/a/171703/6077223 –

+1

이 접근 방식에 두 가지 문제점이 있습니다. 1) ModelForm의 full_clean()이 두 번 호출 될 것입니다 : 폼과 저장에 의해 2) If 양식은 일부 필드를 제외하고 저장으로 계속 유효성을 검사합니다. – mehmet

1

당신이 그 기본 FK를 설정해야합니다 때문에 null=False을 사용하지 않으려는 적어도 하나 개의 FK 관계를 가지고 있으며, 확인하고자하는 모델이있는 경우 (쓰레기 데이터가 될 것이다) 가장 좋은 방법은 맞춤 .clean().save() 메소드를 추가하는 것입니다. .clean()은 유효성 검사 오류를 발생시키고 .save()은 깨끗함을 호출합니다. 이렇게하면 무결성이 양식과 다른 호출 코드, 명령 줄 및 테스트에서 모두 적용됩니다. 이것이 없다면 AFAICT는 특정 모델이 특별히 선택되지 않은 다른 모델에 대해 FK 관계를 갖도록하는 테스트를 작성할 방법이 없습니다.

class Payer(models.Model): 

    name = models.CharField(blank=True, max_length=100) 
    # Nullable, but will enforce FK in clean/save: 
    payer_group = models.ForeignKey(PayerGroup, null=True, blank=True,) 

    def clean(self): 
     # Ensure every Payer is in a PayerGroup (but only via forms) 
     if not self.payer_group: 
      raise ValidationError(
       {'payer_group': 'Each Payer must belong to a PayerGroup.'}) 

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

    def __str__(self): 
     return self.name