Django Admin에서 Form 저장 커스터마이징하기

개발을 파헤치다/Django|2018. 5. 15. 15:30

Django Admin에서 기본적으로 제공하는 Form을 통해 언제든지 Model Instance를 생성할 수 있습니다.

TextField같은 경우 기본적으로 Form에서는 Text Area로 등장하는데 좀 더 다양한 입력을 위해서는 WISYWIG 에디터를 적용해야 합니다.

Summer Note는 가볍고 Django에 적용하기 쉬운 에디터 중 하나입니다.

Summer Note를 적용하고 Form의 save 버튼을 눌렀을 때 있는 그대로 데이터베이스에 저장되지만 때때로 다른 처리가 필요할 수 있습니다.

예를 들면, 서버의 Local에 이미지를 저장하는 것이 아니라 클라우드 서비스에 저장한다던지 같은 예외적인 처리들이 필요할 수 있습니다.

이런 경우에는 Django Admin에서 Form을 전송하여 Model로 변환되고 저장되는 프로세스 중간에 개발자의 로직이 들어가야 합니다.

Django에서는 이를 위해 오버라이딩해서 사용할 수 있는 메서드들을 제공합니다.

from django.contrib import admin

# Register your models here.
from django_summernote.admin import SummernoteModelAdmin

from editor.models import Article


class ArticleAdmin(SummernoteModelAdmin):
summernote_fields = '__all__'

def save_form(self, request, form, change):
return super().save_form(request, form, change)

def save_model(self, request, obj, form, change):
return super().save_model(request, obj, form, change)

admin.site.register(Article, ArticleAdmin)


Django Admin에서 save 버튼을 눌러서 저장하게 되면 위의 save_form과 save_model을 거치게 됩니다.

  • save_form → 이 단계에서는 Form으로 넘어온 데이터를 처리할 수 있습니다.
    아직 Model이 생성되기 전이므로 Form 데이터에 포함된 필드값에 대한 변경이 가능한 단계입니다.
  • save_model → 이 단계에서는 데이터베이스에 저장될 Model 인스턴스와 Form데이터가 함께 오게 됩니다.
    Model에 어떤 값을 넣어서 저장될 지 직접 로직을 처리할 수 있습니다.
    이 단계에서는 Form의 Data필드를 수정해도 반영이 되지 않습니다.



Form은 위의 사진처럼 구성되어 있습니다.

Form의 data 속성에는 Admin 페이지에서 입력한 모든 값들이 포함되어 있습니다.

save_form 메서드에서는 이 값들을 수정할 수 있습니다.

Form의 data 속성은 기본적으로 _mutable이 False로 되어 있습니다.

이것이 의미하는 것은 수정을 할 수 없다는 것입니다.

따라서 아래와 같은 방법을 사용합니다.

 def save_form(self, request, form, change):
data = form.data.copy() # copy()를 사용하면 수정할 수 있는 data가 리턴됩니다
data.update({"contents":"image1.jpg"})
form.data = data # 수정 후 form의 data 속성을 수정한 Query Dict로 바꿔줍니다
return super().save_form(request, form, change)




save_model 메서드는 Form의 data 속성이 모두 입력된 Model Instance가 데이터베이스에 적용되기 전에 호출되는 메서드입니다.

위의 공식문서에서 확인할 수 있듯이 이 메서드에서는 Model이 저장되기 전, 후에 새로운 로직을 추가할 수 있습니다.

  def save_model(self, request, obj, form, change):
data = form.data
html_contents = data.get('contents', None)

html_contents = 'changed'
obj.contents = html_contents
super().save_model(request, obj, form, change)
data = {
'file_name' : 'aaaa',
'image_type' : 'jpeg',
'url': 'http://www',
'related_article': obj,
}
ImageTable.objects.create(**data)
return obj

super().save_model 메서드를 실행하면 실제로 Model Instance가 데이터베이스에 적용됩니다.

따라서 이 메서드 전에 Model에 저장될 내용을 수정할 수 있습니다.

obj가 저장될 모델 인스턴스이기 때문에 이 모델의 속성값에 값을 부여하면 됩니다.

save_model 메서드가 호출되기 전에 obj에는 Form의 data 속성값만 적용되어 있습니다.

pk값은 None으로 표시되어 있는데 아직 데이터베이스에 적용되지 않았기 때문입니다.

save_model메서드를 수행하면 pk값이 부여됩니다. 데이터베이스상에는 row값이 보이지 않을 수 있지만 실제로 저장이 된 것입니다.

이후에는 다른 로직을 처리할 수 있습니다.

위의 예시에서는 저장된 Article Instance로 Foreign Key 제약이 걸린 Image Table의 Instance를 생성하고 있습니다.

댓글()