- 인스타그램 클론 코딩의 일환으로 회원가입 페이지를 만들던 중
- 회원가입을 완료하고 로그인하면 오류가 뜸
- 회원가입한 유저의 프로필 이미지와 닉네임이 없어서 오류 발생
첫번째 시도
Model에서 profile_photo 디폴트 설정
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE) # 장고 유저모델 사용
nickname = models.CharField(max_length=20) # 회원가입 페이지에서 값을 받을 것임
profile_photo = models.ImageField(
upload_to="profile/", blank=True, default="default/person.png") # 기본으로 익명 그림 받음
slug = models.SlugField(blank=True, null=True) # save함수 오버라이드로 소문자 nickname를 자동으로 설정
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.nickname)
super().save(*args, **kwargs)
def get_absolute_url(self):
return resolve_url("accounts:profile", self.slug)
- Profile 폼이 save되야 값이 비더라도 들어가는 것이었음
- 따라서 회원가입 페이지는 User 폼밖에 없기 때문에 Profile은 여전히 빈 데이터 상태로 오류뜸
두번째 시도
View에서 데이터 가공
class UserCreate(CreateView):
template_name = "registration/signup.html"
form_class = CreateUserForm
success_url = reverse_lazy('accounts:create_user_done')
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
if self.request.POST:
ctx['user_form'] = CreateUserForm(self.request.POST)
ctx['profile_form'] = ProfileForm(self.request.POST)
else:
ctx['user_form'] = CreateUserForm()
ctx['profile_form'] = ProfileForm()
return ctx
- 모델은 User로 유지하고, get_context_data 오버라이드 함
- POST와 GET 분리해서 폼 2개 데이터로 받음
def form_valid(self, form):
ctx = self.get_context_data()
profile_form = ctx["profile_form"]
if profile_form.is_valid() and form.is_valid(): # form은 CreateView에서 form_class로 지정한 폼
profile = profile_form.save(commit=False)
user = form.save(commit=False)
profile.user = user # 1:1관계 연결
form.save()
profile_form.save()
return redirect(self.success_url) # 설정한 success_url로 리다이렉트
- DB에 저장하기 전에 commit 잠시 멈추고
- 같은 페이지에 있지만 별개의 폼이므로 장고는 누구 Profile 데이턴지 모름
- 1:1관계인 User 객체와 연결 후 DB에 저장
HTML
<form method="post" class="signup_form" enctype="multipart/form-data">
{% csrf_token %}
<!-- User.email input -->
{% render_field user_form.email class="signup_email" placeholder="이메일 주소" %}
<!-- User.Profile.nickname input -->
{% render_field profile_form.nickname class="signup_nickname" placeholder="닉네임" %}
<!-- User.username input -->
{% render_field user_form.username class="signup_username" placeholder="아이디" %}
<!-- User.password input -->
{% render_field user_form.password1 class="signup_pw" id="signup_pw1" placeholder="비밀번호" %}
{% render_field user_form.password2 class="signup_pw" id="signup_pw2" placeholder="비밀번호 확인" %}
<button type="submit" class="signup_btn">가입</button>
</form>
- Profile 모델의 닉네임만 받아서 저장
- PrifileForm이 저장되므로 '첫번째 시도'에서 디폴트로 설정한 기본 이미지가 자동으로 설정될 것임
- 가입 후 리스트페이지도 잘 나오고 nickname과 profile_photo도 잘 들어가 있음
결론
- get_context_data로 GET POST 데이터를 받고 보냄
- form_valid로 DB 저장 전 폼 데이터 수정 가능
https://stackoverflow.com/questions/12573992/multiple-forms-and-formsets-in-createview
'Backend > Python' 카테고리의 다른 글
[인스타그램클론] 폼 에러메시지 표시 (0) | 2020.07.18 |
---|---|
[인스타그램 클론] Vanilla JS - AJAX (0) | 2020.06.08 |
중복값 갯수(collections.Counter) (0) | 2020.05.02 |
[인스타그램 클론] 프로필 페이지 (0) | 2020.04.28 |
form 이미지 업로드 (0) | 2020.04.22 |