티스토리 뷰

반응형

지금은 장고만  url views templates을 활용하여 회원가입의 기초뼈대를 잡을 것이다. 만약 backend만 장고로 하고 vue나 react를 활용하여 연동을 한다면 아래의 url을 참고하여 바로 넘어가자.

 

2020/09/15 - [Web/Django] - Django rest framework_1. 프로젝트시작하기(서버)

2020/09/15 - [Web/Django] - Django rest framework_2. 포스트맨(POSTMAN) 시작하기

2020/09/17 - [Web/Django] - Django rest framework_3. 회원관리(로그인, 회원가입)

2020/09/21 - [Web/Django] - Django rest framework_4. create_check에 user 추가하기

2020/09/21 - [Web/Django] - django rest framework - pillow (이미지파일저장)

 

 

회원가입을 하면 기본적으로 username(ID)과 password 적는 란이 필요하다. 그러면 models.py에서 추가해서 하면 될까? 그러면 비번은 안보이게 하고, DB에서도 비번은 보이면 안되기 때문에 password를 암호화 저장을 해야한다. 하지만, 이런걸 구현하기 위해서 고민을 하지말자. 왜냐하면 장고를 활용하여 편하게 구현하기 위해 프레임워크를 쓰는 것이다. 장고 내부에는 User 클래스유저생성이 가능한 모델폼이 있다. 회원가입을 구현 시 작성하는 Form은 ModelForm을 기반으로 작성하게 된다. 

 

 

우선은 shell_plus로 실습을 해보자. 바로 코드를 보려면 넘어가도 좋다. 기초부분이므로 아래와 같이 간략하게 설치법을 적어보았다.

# shell_plus

# 설치
> pip install django-extensions

# settings.py에 app추가
    'django_extensions',
    
# shell_plus 실행
> python manage.py shell_plus

 

 shell_plus를 실행해 보면 장고 내부 모델과 우리가 지정한 모델이 자동으로 아래와 같이 import된다.

import한거 보면 자동으로 User가 import 된 것을 알 수 있다. 그래서 우리가 앞에서 User DB를 따로 저장하지 않았지만, `python manage.py createsuperuser`로 관리자 아이디를 만들어서 관리자 User를 만들 수 있었던 것이다.

 

관리자 User의 id를 admin으로 만들고 아래와 같이 shell_plus들어가서 처보면, admin이 들어 있는 것을 알 수 있다.

> User.objects.all()
< <QuerySet[<User : admin>]>

즉, 회원가입 구현 시 이 내부의 User 클래스를 가져다 쓰면 된다. 그렇기 때문에 모델 설정도 필요가 없다.

 

 


 

회원가입 로직 구현

기존에 만들어논 프로젝트에서 accounts라는 앱을 추가로 등록하자.

$ python manage.py startapp accounts

startapp accounts 로 계정관리 app을 만들고 settings.py에서 app 등록을 하자.(기초적 부분은 다음 링크에서 확인하자.)

 

 

 

project urls.py

아래와 같이 include를 활용하여 app으로 urls 설정을 지정해 준다.

urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/', include('articles.urls')),
    path('accounts/', include('accounts.urls')),
]

 

 

app urls.py

accounts폴더 안에 urls를 만들고 path를 지정해 준다.

from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
    path('signup/', views.signup, name='signup'),
]

 

 

views.py

우리가 urls.py에서 설정한 signup을 views.py에서 만들어준다.

from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm


# Create your views here.
def signup(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            # 게시글 목록 페이지
            return redirect('articles:index')
    else:
        form = UserCreationForm()
    context = {
        'form': form
    }
    return render(request, 'accounts/signup.html', context)

위의 내용은 사실 create 로직과 같다. 기본적으로 안다고 생각하고 짧게 설명하겠다. 처음 회원가입을 누르면, GET 방식으로 views.py로 들어와서 form에 UserCreationForm()을 받아서 signup.html로 넘겨준다. 그리고 회원가입에서 빈칸일 넣고 회원가입하기를 누르면 POST방식으로 데이터를 받아서 is_valid를 통해 로직의 오류를 확인후에 없으면 DB에 저장한 후에 redirect로 원하는 페이지로 이동하게 만들었다. 이제 UserCreationForm()에 대해 알아 본 후에 signup.html을 완성해 보자.

 

 

 

UserCreationForm

개념의 시작은 공식문서이다. 우선 공식문서 확인해보자.

github django 검색해서 django/contrib/auth/forms.py를 들어가보자. 그리고 81번째 줄 부터 보면 된다.

https://github.com/django/django/blob/master/django/contrib/auth/forms.py#L104

 

django/django

The Web framework for perfectionists with deadlines. - django/django

github.com

class UserCreationForm(forms.ModelForm):
    """
    A form that creates a user, with no privileges, from the given username and
    password.
    """
    error_messages = {
        'password_mismatch': _('The two password fields didn’t match.'),
    }
    password1 = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
        help_text=password_validation.password_validators_help_text_html(),
    )
    password2 = forms.CharField(
        label=_("Password confirmation"),
        widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
        strip=False,
        help_text=_("Enter the same password as before, for verification."),
    )

    class Meta:
        model = User
        fields = ("username",)
        field_classes = {'username': UsernameField}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self._meta.model.USERNAME_FIELD in self.fields:
            self.fields[self._meta.model.USERNAME_FIELD].widget.attrs['autofocus'] = True

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError(
                self.error_messages['password_mismatch'],
                code='password_mismatch',
            )
        return password2

    def _post_clean(self):
        super()._post_clean()
        # Validate the password after self.instance is updated with form data
        # by super().
        password = self.cleaned_data.get('password2')
        if password:
            try:
                password_validation.validate_password(password, self.instance)
            except ValidationError as error:
                self.add_error('password2', error)

    def save(self, commit=True):
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

 

특징은 아래와 같다.

 

1. UserCreationForm은 forms의 ModelForm을 상속 받고 있다.

 코드 보면 password1과 password2로 input를 2가지를 따로 받는다. 2개가 같은지 검증하기 위해서 독립적으로 2개 필드를 만들었다고 보면 된다.

 

2. 내부적으로 User를 받는다.

class Meta: 부분을 보면 Model은 User로 받고 fields는 Username이 있는걸 알 수 있다. User관련 추가적인 정보는 아래의 링크를 확인해보자.

2021/01/04 - [Web/Django] - [Django]사용자인증관리_User모델, 비밀번호 암호화

 

3. def clean_password2(self) 에서는 패스워드를 검증하는 작업을 한다.

 

4. def save(self, commit=True)는 저장 로직이다.

저장하기 전에 비번을 추가 설정 후에 저장한다.

 

위의 특징들을 이용하고 활용만 잘하면 된다.

 

 

게시판과 User의 가장 큰 차이

게시판에서 Article과 같이 기존의 models.py에서 정의한 DB들은 단순 저장이 되지만, User DB를 저장 시 단순 저장이 불가하다. 왜냐하면 User는 저장 시 password1과 password2가 맞는지 비교 후에 검증(둘다작성되어있고 같은가) 후에 저장을 하기 때문이다.

 

좀 더 정확한 개념을 알기위해서는 추가적은 개념은 User 게시물에서 확인하자. 물론 1:N과 N:M의 개념을 안 이후에 참고하는 것이 좋다.

2020/08/23 - [Web/Django] - [Django]데이터베이스관리(1:N)_User와 Article

2020/08/24 - [Web/Django] - [Django]데이터베이스관리(1:N)_댓글 기능 추가하기

2020/08/28 - [Web/Django] - [Django]데이터베이스관리(N:M)_좋아요 기능 구현

2020/08/29 - [Web/Django] - [Django]데이터베이스관리(N:M)_팔로우 기능 구현(custom user)

 

 

 

 

templates 완성

