반응형
Django ORM
Object Relational Mapping
스프링에서는 mybatis를 썼었고, 장고에서는 이를 위한 기능이 따로 존재한다!
드디어 models.py를 사용하기 시작합니다~
파이썬의 객체와 DB의 객체를 Mapping해주어야 한다.
그럼 파이썬의 객체는 어떻게 생성하는 가?
- Articles에 models 작성
# models.py
# Create your models here.
class Article(models.Model) :
# articles_article
# CharField 는 글자 수 제한 할 때 사용
title = models.CharField(max_length=150)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
$ python manage.py makemigrations
$ python manage.py migrate articles
- python manage.py makemigrations : DB에 설계도 대로 반영을 해라!!
- migrations폴더에 아래의 설계도가 생성된다.
- python manage.py migrate articles : 해당 aritcles 설계도 대로만 스키마 테이블 만들어달라!
- 실제 DB에 반영되기 위해서는?!
$ python manage.py migrate
CREATE
# 직접 shell창 에서 작업하겠다.
$ python manage.py shell
>>> from articles.models import Article
>>> Article.objects.all()
1. INSERT INTO 테이블명 (column1, column2...) VALUES (values1, values2...)
# 첫 번째 방법
>>> article = Article()
>>> article.title = 'first'
>>> article.content = 'django!!'
>>> article.save()
>>> article
### 실제로 DB가 들어갔는지 확인! (N) 이 생겼어요!
<Article: Article object (1)>
# 두 번째 방법
# 어느 변수에 어떤 값을 넣을건지 명시
# id가 생략되어 있을 뿐, 자동으로 생성된다.
>>> article = Article(title='second', content='django~!')
>>> article.save()
>>> article
<Article: Article object (2)>
# 세 번째 방법
# save() 과정 없이 바로 저장이 된다. DB에 반영하는 방법이 포함되어 있다 !
>>> Article.objects.create(title='third', content'django~~')
<Article: Article object (3)>
- 첫, 두번째 방법은 인스턴스를 생상하고 그 안에 넣었다면 세번째는 그냥 넣어준다.
- 사용 용도가 다른것이다!!!!
READ
2. SELECT * FROM articles_article(테이블명)
# 전체 조회
>>> article = Article.objects.all()
>>> article
<QuerySet [<Article: Article object (1)>, <Article: Article object (2)>, <Article: Article object (3)>]>
## 보기가 좋지 않으니
>>> article[0].title
'first'
## 설정을 해줍시다~~
스키마의 형태가 변경이 되면 migration을 해줘야 하지만 단지 데이터의 출력 형태가 변경되는 것은 쉘 창을 종료하고 다시 켜준다.
$ exit()
$ python manage.py shell
>>> from articles.models import Article
>>> Article.objects.all()
<QuerySet [<Article: 1번째 글 - first : django!!>, <Article: 2번째 글 - second : django~!>, <Article: 3번째 글 - third : django~~>]>
3. SELECT * FROM articles_article WHERE title = 'first'
# 특정 제목 불러오기
>>> Article.objects.filter(title='first')
<QuerySet [<Article: 1번째 글 - first : django!!>]>
>>> Article.objects.create(title='first', content='hahahahahahahaha')
<Article: 4번째 글 - first : hahahahahahahaha>
>>> Article.objects.filter(title='first')
<QuerySet [<Article: 1번째 글 - first : django!!>, <Article: 4번째 글 - first : hahahahahahahaha>]>
SELECT * FROM articles_article WHERE title='first' LIMIT= 1
>>> Article.objects.filter(title='first').first()
>>> Article.objects.filter(title='first').last()
>>> Article.objects.filter(title='first')[0]
<Article: 1번째 글 - first : django!!>
SELECT * FROM articles_article WHERE id=1
PK처럼 고유값을 가지고 있어서 단 하나만 가지고 올 수 있는 방법!
>>> Articles.objects.get(id=1)
>>> Articles.objects.get(pk=1)
<Article: 1번째 글 - first : django!!>
# !!주의점!!
# 1.고유값이 아닌 내용을 필터링 해서 2개 이상의 값이 찾아지면 오류를 발생한다.
# -> .get()은 반드시 하나의 객체만 가져올 수 있다.
# 2. 없는 것을 가지고 오려고 해도 오류가 발생한다.
# -> filter는 빈 쿼리셋이 반환이 된다.
>>> Article.objects.filter(pk=10)
<QuerySet []>
Like / startswith / endswith
# 특정 문자로 가져오기
# XXX__contains : XXX에 해당 ''을 포함하고 있는 객체 반환
>>> Article.objects.filter(title__contains='fir')
<QuerySet [<Article: 1번째 글 - first : django!!>, <Article: 4번째 글 - first : hahahahahahahaha>]>
>>> Article.objects.filter(title__startswith='se')
<QuerySet [<Article: 2번째 글 - second : django~!>]>
>>> Article.objects.filter(content__endswith='ha')
<QuerySet [<Article: 4번째 글 - first : hahahahahahahaha>]>
ASC / DESC
# 오름차순
>>> Article.objects.all().order_by('pk')
# 내림차순
>>> Article.objects.all().order_by('-pk')
## Order_by는 DB단에서 역순으로 가져오는 것이고
## 이것은 이미 가져온 것을 파이썬에서 역순으로 처리하는 것이다.
>>> Article.objects.all()[::-1]
UPDATE
UPDATE articles_article SET title='byebye' WHERE id=1
# 수정
>>> article = Article.objects.get(pk=1)
>>> article.title = 'byebye'
>>> article
<Article: 1번째 글 - byebye : django!!>
## 보이는 shell에는 바뀐 것처럼 보이지만 실제 DB에 저장이 되려면 저장을 해줘야 한다.
>>> article.save()
DELETE
DELETE FROM articles_article WHERE id=1
# 삭제
>>> article = Article.objects.get(pk=1)
>>> article.delete()
(1, {'articles.Article': 1})
>>> article = Article.objects.get(pk=1)
## pk=1은 삭제하고 없기 때문에 오류가 난다.
## delete는 별도로 저장을 해주지 않아도 자동으로 DB에 반영이 된다.
관리자 페이지로 확인하기
python manage.py runserver
- 파이썬에는 슈퍼계정이 존재한다~
# 모든 설정파일을 migrate 해준 뒤 슈퍼유저 생성
$ python manage.py migrate
$ python manage.py createsuperuser
- 이메일 생략하고 비밀번호 1q2w3e4r 설정 후 다시 http://127.0.0.1:8000/admin로 접속
- admin.py에서 커스터마이징하기!
customizing된 admin페이지를 확인할 수 있다 :)
Django ORM 복습 버억
index페이지에 전체 DB 보여주기
# views.py
from articles.models import Article
# Create your views here.
def index(request):
# 전체 데이터 가져오기
# 그 데이터 템플릿에게 넘겨주기
# 템플릿에서 반복문으로 각각의 게시글 pk, title 보여주기
article = Article.objects.all()
context = {
'articles' : article
}
return render(request, 'articles/index.html', context
# index.html
{% extends 'base.html' %}
{% block body %}
<h1>게시판</h1>
<hr>
<a href="{% url 'articles:new' %}">NEW</a>
<a href="{% url 'articles:introduce' %}">introduce</a>
{% for article in articles %}
<h3>{{article.pk}}번 째 글</h3>
<h4>{{article.title}}</h4>
<h5>{{article.content}}</h5>
<hr>
{% endfor %}
{% endblock %}
new페이지에서 글 작성하기
# views.py
from django.shortcuts import render, redirect
def new(request):
return render(request, 'articles/new.html')
def create(request):
title = request.POST.get('title')
text = request.POST.get('text')
Article.objects.create(title=title, content=text)
return redirect('articles:index')
# new.html
{% block body %}
<h1>글 작성 페이지</h1>
<form action="{% url 'articles:create' %}" method="POST">
{% csrf_token %}
<label for="name">제목 : </label>
<input type="text" name="title">
<label for="cnt">내용 : </label>
<input type="text" name="text">
<input type="submit" value="글 작성">
</form>
{% endblock %}
# create.html
{% block body %}
<p>{{ title }}, {{ text }}</p>
{% endblock %}
- csrf_token 이란??
- 내 DB에 어떠한 조작을 할 수 있는 요청을 보낼 땐 항상 세트로 넣어줘야 한다.
- 보안을 위한 것. ( 없어도 요청은 감 )
- redirect를 import하여 index로 redirect한다.
index페이지에서 상세페이지보기
# urls.py
path('<int:article_pk>detail/', views.detail, name="detail"),
# views.py
# 1. 상세 페이지를 보기위한 경로
# 1-1. 특정 게시글에 대한 고유 값
# 1-2. /articles/1/, /articles/2/...
# 2. 해당 게시글에 대한 상세 내용
# 2-1. 게스글의 pk, title, ...
# 3. 인덱스 페이지로 돌아가는 링크
def detail(request, article_pk):
article = Article.objects.get(pk=article_pk)
context = {
'article' : article
}
return render(request, 'articles/detail.html', context)
# index.html
{% for article in articles %}
<a href="{% url 'articles:detail' article.pk %}"><h3>{{article.pk}}번 째 글</h3></a>
<h4>{{article.title}}</h4>
<h5>{{article.content}}</h5>
<hr>
{% endfor %}
# detail.html
{% block body %}
<h1> 상세 페이지^^</h1>
<h2>{{article.pk}}번 째 글</h2>
<h4>제목 : {{article.title}}</h4>
<h5>내용 : {{article.content}}</h5>
<p>생성 시간 : {{article.created_at}}</p>
<p>수정 시간 : {{article.updated_at}}</p>
<a href="{% url 'articles:index' %}">[back]</a>
{% endblock %}
상세페이지에서 글 삭제하기
# urls.py
path('<int:article_pk>/delete/', views.delete, name="delete"),
# views.py
# 1. 특정 글 삭제를 위한 경로 작성
# 1.1 /articles/delete/
# 2. 글 삭제 처리를 해주는 view 작성
# 3. 글 삭제 후, index page로 redirect
# 4. 글 삭제를 위한 링크 detail에 작성
def delete(request, article_pk):
article = Article.objects.get(pk=article_pk)
article.delete()
return redirect('articles:index')
# detail.html
{% block body %}
<h1> 상세 페이지^^</h1>
<h2>{{article.pk}}번 째 글</h2>
<h4>제목 : {{article.title}}</h4>
<h5>내용 : {{article.content}}</h5>
<p>생성 시간 : {{article.created_at}}</p>
<p>수정 시간 : {{article.updated_at}}</p>
<a href="{% url 'articles:delete' article.pk %}">삭제</a>
<a href="{% url 'articles:index' %}">[back]</a>
{% endblock %}
게시글 수정하기
# urls.py
path('<int:article_pk>/edit', views.edit, name="edit"),
path('<int:article_pk>/update', views.update, name="update"),
# views.py
# 1. 특정 글 수정을 위한 경로 생성
# 1-1. /articles/1/edit
# 2. 글 수정 template를 render하는 edit view 작성
# 2-1. 해당 templateㄹ에 form tag 생성
# 2-2. 각 input tag 내부에 기존 내용이 들어있어야 함.
# 3. edit 보낸 데이터 처리를 위한 경로 생성
# 3-1. /articles/1/update
# 4. 글 수정 처리를 하는 update view 작성
# 5. 해당 글 상세 페이지로 redirect
# 6. 글 수정을 위한 edit 링크 해당 글 상세 페이지에 생성
# 6-1. {% url 'articles:edit' articles.pk %}
def edit(request, article_pk):
article = Article.objects.get(pk=article_pk)
context = {
'article' : article
}
return render(request, 'articles/edit.html', context)
def update(request, article_pk):
edit_title = request.POST.get('edit_title')
edit_content = request.POST.get('edit_content')
article = Article.objects.get(pk=article_pk)
article.title = edit_title
article.content = edit_content
article.save()
return redirect('articles:detail', article_pk)
# detail.html
{% block body %}
<h1> 상세 페이지^^</h1>
<h2>{{article.pk}}번 째 글</h2>
<h4>제목 : {{article.title}}</h4>
<h5>내용 : {{article.content}}</h5>
<p>생성 시간 : {{article.created_at}}</p>
<p>수정 시간 : {{article.updated_at}}</p>
<a href="{% url 'articles:edit' article.pk %}">수정</a>
<a href="{% url 'articles:delete' article.pk %}">삭제</a>
<a href="{% url 'articles:index' %}">[back]</a>
{% endblock %}
# edit.html
{% block body %}
<form action="{% url 'articles:update' article.pk %}" method="POST">
{% csrf_token %}
{{ article.pk }}번 째 글
제목 : <input type="text" name="edit_title" value="{{ article.title }}">
내용 : <input type="text" name="edit_content" value="{{ article.content }}">
<input type="submit" value="수정하기">
</form>
<a href="{% url 'articles:index' %}">[back]</a>
{% endblock %}
반응형
'웹 프로그래밍 > [ Django ]' 카테고리의 다른 글
[ Django ] 05. Django relation 1:N (사용자 분할) (0) | 2020.08.11 |
---|---|
[ Django ] 04. Django 로그인/회원가입 구현 (0) | 2020.08.11 |
[ Django ] 03. Django Model-Form 알아보기 (0) | 2020.08.11 |
[ Django ] 02. [예습] 전생 알아보기 (0) | 2020.08.11 |
[ Django ] 00. Django 알아보기 (4) | 2020.08.11 |