AI 웹 개발 과정/파이썬 장고 실무 기초

05. 3주차 이론 -

만 기 2022. 5. 30. 10:56

 

Django의 사용자 모델

 

- django의 사용자 모델 테이블 : auth_user

 

- 만든 사용자 모델과 django의 사용자 모델 비교

 

 

 

** class 상속

 

class A:
	def 기능_A_1:
		return '기능_A_1'
	def 기능_A_2:
		return '기능_A_2'

class B:
	def 기능_B_1:
		return '기능_B_1'

 

  • class B에서 class A 의 기능들을 사용하고싶을때!!

 

class B(A):
	def 기능_B_1:
		return '기능_B_1'
  • 괄호() 안에 상속 받고 싶은 클래스명을 넣는다.

 

 

 

 

User 모델 업그레이드

 

1. user 앱의 models.py

class UserModel(models.Model):
    class Meta:     # db table의 이름을 정해준다.(정보를 넣어준다)
        db_table = "my_user"

    username = models.CharField(max_length=20, null=False)
    password = models.CharField(max_length=256, null=False)
  • class UserModel 의 인자에 (models.Model) : models.Model 클래스의 기능들을 사용하겠다 의미

 

 

2. 업그레이드

 

- user 앱의 models.py 에 추가

#user/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser  
# 장고에서 제공하는 기본 유저 모델. auth_user 테이블과 연결

# Create your models here.
class UserModel(AbstractUser):      # 상속
    class Meta:     # db table의 이름을 정해준다.(정보를 넣어준다)
        db_table = "my_user"

    bio = models.CharField(max_length=256, default='')  # 기본 모델에는 bio 없어서 추가해줌
  • UserModel 은 Django의 기본 모델(AbstractUser)을 사용하고 추가적으로 bio를 넣었다. 

 

 

3. 기본모델을 수정했다고 settings.py 파일에서 알려주기

 

- mySpartaSns 폴더의 settings.py 

# mySpartaSns/settings.py
AUTH_USER_MODEL = 'user.UserModel'  # 장고의 기본모델을 바꾸겠다고 알려준다.

 

 

4. 수정됨 알려주고 적용시키기

 

  • python manage.py makemigrations
  • python manage.py migrate
  • 데이터베이스 초기화

 

 

 

 

django 사용자 모델 적용 : 회원가입 수정

 

1. user/views.py 수정

from django.contrib.auth import get_user_model  # 사용자가 데이터 베이스 안에 있는지 검사해주는 함수


# Create your views here.
def sign_up_view(request):
    if request.method == 'GET':
        return render(request, 'user/signup.html')
    elif request.method == 'POST':
        # html에서 name='username' 이름으로된 데이터를 가져온다. 없다면 빈칸처리
        username = request.POST.get('username',None)
        password = request.POST.get('password',None)
        password2 = request.POST.get('password2',None)
        bio = request.POST.get('bio',None)

        if password != password2:
            return render(request, 'user/signup.html')
        else:
            exist_user = get_user_model().objects.filter(username=username)
            # exist_user = UserModel.objects.filter(username=username)
            # .filter는 데이터가 없어도 에러발생을 안함

            if exist_user:
                return render(request, 'user/signup.html')
            else:
                UserModel.objects.create_user(username=username, password=password, bio=bio)

                # new_user = UserModel()    # 만든모델 사용할때 추가
                # new_user.username = username
                # new_user.password = password
                # new_user.bio = bio
                # new_user.save()

                return redirect('/sign-in')
  • get_user_model 임포트 :   사용자가 데이터 베이스 안에 있는지 검사해주는 함수
  • get_user_model().objects.filter(username=username) : get_user_model() 함수의 username 같은지 
  • UserModel.objects.create_user(username=username, password=password, bio=bio) : UserModel 클래스에 creat_user() 적용

 

2. 데이터베이스 my_user 더블클릭해서 확인

 

  • 자동적으로 비밀번호가 암호화까지 되어있는것을 알 수 있다.

 

 

 

 

django 사용자 모델 적용 : 회원가입 수정

 

- 회원가입시 django 사용자 모델을 사용해서 비밀번호가 암호화되어 로그인 할때도 django의 인증 기능을 사용해야한다.

 

- user/ views.py

def sign_in_view(request):
    if request.method == 'POST':
        username = request.POST.get('username',None)
        password = request.POST.get('password',None)

        # 인증기능 모듈. 암호화된 비밀번호와 입력된 비밀번호가 일치하는지, 사용자와 일치하는지까지
        me = auth.authenticate(request, username=username, password=password)
        # me = UserModel.objects.get(username=username)
        if me is not None:  # 사용자가 있다면
            auth.login(request, me) # 
            # request.session['user'] = me.username   # session : 사용자정보를 저장할수있는 공간
            return HttpResponse(me.username)
        else:
            return redirect('/sign-in')
    elif request.method == 'GET':
        return render(request, 'user/signin.html')
  • auth.authenticate(request, username=username, password=password) : 암호화된 비밀번호와 아이디 까지 확인해준다.
  • auth.login(request, me) : 사용자 정보가 담긴 me로 로그인 해주는 기능.

 

 

 

 

로그인 후 페이지 이동

 

1. 로그인 후 home.html 화면으로 이동할 수 있도록 html  파일 추가 (templates/tweet/home.html)

 

2. 글쓰기는 tweet 앱 기능으로 들어가기때문에 tweet 앱의 views.py 파일 작성

