5월31일 TIL (Django 특강 코드리뷰)
프로젝트의 내용, 구현해야하는 목록들
- 1. Django 프로젝트를 생성하고, blog 라는 앱을 만들어서 settings.py 에 등록해보세요.
- 2. Models.py 에 <글 제목, 글 카테고리, 글 내용>이 들어갈 수 있는 Article 이라는 모델을 만들어보세요.
- 3. Models.py 에 <카테고리 이름, 설명>이 들어갈 수 있는 Category 라는 모델을 만들어보세요.
- 4. Article 모델의 글 카테고리에는, Category 모델에 존재하는 카테고리만 들어갈 수 있도록 만들어보세요. (힌트: Foreign Key)
- 5. Admin 페이지를 통해서, Category 모델에 ‘영화’, ‘드라마’, ‘예능’ 이라는 카테고리를 각각 생성해보세요.
- 6. 새 글을 작성할 수 있도록, templates 폴더 안에 form 태그가 존재하는 new.html 을 만들고, Views.py 과 Urls.py 에 적절한 코드를 작성해보세요.
- 7. 카테고리 목록을 볼 수 있도록, templates 폴더 안에 카테고리 이름을 리스팅하는 category.html 을 만들고, Views.py 과 Urls.py 에 적절한 코드를 작성해보세요.
- 8. 작성된 글 목록을 볼 수 있도록, templates 폴더 안에 글 제목을 리스팅하는 article.html 을 만들고, 사용자가 category.html 에서 클릭한 카테고리에 해당하는 글만 필터링하여 보여주도록 Views.py 과 Urls.py 에 적절한 코드를 작성해보세요.
- 9. 특정한 글의 내용을 볼 수 있도록, templates 폴더 안에 글의 제목과 내용을 보여주는 detail.html 을 만들고, 사용자가 article.html 에서 클릭한 글에 해당하는 제목과 내용을 보여주도록 Views.py 와 Urls.py 에 적절한 코드를 작성해보세요.
10. (심화) category.html 에서 카테고리 목록을 보여줄 때, 카테고리 별 글의 개수까지 함께 보여줄 수 있도록 코드를 수정해보세요.
ㅋㅋㅋ
일단은 Djago이기 떄문에 파일의 양이 많아서 주석으로 설명을 대체하는 형식으로 진행하겠다.
1. Django 프로젝트를 생성하고, blog 라는 앱을 만들어서 settings.py 에 등록해보세요.
일단 1번문제는 django-admin startapp product 를 실해하여 APP을 하나 추가해준다.
그 후 settings.py에 있는 INSTALLED_APPS 에 'blog'를 추가해준다.
2. Models.py 에 <글 제목, 글 카테고리, 글 내용>이 들어갈 수 있는 Article 이라는 모델을 만들어보세요.
3. Models.py 에 <카테고리 이름, 설명>이 들어갈 수 있는 Category 라는 모델을 만들어보세요.
4. Article 모델의 글 카테고리에는, Category 모델에 존재하는 카테고리만 들어갈 수 있도록 만들어보세요. (힌트: Foreign Key)
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=256)
description = models.TextField()
class Article(models.Model):
title = models.CharField(max_length=256)
content = models.TextField()
# category 에 들어가는건 글도 아니고, 숫자도 아니고, 리스트도 아니고...
# Category object 가 들어가야만한다
category = models.ForeignKey(Category, on_delete=models.CASCADE)
2,3,4번은 models.py 에 해당 class를 생성하여 주는 것으로 모두 마무리가 된다.
5. Admin 페이지를 통해서, Category 모델에 ‘영화’, ‘드라마’, ‘예능’ 이라는 카테고리를 각각 생성해보세요.
admin 페이지를 사용하기 위해서는 super계정이 필요하다.
계정을 만드는 방법은 터미널에
python manage.py createsuperuser
를 사용하도록 하자.
6. 새 글을 작성할 수 있도록, templates 폴더 안에 form 태그가 존재하는 new.html 을 만들고, Views.py 과 Urls.py 에 적절한 코드를 작성해보세요.
<new.html>
<form method="POST">
{# cross site request forgery -> 해킹 공격의 일종, 요청을 만들어서 실제 요청인것마냥 보내는것, 글을 100만개 쓰여지도록 요청을 만들 수도 있음 #}
{% csrf_token %}
<input name="title">
<input name="content">
<select name="category">
{% for category in categories %}
<option value="{{ category.name }}">{{ category.name }}</option>
{% endfor %}
</select>
<button type="submit">글쓰기</button>
</form>
<urls.py>
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.category_view, name='category'),
path('new', views.new_view, name='new'),
path('detail/<int:pk>', views.detail_view, name='detail'),
# detail_view 라는 함수가 PK 라는 변수를 받아서 실행될 수 있게 되고
path('<str:name>', views.article_view, name='article'),
# article_view 라는 함수가 NAME 이라는 변수를 받아서 실행될 수 있게됩니다.
]
지금 부분의 urls.py 부분은 path('new') 부분만 보면된다.
기본의 경로에서 new라는 경로가 들어왔을 경우, views.py에서 new_view라는 함수를 실행시킨다는 의미이다.
<views.py>
from django.shortcuts import render, redirect
from .models import Category, Article
def new_view(request):
# get 요청으로 들어오면 form 태그 있는 html 을 보여주고
# post 요청이 들어오면 request.POST 변수들 받아서 글 생성
if request.method == 'POST':
title = request.POST.get('title', None)
content = request.POST.get('content', None)
# '영화'라는 카테고리로 글을 썼다면 category_name 에는 '영화'가 할당될것
category_name = request.POST.get('category', None)
# 아래 코드에서 category_name 도 '영화'
category = Category.objects.get(name=category_name)
article = Article.objects.create(title=title, content=content, category=category)
# django 는 자동으로 PK 라는 필드를 만들어준다
# 첫번째 글을 썼다 -> pk = 1
# 두번째 글을 썼다 -> pk = 2
return redirect('detail', article.pk)
elif request.method == 'GET':
# 새 글을 쓸때 현재 category 모델에 존재하는 것만 사용자가 선택할 수 있어야함
categories = Category.objects.all()
return render(request, 'new.html', {'categories':categories})
그런데! 여기서 views.py를 이해하기 위해서는 models.py도 보아야한다.
왜냐하면 지금 views.py에서 다루고 있는 부분이 modes.py에서 명시를 해준 Caregory, Article이기 때문이다.
(2,3,4번의 models.py에서 명시한 부분을 보아야함)
7. 카테고리 목록을 볼 수 있도록, templates 폴더 안에 카테고리 이름을 리스팅하는 category.html 을 만들고, Views.py 과 Urls.py 에 적절한 코드를 작성해보세요.
<category.html>
{% for name, count in infos.items %}
<a href="{% url 'article' name %}">{{ name }}({{ count }})</a>
{% endfor %}
<a href="{% url 'new' %}">글쓰기</a>
<Urls.py> (메인 프로젝트의 urls에서 한번에 관리하는중)
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.category_view, name='category'),
path('new', views.new_view, name='new'),
path('detail/<int:pk>', views.detail_view, name='detail'),
# detail_view 라는 함수가 PK 라는 변수를 받아서 실행될 수 있게 되고
path('<str:name>', views.article_view, name='article'),
# article_view 라는 함수가 NAME 이라는 변수를 받아서 실행될 수 있게됩니다.
]
<views.py> (이건 app에서)
def category_view(request):
categories = Category.objects.all()
infos = {}
for category in categories:
infos[category.name] = Article.objects.filter(category=category).count()
return render(request, 'category.html', {'infos': infos})
8. 작성된 글 목록을 볼 수 있도록, templates 폴더 안에 글 제목을 리스팅하는 article.html 을 만들고, 사용자가 category.html 에서 클릭한 카테고리에 해당하는 글만 필터링하여 보여주도록 Views.py 과 Urls.py 에 적절한 코드를 작성해보세요.
<article.html>
{% for article in articles %}
<a href="{% url 'detail' article.pk %}">{{ article.title }}</a>
{% endfor %}
<urls.py> ( '<str:name>' 부분을 보기 )
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.category_view, name='category'),
path('new', views.new_view, name='new'),
path('detail/<int:pk>', views.detail_view, name='detail'),
# detail_view 라는 함수가 PK 라는 변수를 받아서 실행될 수 있게 되고
path('<str:name>', views.article_view, name='article'),
# article_view 라는 함수가 NAME 이라는 변수를 받아서 실행될 수 있게됩니다.
]
여기서 왜 <str:name>으로 가는지 이해가 안될 수 있다.
이 부분을 보기 위해서는 우선 category.html을 보아야한다.
위에서 category.html파일을 보면
{% for name, count in infos.items %}
<a href="{% url 'article' name %}">{{ name }}({{ count }})</a>
{% endfor %}
이렇게 되어있다. 즉 해당 article의 name부분으로 url을 이동한다는 뜻이다.
path는 기본 주소의 방금 받은 article의 name 부분을 받아 할당된 article.html로 이동 할 것이다.
ex) 현재 나의 IP할당 주소가 http://100.0.0.1:8000/ 인경우,
현재 내가 누른 article의 name이 '영화' 인 경우
이동한 나의 path 는 http://100.0.0.1:8000/ 영화 가된다.
<views.py> (article_view 부분을 보기)
def article_view(request, name):
category = Category.objects.get(name=name)
articles = Article.objects.filter(category=category)
return render(request, 'article.html', {'articles': articles})
9. 특정한 글의 내용을 볼 수 있도록, templates 폴더 안에 글의 제목과 내용을 보여주는 detail.html 을 만들고, 사용자가 article.html 에서 클릭한 글에 해당하는 제목과 내용을 보여주도록 Views.py 와 Urls.py 에 적절한 코드를 작성해보세요.
<detail.html>
<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
<p>{{ article.category.name }}</p>
<a href="{% url 'category' %}">목록으로</a>
urls.py (detail/<int:pk>) 부분을 보기
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.category_view, name='category'),
path('new', views.new_view, name='new'),
path('detail/<int:pk>', views.detail_view, name='detail'),
# detail_view 라는 함수가 PK 라는 변수를 받아서 실행될 수 있게 되고
path('<str:name>', views.article_view, name='article'),
# article_view 라는 함수가 NAME 이라는 변수를 받아서 실행될 수 있게됩니다.
]
이부분도 똑같다. article에서 링크를 article의 pk로 걸어주었기에, 상세 페이지를 아까와는 다르게 pk로 접근을 하는것
pk는 1부터 하나하나 할당을 해준다.
<views.py>
def detail_view(request, pk):
article = Article.objects.get(pk=pk) # pk=1
return render(request, 'detail.html', {'article': article})