instagram 만들기 (1)유저 지정 및 회원가입
2022. 4. 4. 01:31
- 커스텀 유저생성(user model)
- 아이디 / 암호 / 이메일 /이름을 받아서 회원가입 구현
1. Usermodel 생성
- accounts app 생성
- accounts app의 models.py에서 Usermodel을 생성
- Abstractuser를 상속받았음 > AbstractUser에서 제공하는 필드들(first_name,last_name,email....)을 그대로 사용
#accounts/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
website_url = models.URLField(blank=True, max_length=200)
bio = models.TextField(blank=True)
phone_number = models.DecimalField(blank=True,max_digits=12,decimal_places=0)
2. AUTH_USER_MODEL 설정
- 생성한 usermodel에 대해 AUTH_USER_MODEL 설정
- 이 프로젝트 내부에서 돌리는 usermodel은 accounts.user라는 것임
#settings.py
AUTH_USER_MODEL = "accounts.User"
3. 회원가입을 정보를 담을 form 구현
- 참고)form을 쓰는 이유 : https://han-py.tistory.com/87?category=907665
- 사용자가 정보를 적을 수 있게 form양식을 사용자에 주고
- 사용자가 그 form에 제출한 정보를 담아 views에서 받고, db로 처리해줌
- 즉 정보를 담는 통 역할을 함
- forms.py에서 회원가입을 위한 정보를 담을 통인 signupform 구현
- 비밀번호에 관한 로직(암호화, 비밀번호 확인)등을 위해 usercreationform을 사용
- 참고로 usercreationform은 usermodel을 상속받는 모델폼임. 즉 usermodel기반의 modelform에 이런저런 기능등을 갖다 붙인 것임
- __init__
- 원래 설정된 기능이 정상작동 하도록 super사용
- __super__.__init__ 하고나서야 filed값이 생겨서, 아래의 fields.required가 가능하다.
- fileds.required 값을 필수로 수정하기 위해 사용
- Meta : 모델폼에서 사용되는 장고 고유의 문법으로, form의 데이터 자체에 대해서 설정
- 연동되는 모델 = get_user_model(). get_user_model()을 하면 현재 활성화된 모델을 가져올 수 있음
- 모델의 데이터 필드들 중, 받을 데이터의 필드 = username~phone_number
- clean_field
- 참고(https://www.inflearn.com/questions/490676)
- form.cleaned_data는 유효성 검사가 시작되는 시점에 빈 사전으로 초기화가 진행되며, 각 필드(폼에서 받는 데이터필드)에 대한 값들이 업데이트 됨
- 유효성 검사 과정에서, 각 Form field별 유효성 검사를 수행한 후, form 인스턴스에 clean_필드명 이름의 속성이 있을 경우 이를 호출함
- clean_필드명 함수의 반환값은 cleaned_data에 저장됨(즉 마치, 유효성검사후에 clean_field명 함수로 유효성검사를 한번 더 진행하는 것같은 느낌임)
- 의문점)cleaned_data에는 필드별 모든 정보가 담기는 걸로 알고 있는데, clean_필드명 함수가 없다면 그냥 함수를 거치지 않고 바로 담기는지?
#accounts/forms.py
class SignupForm(UserCreationForm):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
#print(self.field['email'].required)
self.fields['email'].required = True
self.fields['first_name'].required = True
self.fields['last_name'].required = True
self.fields['phone_number'].required = True
class Meta(UserCreationForm.Meta):
#Meta도 usercreationform의 메타이기 때문
model = get_user_model()
#model도 직접적으로 설정을 해줘야 함. auth에 있는 모델에 의존하고 있기 때문
fields = ['username','email','first_name','last_name','phone_number']
#form이 제출될 때, clean_field형식의 함수들이 자동으로 호출이 됨?
#답변 form.cleaned_data는 유효성 검사가 시작되는 시점에 빈 사전으로 초기화가 되며, 유효성 검사 과정에서 각 필드에 대한 값들이 업데이트됨
def clean_email(self):
email = self.cleaned_data.get('email')
if email:
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("이미 등록된 이메일 주소입니다.")
return email
def clean_phone_number(self):
phone_number = self.cleaned_data.get('phone_number')
if phone_number:
qs = User.objects.filter(phone_number=phone_number)
if qs.exists():
raise forms.ValidationError("이미 등록된 전화번호 입니다")
return phone_number
4. views.py
- get으로 요청이 왔다 > 빈 signupform을 담은 html파일 랜더링 > 사용자가 정보 입력
- 동일한 url로 post요청하면서 입력된 정보를 전달 > views에서 받아서, form객체에 해당 요청의 post메서드 값을 담음
- form에 담겨져 오는게 아니라, 데이터를 받고 이때 form에 넣어주는 것임
- 즉 처음에 보내주는 빈 signupform과 나중에 받는 데이터가 연결되어 있는게 아닌 듯함..
- 데이터를 form에 담은 후, 각 데이터필드 별로 유효성 검사를 진행 > 문제가 없으면 form.save실행(db에 데이터 저장)
- form인스턴스 하나가 db한줄이라고 생각하면 된다
- url로 통해 들어오는 get값에서 next를 가져오고, next가 없으면 '/'를 가져와서 next_url로 받음
- 원래 사용자가 접근하려 했던 경로가 존재할 경우(그러니까, 특정 접근 도중에 회원가입을 하라고 요청받을 경우) 원래 접근하려 했던 경로가 url에 next쿼리스트링 값으로 노출된다
- ex) http://127.0.0.1:8000/accounts/signup/?next=article/4/update
- 그리고 이 next의 쿼리스트링 값을, request.Get으로 접근할 수 있다. 참고로 어떤 메서드이든지 get요청에 대한 부분은 존재할 수 있다. url로 접근을 하기 때문임
- 또한 request.GET은 querydict형태로, dict에서 사용가능한 get메소드 등을 사용할 수 있다.
- 따라서 next_url = request.Get.get('next','/')로 받아줌. next가 존재하면 next string의 값을 받아서 원래 사용자가 가려했던 곳으로 다시가게 해주고 , 없으면 '/'으로 즉 root경로로(홈페이지로) 이동하게 됨
- 만약 next값이 없다면 홈페이지('/')로 이동
- 추가) '/'로 이동한다는 것은 'http://127.0.0.1:8000/' 로 이동을 한다는 것임
#accounts/views.py
def signup(request):
if request.method == "POST":
form = SignupForm(request.POST)
if form.is_valid():
form.save()
messages.success(request,"회원가입을 환영합니다!")
next_url = request.Get.get('next','/')
#post메소드여도, url을 통해 들어오는 get값이 있음
return redirect(next_url)
else:
form = SignupForm()
return render(request,'accounts/signup_form.html',{
'form':form,
})
5 . html파일
- html파일부분은 크게 다루지 않을 생각임. 다만 각 챕터별로 사용된 방법(?), 기술(?)에 대해서 적으려 함
message
- 바로위에 views.py에 보면 messages에 관한 부분이 있음
- 로그인 성공시 message 객체를 보내는 건데, message가 존재할 경우 다음과 같이 html파일에서 표시해주도록 할 수 있음
- 이런식으로 짤 경우, message들이 div태그안에 담겨져서 보이게 되며, message들이 여러개라면 다같이 보이게 됨
{% if messages %}
{% for message in messages %}
<div class = "alert alert-{{ messages.tag }}" >
{{ message }}
</div>
{% endfor %}
{% endif %}
extends와 include를 함께 사용
- extends로 accounts/layout.html 파일을 땡겨와서(extend) 해당 파일안에 자신(signup_form.html)을 담음
- 자신 안에는 _form.html을 들고와서 포함시킴(include)
- 포함시킬 때, with를 사용해서 특정 변수(submit_label)에 대한 값을 주었음
#signup_form.html
{% extends 'accounts/layout.html' %}
{% load bootstrap5 %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-sm-8 offset-sm-2">
{% include "_form.html" with submit_label="회원가입" %}
</div>
</div>
</div>
{% endblock %}
#_form.html
{% load bootstrap5 %}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %} {% bootstrap_form form %} {% buttons %}
<button type="submit" class="btn btn-primary">
{{ submit_label|default:"" }}
</button>
{% endbuttons %}
</form>
추가로 해보고 싶은 것
- form자체를 좀 이쁘게 (인스타그램처럼)꾸며보고 싶음. 하는 방법이 있는데 나중에 찾아볼 것
'django > 프로젝트' 카테고리의 다른 글
SignUp , SignIn , Jwt token // django 인스타그램 api(1) (0) | 2022.04.24 |
---|---|
instagram만들기(3)로그인 / 로그아웃 구현 (0) | 2022.04.07 |
수정필요!)instagram 만들기 (2)회원가입 환영 이메일 보내기 (0) | 2022.04.06 |
instagram 만들기(0) (0) | 2022.04.03 |
Django로 pinterest 만들기(0) (0) | 2022.01.27 |