from django.shortcuts import render, redirect

# Create your views here.

def home(request):
    user = request.user.is_authenticated    # 사용자가 인증을 받았는지(로그인이 되어있는지)
    if user:
        return redirect('/tweet')
    else:
        return redirect('/sign-in')

def tweet(request):
    if request.method == 'GET':
        return render(request, 'tweet/home.html')
  • request.user.is_authenticated : 사용자가 인증을 받았는지 (로그인이 되어있는지) 검사해주는 기능
  • home 이라는 함수에서 사용자가 로그인 했는지 확인 하고, 로그인 여부에 따라서 보여주는 페이지를 나눈다.

 

3. url 연결 작업

  • tweet 앱에 urls.py 생성 후 코드 작성
# tweet/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'), # 127.0.0.1:8000 과 views.py 폴더의 home 함수 연결
    path('tweet/', views.tweet, name='tweet') # 127.0.0.1:8000/tweet 과 views.py 폴더의 tweet 함수 연결
]
  • url 빈칸이면 기본첫페이지

 

  • mySpartaSns 폴더의 urls.py  연결
urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/', views.base_response, name='first_test'),  # test/ url로 views파일의 base_response 함수와 연결 시켜줌
    path('first/', views.first_view, name='first_view'),
    path('',include('user.urls')),  # user의 url과 mySparta의 url 을 연결해줌
    path('',include('tweet.urls')), # user.urls 는 일치하는 url이 없고 tweet.urls가 응답
]

 

  • 로그인 성공시 redirect 주소 변경 (user/views.py)
        if me is not None:  # 사용자가 있다면
            auth.login(request, me) 
            
            return redirect('/')	# 기본 url경로

 

 

 

 

 

로그인 후 메인페이지에서 사용자 정보 표시하기

 

1. 사용자 아이디와 소개 메세지 표시

  • templates/tweet/home.html 파일 수정
<h5 class="card-title"> {{ user.username }} </h5>
<p class="card-text"> {{ user.bio }} </p>

 

2. 로그인 되어있을때 헤더 바꾸기

  • templates/base.html 파일 수정
<form class="form-inline my-2 my-lg-0">
    {% if not user.is_authenticated %}
    <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
            <a class="nav-link" href="/sign-in"> Sign In <span class="sr-only"></span></a>
        </li>
        <li class="nav-item active">
            <a class="nav-link" href="/sign-up"> Sign Up <span class="sr-only"></span></a>
        </li>
    </ul>
    {% else %}
        {{ user.username }} 님 반갑습니다.
    {% endif %}
</form>
  • {{ }}, {% %}

 

3. 로그인 해야만 들어갈 수있는 페이지

  • 인증 받은 사용자만 tweet 메인페이지로 들어갈 수 있기때문에, tweet/home.html로 렌더링 해주는 views.py 파일 수정
def tweet(request):
    if request.method == 'GET':
        user = request.user.is_authenticated
        if user:
            return render(request, 'tweet/home.html')
        else:
            return redirect('/sign-in')
  • request.user.is_authenticated 

 

4. 로그인된 상태에서 로그인페이지랑 회원가입페이지로 가지 않게

  • sign-in, sign-up 화면을 보내는 user앱의 views.py 파일에서 GET method 수정

- sign-up

def sign_up_view(request):
    if request.method == 'GET':
        user = request.user.is_authenticated
        if user:
            return redirect('/')    # / 는 tweet앱에 views.py의 home 함수와 연결
        else:
            return render(request, 'user/signup.html')

 

- sign-in

    elif request.method == 'GET':
        user = request.user.is_authenticated
        if user:
            return redirect('/')
        else:
            return render(request, 'user/signin.html')

 

5. 로그아웃

  • 로그아웃은 user와 관련된 기능이기때문에 user앱의 views.py에 작성
from django.contrib.auth.decorators import login_required	# login_required 사용!

@login_required 	# 사용자가 꼭 로그인이 되어있어야만 접근이 가능한 함수
def logout(request):	
    auth.logout(request)	# django logout 기능
    return redirect('/')

 

  • logout url 연결
urlpatterns = [
    path('sign-up/', views.sign_up_view, name='sign-up'),
    path('sign-in/', views.sign_in_view, name='sign-in'), 
    path('logout/',views.logout, name='logout'),	# logout/ 주소, views파일의 logout 함수 실행
]

 

  • base.html 에 logout 실행시킬 버튼 생성
<form class="form-inline my-2 my-lg-0">
    {% if not user.is_authenticated %}
        <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
                <a class="nav-link" href="/sign-in"> Sign In <span class="sr-only"></span></a>
            </li>
            <li class="nav-item active">
                <a class="nav-link" href="/sign-up"> Sign Up <span class="sr-only"></span></a>
            </li>
        </ul>
    {% else %}
        <ul class="navbar-nav mr-auto">
            <li class="nav-item disabled">
                <span class="nav-Link">
                    {{ user.username }} 님 반갑습니다.
                </span>
            </li>
            <li class="nav-item active">
                <a class="nav-link" href="/logout"> 로그아웃</a>
            </li>
        </ul>
    {% endif %}
</form>
  • {% if not user.is_authenticated %} : 인증 안되어있으면 로그인 로그아웃 버튼 그대로 보여준다
  • <a class="nav-link" href="/logout"> 로그아웃</a> : 로그아웃 버튼 누르면 /logout url 이동