programing

장고 모델 양식:save(commit=False)는 무엇에 사용됩니까?

linuxpc 2023. 8. 4. 22:43
반응형

장고 모델 양식:save(commit=False)는 무엇에 사용됩니까?

내가 왜 사용하겠습니까?save(commit=False) 에서 양식 를 만드는 ModelForm 및 중인 하위스행is_valid()양식과 모델을 모두 검증하시겠습니까?

다시말서, 무이엇이 입니까?save(commit=False)요?

이것이 유용할 수 있는 가상의 상황을 제공할 수 있습니까?

하지만, 모델 데이터를 채워야 합니다.null=False형식이 아닌 데이터가 있는 필드입니다.

으로 commit=False모델 개체를 가져온 다음 추가 데이터를 추가하고 저장할 수 있습니다.

이것은 그 상황의 좋은 예입니다.

다음은 저장 방법에 대한 문서입니다.양식에 다대다 필드가 포함된 경우, 호출할 수도 있습니다.form.save_m2m()모델 인스턴스(instance)를 저장한 후.

다음은 (문서에서) 답변입니다.

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

가장 일반적인 상황은 폼에서 인스턴스를 가져오지만 데이터베이스가 아닌 '메모리 내'에서만 인스턴스를 가져오는 것입니다.저장하기 전에 다음 사항을 변경해야 합니다.

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

장고 문서에서:

이 save() 메서드는 True 또는 False를 허용하는 선택적 commit 키워드 인수를 허용합니다.와 함께 save()를 호출하는 commit=False그런 다음 데이터베이스에 아직 저장되지 않은 개체를 반환합니다.

이 경우 결과 모델 인스턴스에 대해 save()를 호출하는 것은 사용자에게 달려 있습니다.이 기능은 개체를 저장하기 전에 개체에 대해 사용자 지정 처리를 수행하거나 특수 모델 저장 옵션 중 하나를 사용하려는 경우에 유용합니다.commit은 기본적으로 True입니다.

저장) 것 .commit=False인스턴스를 는 모델 인스턴스를 생성하며, 이 인스턴스는 사용자에게 반환됩니다.실제로 저장하기 전에 후처리에 적합합니다!

"실제 예"로 이메일 주소와 사용자 이름이 항상 동일한 사용자 모델을 고려하면 다음과 같이 ModelForm의 저장 방법을 덮어쓸 수 있습니다.

class UserForm(forms.ModelForm):
    ...
    def save(self):
        # Sets username to email before saving
        user = super(UserForm, self).save(commit=False)
        user.username = user.email
        user.save()
        return user

당신이 않경우은지를 사용하지.commit=False사용자 이름을 전자 메일 주소로 설정하려면 사용자 모델의 저장 방법을 수정하거나 사용자 개체를 두 번 저장해야 합니다(이 경우 값비싼 데이터베이스 작업이 중복됨).

여기서 제가 이해하는 기본적인 것은 시각적으로 '형태' 인스턴스에서 특정 '모델' 인스턴스로 바뀐다는 것입니다.

StackOverflow에 이와 같은 답변을 게시하려고 합니다.코드는 다음과 같습니다.

# Create a form instance with POST data.
>>> form_data = AnswerForm(request.POST)

# Create, but don't save the new answer instance.
>>> Answer = form_data.save(commit=False)

이제 이 답변의 소유자를 추가하고 다음과 같이 보기 페이지의 데이터베이스에 저장해야 합니다.

>>> Answer.owner = request.user

>>> Answer.save()

래서우그이렇할게수없이수있다추주습니인가답할을변는처럼 할 수 없는 이 답의 을 추가할 수 .form_data.owner = request.user양식 클래스가 아닌 보기 페이지에 있습니다.

따라서 기본적으로 'form' 인스턴스에서 'model' 인스턴스로 변경된 다음 데이터를 수정하고 저장할 수 있습니다.

            form = AddAttachmentForm(request.POST, request.FILES)
            if form.is_valid():
                attachment = form.save(commit=False)
                attachment.user = student
                attachment.attacher = self.request.user
                attachment.date_attached = timezone.now()
                attachment.competency = competency
                attachment.filename = request.FILES['attachment'].name
                if attachment.filename.lower().endswith(('.png','jpg','jpeg','.ai','.bmp','.gif','.ico','.psd','.svg','.tiff','.tif')):
                    attachment.file_type = "image"
                if attachment.filename.lower().endswith(('.mp4','.mov','.3g2','.avi','.flv','.h264','.m4v','.mpg','.mpeg','.wmv')):
                    attachment.file_type = "video"
                if attachment.filename.lower().endswith(('.aif','.cda','.mid','.midi','.mp3','.mpa','.ogg','.wav','.wma','.wpl')):
                    attachment.file_type = "audio"
                if attachment.filename.lower().endswith(('.csv','.dif','.ods','.xls','.tsv','.dat','.db','.xml','.xlsx','.xlr')):
                    attachment.file_type = "spreasheet"
                if attachment.filename.lower().endswith(('.doc','.pdf','.rtf','.txt')):
                    attachment.file_type = "text"
                attachment.save()

다음은 저장(commit=False)을 사용하는 예입니다.데이터베이스에 저장하기 전에 사용자가 업로드한 파일 유형을 확인하고 싶습니다.그 필드가 양식에 없어서 첨부된 날짜도 받고 싶었습니다.

간단히 말하면, 여기서 양식 개체를 업데이트하고 지금 당장 데이터베이스에 값을 저장하지 않는다는 것을 알려줍니다. 인스턴스를 사용하여 일부 입력을 변경한 다음 .save()를 사용하여 데이터베이스에 모든 값을 저장할 수 있습니다.