url과 views까지 완성했으니, templates를 완성해보자. 물론 Vue나 react와 연결을 하려면 아래의 링크를 참고하면 좋다. 그러나 우리는 기본개념이 우선이기 때문에 장고에서 html을 작성하도록 한다.

2020/09/15 - [Web/Django] - Django rest framework_1. 프로젝트시작하기(서버)

2020/09/15 - [Web/Django] - Django rest framework_2. 포스트맨(POSTMAN) 시작하기

2020/09/17 - [Web/Django] - Django rest framework_3. 회원관리(로그인, 회원가입)

 

 

accounts/templates/signup.html

간단하게 회원가입이 사용자가 보여지게 만들어 보자.

{% extends 'base.html' %}
{% block body %}
    <form action="" method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button>회원가입 신청</button>
    </form>
{% endblock %}

 

우리는 views에서 UserCreationForm를 form에 넣어서 context로 html으로 보냈다. 따라서 우리가 설정했던, '이름' '비밀번호' '비밀번호확인' 이렇게 세가지가 뜬다.

# 서버실행
$ python manage.py runserver

서버 켜서 회원가입 후에 관리자 page 들어가서 사용자 확인해 보면, 가입이 된것을 볼 수 있다.

 

 

signup.html+bootstrap

장고에 최적화된 부트스트랩을 적용했다면 아래와 같이 사용가능하다. 설치와 사용법은 아래와 같다.

https://django-bootstrap4.readthedocs.io/en/latest/

 

Welcome to django-bootstrap4’s documentation! — django-bootstrap4 2.0.2 documentation

© Copyright 2020, Dylan Verheul Revision 8c7d5e3c.

django-bootstrap4.readthedocs.io

{% extends 'base.html' %}
{% load bootstrap4 %}
{% block body %}
    <form action="" method="POST">
        {% csrf_token %}
        {% bootstrap_form form %}
        <button class="btn btn-primary">회원가입 신청</button>
        <a href="{% url 'accounts:login' %}">로그인</a>
    </form>
{% endblock %}

 


아래의 내용은 로그인을 공부한 이후에 추가해 줘도 된다.

 

위와 같은 코드의 가장 큰 문제가 있다. 아직 로그인이 된 상태에서 회원가입을 누르면, 회원가입으로 이동이 가능하다. 들어가지 않게 하기 위해서 html에서 링크를 표현하지 않아도 되지만, 내부 장고 코드에서도 반영해 줘야 url로도 접근이 불가능하다.

 

로그인에 대한 내용은 아래에서 참고하자.

2020/08/13 - [Web/Django] - [Django]사용자인증관리_login, 쿠키와 세션, 캐쉬

2020/08/13 - [Web/Django] - [Django]사용자인증관리_logout

 

아래와 같이 views.py에 is_authenticated를 추가한다.

# accounts/views.py
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
def signup(request):
    if request.user.is_authenticated:
        return redirect('articles:index')
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            # 게시글 목록 페이지
            return redirect('articles:index')
    else:
        form = UserCreationForm()
    context = {
        'form': form
    }
    return render(request, 'accounts/signup.html', context)

 

기본적으로 settings.py의 설정에 의해서 templates에서는 import 없이 사용가능한 것들이 있다. 즉, templates에서는 settings.py의 설정에 의해 user를 그냥 써도 되지만, views에서는 import가 필수적이다. request에서 user를 가져와야한다. 이부분 관련 공식문서는 아래와 같다.

RequestContext 관련 문서는 이곳을 클릭하면 넘어간다. 참고하자.

 

 

 

 

 

 

다음은 회원의 CRUD 중 detail 부분의 회원인증 관리를 공부해 보자.

han-py.tistory.com/146

 

[Django]사용자인증관리_Detail(프로필보기) get_user_model

0. 들어가면서 이부분은 Detial 페이지이다. 사용자 아이디를 누르면 들어오는 곳이다. 초기 detail.html 코드부터 나중에 좋아요와 팔로우 기능 구현까지 적용된 detail.html까지 여러 가지를 넣어둘 예

han-py.tistory.com

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함