CRUD를 restful하게 바꿔보기 + image 업로드
crud = function based view || class based view
Restful
new / create 묶기
edit / update 묶기
1
2
3
4
5
6
7
8
9
10
11
# photo urls.py
from django.urls import path
from . import views
app_name= "photos"
urlpatterns = [
path("", views.list, name="list"),
# / 오류 적게?
## class based view에서 list를 사용
]
1
2
3
4
5
# photo views.py
from django.shortcuts import render
def list(request):
return render(request, "photo/list.html")
1
# base.html 생성 후 list.html 생성
1
2
3
4
5
6
7
8
9
# base.html
<!--예전에 쓰던 url 코드-->
<li><a href="/photos/list/">Home</a></li>
<!--앞으로 바꿀 url 코드-->
<!--변수처럼 사용! -->
<li><a href="{% url 'photos:list '%}">Home</a></li>
<li><a href="{% url 'photos:create' %}">Create</a></li>
글작성(create)
1
2
3
4
5
# photo urls.py
# new를 만들지 않는다~
# 하나로 통합! --> restful하다
path("create/", views.create, name="create"),
1
2
3
4
5
6
7
8
# models.py
from django.db import models
class Photo(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
1
2
3
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py createsuperuser
1
2
3
4
5
# photo admin.py
from django.contrib import admin
from .models import Photo
admin.site.register(Photo)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# photo views.py
## 지금껏 create / new라는 두개의 url로 create를 구현
### get방식 create 1개랑
### post방식 create 1개를 나누어서 분리 구현
def create(request):
if(request.method == "POST"):
# POST방식으로 들어왔을 때
# 데이터를 저장
pass
else:
# GET방식으로 들어왔을 때
# 입력할 수 있게 폼을 제공
return render(request, "photo/create.html")
get방식
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# create.html
{% extends "photo/base.html" %}
{% block bb %}
# action을 없애고 메소드만 POST로
## action을 지정해 주지 않아도 photos/create/로 ...
## 기본적을 지정해 주지 않았을 때 현재의 url로 방식만 POST로 바꿔서 그대로 보내주게 됨
<form method="POST">
{% raw %}{% csrf_token %}
<input type="text" name="title"/>
<input type="text" name="content"/>
<input type="submit" value="Submit"/>
</form>
{% endblock %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# photo views.py
## 지금껏 create / new라는 두개의 url로 create를 구현
### get방식 create 1개랑
### post방식 create 1개를 나누어서 분리 구현
def create(request):
if(request.method == "POST"):
# POST방식으로 들어왔을 때
# 데이터를 저장
title = request.POST.get("title")
content = request.POST.get("content")
Photo.objects.create(title=title, content=content)
return redirect("photos:list")
else:
# GET방식으로 들어왔을 때
# 입력할 수 있게 폼을 제공
return render(request, "photo/create.html")
리스트페이지에 보여주기
1
2
3
4
# views.py
def list(request):
photos = Photo.objects.all()
return render(request, "photo/list.html", {"photos":photos})
1
2
3
4
5
6
7
8
9
10
11
# list.html
{% extends "photo/base.html" %}
{% block bb %}
<h1>여기는 리스트 페이지</h1>
{% for photo in photos %}
<h3>{{photo.title}}</h3>
{% raw %}{% endfor %}
{% endblock%}
읽기(read) - detail
1
2
# photo urls.py
path("<int:id>/", views.detail, name="detail")
1
2
3
4
5
# photo views.py
def detail(request, id):
photo = Photo.objects.get(id=id)
return render("photos/detail.html", {"photo":photo})
1
2
3
4
5
6
7
8
9
10
11
# detail.html
{% extends "photo/base.html" %}
{% block bb %}
<h2></h2>
<h3></h3>
<h4></h4>
<h4></h4>
{% endblock%}
update
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# photo views.py
def update(request,id):
if(request.method == "POST"):
photo = Photo.objects.get(pk=id)
title = request.POST.get("title")
content = request.POST.get("content")
photo.title = title
photo.content = content
photo.save()
return redirect("photos:detail", photo.id)
else:
photo = Photo.objects.get(pk=id)
return render(request, "photo/update.html", {"photo":photo} )
1
2
3
4
5
6
7
8
9
10
11
12
13
# update.html
{% extends "photo/base.html" %}
{% block bb %}
<form method="POST">
{% csrf_token %}
<input type="text" name="title" value=""/>
<input type="text" name="content" value=""/>
<input type="submit" value="Submit"/>
</form>
{% endblock %}
delete
1
2
# photo urls.py
path("<int:id>/delete/", views.delete, name="delete"),
1
2
3
4
5
6
# photo views.py
def delete(request, id):
photo = Photo.objects.get(pk=id)
photo.delete()
return redirect("photos:list")
1
2
# detail.html
<a href="{% url 'photos:delete' photo.id %}">삭제</a>
정적파일 static
-
static 폴더안에 base.css생성
- static 폴더안에 css , img, js, 폴더로 따로따로 만들어서 정리
- setting.py 안에 121 line STATIC_URL = 에 따로 경로
1
2
3
4
# static base.css
h1 {
color:red;
}
1
2
3
4
5
6
# photo base.html
<!-- 맨 위에 -->
{% load static %}
<!-- head부분에 추가 -->
<link rel="stylesheet" href="{% static 'base.css' %}" type="text/css" />
1
2
<!-- 파비콘 넣기 -->
<link rel="shortcut icon" href="{% static 'img/a.jpg' %}">
404 page
사용자가 입력한 이미지 column 추가
폼 구성
1
2
3
4
5
# models.py
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill, ResizeToFit
image = models.ImageField(blank=True)
1
2
3
4
# 외부라이브러리 추가 (ImageField를 사용하기 위해)
$ pip install Pillow
$ pip install pilkit
$ pip install django-imagekit
1
2
$ python manage.py makemigrations
$ python manage.py migrate
1
2
3
4
5
# photo create.html에 추가
## 파일 업로드시 form에 enctype 추가
<form method="POST" enctype="multipart/form-data">
## 이미지 형식 아니면 안받겠다
<input type="file" name="image" accept="image/*"/>
저장
1
2
3
# photo views.py
## create에 추가
image = request.FILES.get("image")
1
2
# detail.html 추가
<img src="" alt=""></img>
1
2
3
4
5
# setting.py
## 이미지 업로드된 장소를 지정해주기 위해
### 맨 밑에
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
1
2
3
4
5
6
7
# mysite urls.py
# django static 파일을 넣으려면 추가
from django.conf.urls.static import static
from django.conf import settings
## 위에 urlpatterns에 추가
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
이미지 리사이징
-
원본 / 서비스 / 섬네일 3가지 사이즈로
-
이미지 리사이징을 위한 라이브러리 설치
1
2
$ pip install pilkit
$ pip install django-imagekit
1
2
3
# setting.py
INSTALLED_APPS에 추가
'imagekit',
1
2
3
4
5
6
7
8
9
10
11
# models.py
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill, ResizeToFit
# 기존 image를 주석
image = ProcessedImageField(
upload_to = "photo/image",
processors = [ResizeToFill(150, 150)],
format = 'JPEG',
options = {"quality":90}
)
makemigrations / migrate
- 필드가 바뀔때는 다시해야하지만 안의 함수를 수정할 때는 상관 없음