따라서 HTML 양식에서 모든 값을 가져와 요구 사항에 따라 사용자 지정한 다음 인스턴스를 저장할 수 있습니다.

  • save(commit=False)는 개체를 저장할 수 없지만 목록에서 개체를 반환할 수 있으며 장고 관리자에서 제출된 인라인 개체를 사용자 지정하는 데 사용됩니다.*제가 조사하고 실험한 바로는,save(commit=False)Django Admin에서 제출된 인라인 개체를 사용자 지정하는 가장 쉬운 방법입니다.

  • save()와동한에 save(commit=True)개체를 저장한 다음 목록의 개체를 다시 실행할 수 있으며 더 많은 쿼리가 실행되므로 Django Admin에서 제출된 인라인 개체를 사용자 지정하는 데 사용되지 않습니다.

예를 들어, 다음과 같은 것들이 있습니다.Category 및 모델Product가 의 외 키 가 진 모 델 를 Category아래와 같은 모델:

# "my_app/models.py"

class Category(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

그리고 save_formset()을(를) 재정의함print(formset.save())Category가 있는 Product아래 그림과 같이 인라인. *save_formset()인라인 개체를 변경할 때 실행됩니다.

# "my_app/admin.py"

class ProductInline(admin.TabularInline):
    model = Product
    extra = 0
    
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    inlines = (ProductInline,)

    def save_formset(self, request, form, formset, change):
        print(formset.save()) # Here

그리고, 있습니다.Fruits 있는 Apple그리고.Orange아래 표시된 제품:

enter image description here

이제, 나는 변합니다.AppleApple Juice그리고.OrangeOrange Juice아래와 같이 SAVE를 클릭합니다.

enter image description here

그리고나서,Apple 로변됨으로 되었습니다.Apple Juice그리고.Orange 로변됨으로 되었습니다.Orange Juice아래와 같이:

enter image description here

그런 다음 아래와 같이 콘솔의 목록에 2개의 인라인 개체가 반환됩니다.

[<Product: Apple Juice>, <Product: Orange Juice>]

두 는 두 의 그고두인객두로 됩니다.UPDATEPostgre에 따른 질의아래 SQL 로그입니다.*Postgre에서 쿼리를 기록하는 방법을 설명하는 제 답변을 볼 수 있습니다.SQL:

enter image description here

다음으로, 저는 사용합니다.formset.save(commit=False)아래와 같이:

# "my_app/admin.py"

# ...

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    inlines = (ProductInline,)

    def save_formset(self, request, form, formset, change):
        print(formset.save(commit=False)) # Here

다시, 나는 변합니다.AppleApple Juice그리고.OrangeOrange Juice아래와 같이 SAVE를 클릭합니다.

enter image description here

그리고나서,Apple .Apple Juice그리고.Orange .Orange Juice아래와 같이:

enter image description here

그런 다음 아래와 같이 콘솔의 목록에 2개의 인라인 개체가 반환됩니다.

[<Product: Apple Juice>, <Product: Orange Juice>]

두 가 두 개의 그면두인개두체에 .UPDATEPostgre Postgre를 수행합니다.아래 SQL 로그:

enter image description here

.formset.save(commit=False)아래와 같이*다시,save(commit=False)Django Admin에서 제출된 인라인 개체를 사용자 지정하는 데 사용됩니다.

# "my_app/admin.py"

# ...

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    inlines = (ProductInline,)

    def save_formset(self, request, form, formset, change):
        for object in formset.save(commit=False): # Here
            object.name = object.name.upper()
        formset.save()

이제 추가합니다.Vegetable 카고리테,Cucumber그리고.Potato아래와 같이 SAVE를 클릭하면 제품이 표시됩니다.

enter image description here

그리고나서,Cucumber그리고.Potato됩니다.

enter image description here

두 는 두 의 그고두인객두로 됩니다.INSERTPostgre Postgre를 수행합니다.아래 SQL 로그:

enter image description here

.formset.save()아래와 같이*다시,save()와동한에 save(commit=True)더된 인라인 를 사용자 하는 데 사용되지 . Django Admin은 다음과 같은 쿼리를 실행합니다.

# "my_app/admin.py"

# ...

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    inlines = (ProductInline,)

    def save_formset(self, request, form, formset, change):
        for object in formset.save(): # Here
            object.name = object.name.upper()
        formset.save()

이제 다시 한 번 덧붙입니다.Vegetable 카고리테,Cucumber그리고.Potato아래와 같이 SAVE를 클릭하면 제품이 표시됩니다.

enter image description here

에 다시 그고또리.Cucumber그리고.Potato됩니다.

enter image description here

두 객체가 있는데, 이 두 개의 인라인 객체가 .Cucumber그리고.Potato의 2인치 약됩니로 됩니다.INSERT 번째,두 번째, 두 , 두 , 두 , 두 번째, 두 번째, 두 번째.CUCUMBER그리고.POTATO의 2인치 약됩니로 됩니다.UPDATEPostgre Postgre를 수행합니다.아래 SQL 로그:

enter image description here

사용하지 마십시오.save()더 많은 쿼리가 실행되므로 Django Admin에서 제출된 인라인 개체를 사용자 지정합니다.대신에, 당신은 사용해야 합니다.save(commit=False)Django Admin에서 제출된 인라인 개체를 사용자 지정합니다.

언급URL : https://stackoverflow.com/questions/12848605/django-modelform-what-is-savecommit-false-used-for

반응형