일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 파이썬
- gpu 병렬처리
- selenium
- 추천 영상
- python
- flask
- 그리디 알고리즘
- Google Drive
- List
- 유튜브
- DB
- MongoDB
- 아이폰
- docker-compose
- 바로학교
- 리스트
- 충북
- 깃허브
- 장고
- G-Suite
- 단축어
- 알고리즘
- 코딩
- pymongo
- Django
- venv
- 링크
- nocookie
- 구글 드라이브
- 탐욕 알고리즘
Archives
- Today
- Total
SSAMKO의 개발 이야기
Django에서 하나의 폼으로 여러 테이블에 데이터 작성하기 | transaction.atomic 본문
반응형
회원가입 시 하나의 폼 작성으로 school과 adminuser 그리고 Comroom 테이블에 동시에 데이터를 생성해야 했다.
form_valid단계에서 각 field의 정보들로 세 개의 Model에 대한 인스턴스를 생성해서 저장하면 되는 그리 어렵지 않은 문제였지만,
만일 하나의 테이블에는 정상적으로 생성이 되고, 다른 테이블에서는 실패한다면 다시 회원가입을 시도하려고 할 때 문제가 발생할 수 있다.
이런 문제를 해결하기 위해 데이터베이스 트랜젝션Database transaction을 이용해야 한다.
데이터베이스 트랜젝션이란, 두 개 이상의 Query를 처리할 때 하나라도 실패하면 전체를 되돌리도록 query를 단일화 하는 작업으로, ACID라는 특성을 갖는다.
Atomic(원자성), Consistent(일관성), Isolated(독립성), Durable(지속성)
- from <Two scoops of django>
이러한 트랜젝션을 쉽게 처리할 수 있다는 것이 django의 장점 중 하나이다.
그럼 실제 어떻게 사용되는지 살펴보자.
# forms.py
class RegisterForm(forms.Form):
# for School
province = forms.CharField(label='교육청',
widget=forms.Select(choices=province_list)
name = forms.CharField(max_length=64, label='학교명')
ea = forms.IntegerField(label='교내 컴퓨터실 수',
help_text='특별실(스마트패드)을 포함한 수. 최대 5개.',
validators=[MaxValueValidator(5)])
# for AdminUser
user = forms.CharField(max_length=64, label='아이디')
password = forms.CharField(widget=forms.PasswordInput, label='비밀번호')
re_password = forms.CharField(widget=forms.PasswordInput, label='비밀번호 확인')
realname = forms.CharField(max_length=64, label='담당자 이름')
email = forms.EmailField(label='이메일')
# views.py
from django.db import transaction
class RegisterView(FormView):
template_name = 'register.html'
form_class = RegisterForm
success_url = '/' # 사용되지 않음
def form_valid(self, form):
with transaction.atomic(): #트랜잭션
# School query
school = School(
# Put proper data from cleaned_data here
)
school.save()
adminUser = AdminUser(
# Put proper data from cleaned_data here
)
# AdminUser query
adminUser.save()
# Comroom Query
for i in range(int(form.cleaned_data.get('ea'))):
comroom = Comroom(
school=school,
roomNo=i+1,
name=f"컴{i+1}실",
caption='위치, 교실 이용방법, 이용시 주의사항 등'
)
comroom.save()
# Message process
return render(self.request, 'notice.html', {'message': message})
views.py에서 form_valid안에 with 구문을 사용해 transaction.atomic처리를 해주었다.
이렇게 하면 school.save(), adminUser.save(), comroom.save() 중 하나라도 실패할 경우 모든 commit을 roll-back해서 원래 상태도 되돌린다.
이렇게 하면 동시에 여러 개의 query를 ACID를 유지하며 처리할 수 있다.
반응형
'Django' 카테고리의 다른 글
[Django] TestCase 이용해서 테스트 코드 짜기 (0) | 2021.01.14 |
---|---|
[GCP] django 개발서버 배포하기 (0) | 2021.01.13 |
[django] systemd, gunicorn, nginx 서버 배포하기 (0) | 2021.01.12 |
pillow - 이미지 리사이즈 하기 | Django (0) | 2020.05.08 |
한 페이지에서 여러 개의 폼(forms) 다루기 | Django (1) | 2020.03.28 |
Comments