2-4 django model(파이썬에서 data 생성, 읽기, 삭제, 수정) , 사용자 관리

kst5137·2022년 1월 13일

장고 모델을 통해 SQL을 생성/실행 (ORM)
ORM = 객체 관계 매핑
장고 내장 ORM
ORM의 역할 : SQL을 직접 작성하지 않아도 장고 모델을 통해 데이터베이스로 접근한다. (조회/추가/수정/삭제)
(중요) SQL을 몰라도 된다는 것은 아니다. 최소한 내가 작성한 코드가 어떤 SQL을 만들어내는지는 검증할 수 있어야 한다.

0. 기본작업 준비

mysql client unicode에서 create database blog를 치고
use blog 후
show tables로 한번 확인

파이썬 터미널에서 pip install mysqlclient
setting에 database 부분을 다음과 같이 바꿔준다

그 후
터미널에 python manage.py migrate를 치면

수많은 ok를 지나서 완료됨

app폴더 제목은 자유로 하나 만드록
여기서는 board 로 만들예정
python manage.py startapp board

board에 models로 가서

데이터 양식 작성후

settings에 가서

INSTALLED_APPS에 우리가 만든 app폴더 이름을 써주고

python manage.py makemigrations board라고 치면

Migrations for 'board':
board\migrations\0001_initial.py
- Create model Board
라고 나오고 그후 다시
python manage.py migrate 라고 치면 완료

show tables로 한번 확인

board_board가 추가된것을 확인 가능

desc board_board; 를 치면

이것처럼 타입을 확인 가능하다.

django 모델 활용

models.py에

from django.db import models

# Create your models here.
class Board(models.Model):
    title = models.CharField(max_length=200)
    contents = models.TextField()
    create_date = models.DateTimeField(auto_now_add=True)

이렇게 class Board를 만든다.

그후 받은 데이터가 post방식일때 사용할 forms라는 py파일을 만들고

from django import forms
from .models import Board



class BoardForm(forms.ModelForm):
    class Meta:
        model = Board
        fields = ('title', 'contents')

를 입력하면

# html에서 다음과 같이 폼에다가 input넣지 않아도 됨 
# fields값 안에 title과 contents가  input name에 해당
# <!--<form method="post" action="/board/register">-->
# <!--	{% csrf_token %}-->
# <!--	<input type="text" name="title">-->
# <!--	<input type="text" name="content">-->
# <!--	<input type="submit">-->
# <!--</form>-->
<form action = "/board/register" method="post">
   {% csrf_token %}
   {{ boardForm }}
   <input type="submit">
</form>

이정도만 입력해주면 위의 역할을 대신할 수 있다.

1. 데이터 생성하기

1) views.py 내용

def register(request):
    if request.method == "GET":   	
    	#만약 요청이 겟 방식이면
        boardForm = BoardForm()	  	
        #import한 forms. 안의 값인 BoardForm의 값을 board form에 저장합니다.
        return render(request, 'board/register.html',  
                      {'boardForm':boardForm}) 
# 그 후 함수는 board/register.html을 보여주고 위에서 저장한 데이터를 'boardForm'에 저장합니다.
# render라는 함수가 boardForm의 데이터 board폴더에 forms.py 안에 있는 데이터  받아와 board/register.html을 완성시킨다는 개념
이때 'boardForm'은 register.html에서 
<form action = "/comment/register" method="post">
    {% csrf_token %}
    {{ commentForm }}
    <input type="submit">
</form>
폼 안에 {{}}부분에 해당하게된다.
    elif request.method == "POST" :
        boardForm = BoardForm(request.POST)
        만약 요청이 POST 방식이라면 
        #import한 forms. 안의 값인 BoardForm인 입력받은 POST 
        값을 board form에 저장합니다.
        # 모델폼을 이용하면 알아서 다 받아짐
        if boardForm.is_valid():   
        	#boardForm안에 값이 유효한다면
            board = boardForm.save(commit=False)
            #board라는 변수에 BoardForm(request.POST)에서 받아온 값을 저장한다.
            board.save()
            #그후 board를 저장하고
            return redirect('/board/register')
            # 패쓰값 /board/register로 가고 그러면 url로 인해 다시 처음의 def register가 실행됨
           

로 입력하면 이제 우리의 주소 http://127.0.0.1:8000/board/register에 가면 입력란이 있고 여기에 값을 입력하면 그 값이 database에 저장된다.

이 값을 불러와서 다른 페이지에서 보여주려면
views.py에

def posts(request) :
    posts = Board.objects.all()     #board table에서 모든 데이터를 다 가져옴

    return render(request, 'board/list.html',
                  {'posts': posts})

를 작성하고
url에서 패스를 설정하고
path('board/list',board.views.posts)

2) list.html 내용

{% if posts %}   <!--posts안에 데이터가 담겨 있으면 반복문을 실행한다. -->
        {% for post in posts %}   <!--posts안에 있는 것을 하나하나 꺼내서 post에 저장한다  파이썬과 용법 동일함 -->
          <div>
            <tr>
              <td> {{post.id}} </td>  <!--post라는 객체 안에 있는 id를 보여준다 -->
              <td> {{ post.title }} </td>
              <td> {{ post.create_date }}  </td>
            </tr>
          </div>
        {% endfor %}
      {% endif %}

