programing

django의 model.save()가 full_clean()을 호출하지 않는 이유는 무엇입니까?

yellowcard 2023. 6. 9. 21:57
반응형

django의 model.save()가 full_clean()을 호출하지 않는 이유는 무엇입니까?

저는 장고의 옴이 모델 폼의 일부로 저장되지 않는 한 모델에서 'full_clean'이라고 부르지 않는 이유가 있는지 아는 사람이 있는지 궁금합니다.

모델의 save() 메서드를 호출할 때 full_clean()은 자동으로 호출되지 않습니다.수동으로 생성한 모델에 대해 한 단계 모델 유효성 검사를 실행하려면 수동으로 호출해야 합니다. django의 전체 클린 문서

(참고: Django 1.6에 대한 견적 업데이트...이전 django 문서에도 모델폼에 대한 경고가 있었습니다.)

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

저는 모든 것을 제대로 작동시키는 방법을 알고 있습니다. 그냥 설명을 찾고 있는 중입니다.

AFAIK, 이것은 이전 버전과의 호환성 때문입니다.제외된 필드가 있는 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()

가장 간단한 호출 방법은full_clean방법은 단지 그것을 무시하는 것입니다.save모형의 방법:

class YourModel(models.Model):
    ...  
    
    def save(self, *args, **kwargs):
        self.full_clean()
        return super(YourModel, self).save(*args, **kwargs)

@Alfred Huang의 답변과 그에 대한 논평.현재 모듈(models.py )에서 클래스 목록을 정의하고 pre_save 후크에서 확인하여 pre_save 후크를 앱에 잠글 수 있습니다.

CUSTOM_CLASSES = [obj for name, obj in
        inspect.getmembers(sys.modules[__name__])
        if inspect.isclass(obj)]

@receiver(pre_save)
def pre_save_handler(sender, instance, **kwargs):
    if type(instance) in CUSTOM_CLASSES:
        instance.full_clean()

하나 이상의 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

앱을 할 수 .INSTALLED_APPS을 에 포함시키다.settings.py

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

그 전에 PyPI를 사용하여 설치해야 할 수도 있습니다.

pip install django-fullclean

기업pre_save항상 모델 유효성 검사를 보장하려면 신호가 잘 작동할 수 있습니다.그러나 현재 버전(3.1.x)에서 장고의 인증에 문제가 발생할 수 있으며 사용 중인 다른 앱의 모델에 문제가 발생할 수 있습니다.

@Peter Shannon의 답변을 자세히 설명하면, 이 버전은 사용자가 실행하는 모듈 내부의 모델만 검증하고 "raw" 저장으로 검증을 건너뛰고 다음을 추가합니다.dispatch_uid중복 신호를 방지합니다.

from django.db.models.signals import pre_save
import inspect
import sys

MODELS = [obj for name, obj in
    inspect.getmembers(sys.modules[__name__], inspect.isclass)]

def validate_model(sender, instance, **kwargs):
    if 'raw' in kwargs and not kwargs['raw']:
        if type(instance) in MODELS:
            instance.full_clean()

pre_save.connect(validate_model, dispatch_uid='validate_models')

언급URL : https://stackoverflow.com/questions/4441539/why-doesnt-djangos-model-save-call-full-clean

반응형