다음과 같이 조건문을 반복하면

이런 형태로 출력 가능하다.

2. 데이터 읽기

1) views.py 내용

def read(request, bid) :
    post = Board.objects.get( Q(id=bid)) 
    #posts = Board.objects.all()     
    위의 내용은 board table에서 모든 데이터를 다 가져오는 것이고 조건을 지정하려면
    .all이 아닌 .get을 사용
    bid에 해당하는 내용이 post에 담기고 게시글의 id를 불러올 것이다
    bid는 사용자가 요청한 게시글에 대한 얘기
    return render(request, 'board/read.html',{'read' : post})
    #board/read.html페이지를 보여주고 Board.objects.get( Q(id=bid))의 값
    을 'read'로 저장한다.
    

2) read.html 내용


    {% if read %}   <!--read안에 데이터가 담겨 있으면 반복문을 실행한다. -->
              <div>
                <tr>
                  <td> {{read.id}} </td>  <!--read라는 객체 안에 있는 id를 보여준다 -->
                  <td> {{read.title }} </td>
                  <td> {{read.contents}}  </td>
                  <td> {{read.create_date }}  </td>
                </tr>
              </div>

    {% endif %}
    

3. 데이터 삭제하기

1) view.py

def delete(request, bid) :
    post = Board.objects.get(Q(id = bid))
    post.delete()
    post는 Board에서 특정조건 id의 값을 저장
    그후 그 값을 삭제
    return redirect('/board/list')
    패스 /board/list로 이동

2) delete.html

내용삭제기 때문에 없음...

4. 데이터 수정하기

1) view.py

def update(request, bid) :
    post = Board.objects.get(Q(id=bid))  #게시글 하나를 가져오는것
    if request.method == "GET" :
        boardForm = BoardForm(instance=post)  
        #특정 조건 id에 해당하는 값을 저장한다.
        return render(request,'board/update.html',{'boardForm' : boardForm})
    elif request.method == "POST" :
        boardForm = BoardForm(request.POST)
        # boardForm에서 사용자가 보내온 데이터를 받느다
        if boardForm.is_valid():   #boardForm안에 값이 유효한다면
            post.title = boardForm.cleaned_data['title']
            #boardForm의 값이 출력되면 html의 형식까지 모든게 서버로 보내지기 때문에
            우리가 필요한 값 'title'만 뽑아내기 위해 cleaned_data를 사용한다.
            post.contents = boardForm.cleaned_data['contents']
            post.save()
            return redirect('/board/list')

2) update.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form  method = "post">
        {% csrf_token %}
        {{boardForm}}
        <input type = 'submit'>
<!--   form에는 원래 버튼을 누르면 action이라고 적힌 부분을 반복하지만 없기 때문에 현재 url로 보낸다.-->


    </form>
</body>
</html>

5. 회원관리 만들기

1) 회원가입

기존에는 데이터를 받을때 models.py에 입력받을 값을 정하고 사용했지만 이번에는 django가 제공하는것 그냥 사용해보기

(1) views.py

def signup(request):
    if request.method == "GET":
        signupForm = UserCreationForm()
        #UserCreationForm()이 장고가 제공하는 것 
        return render(request, 'users/signup.html',{'signupForm': signupForm})

    elif request.method == "POST" :
        signupForm = UserCreationForm(request.POST)
        if signupForm.is_valid():
            signupForm.save()
            return redirect('/users/signup')

(2) html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action = "/users/login" method="post">
    {% csrf_token %}
    {{ loginForm }}
    <input type="submit">
</form>


</body>
</html>

users/signup으로 가면


다음과 같이 미리 준비된 창이 나오고 값을 입력하면 됨
비밀번호의 경우 다음의 규칙이 만족하지 않으면 오류가 남

post형식으로 받은 데이터는 my sql client에 table중

auth_user에 저장이 된다.
select from auth_user\G; 이렇게 치면 저장된 데이터를 하나씩 볼 수 있다.

select
from auth_user를 치면 표형식으로 볼 수 있음

자료가 많아지고 특정 아이디만 보고 싶으면
select * from auth_user where username = 'kst511313' \G; 같이 조건을 걸어도 된다.

2) 로그인

(1) views.py

def userlogin(request) :
    if request.method == "GET":
        loginForm = AuthenticationForm()     <-- 장고가 제공하는 로그인 폼
        return render(request, 'users/login.html',{'loginForm': loginForm})
    elif request.method == "POST" :
        loginForm = AuthenticationForm(request, request.POST) 
        # 로그인만은 신기하게 (request.POST)가 아닌 (request, request.POST)를 사용한다.
        if loginForm.is_valid():    #검증단계
            login(request, loginForm.get_user())
            return redirect('/board/list')
        else :
            return redirect('/users/login')

(2) userlogin.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action = "/users/login" method="post">
    {% csrf_token %}
    {{ loginForm }}
    <input type="submit">
</form>


</body>
</html>

html은 기존의 형태와 같음 {{}}안에 내용만 views.py의 특정 함수에서 보낸 값으로 바꿔주면 됨

3) 로그아웃

(1) views.py


def userlogout(request) :
    logout(request)
    return redirect('/users/login')
    
profile
공부중인 학생

0개의 댓글