QuerySet -> MTV의 V(view-logic)에서 사용
-- Blog App 작성 : URL Routing
**Django의 Architecture : URL Routing

**Django URLConf (configuration)란?
1) 프로젝트/settings.py 에 최상위 URLConf 모듈을 지정
-
URLConf는 장고에서 URL과 읷치하는 view를 찾기 위한 패턴들의 집합이다.
-
특정 URL과 View 매핑 List
-
Django 서버로 Http 요청이 들어올 때마다, URLConf 매핑 List를 처음부터 끝까지 순차적으로 찾으며 검색합니다.
*mydjango/urls.py
from django.conf.urls import include, url
from django.contrib import admin
Urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('blog.urls')),
]
mydjango -> urls.py (include blog, include product)
blog -> urls.py
admin (내부적으로)
product -> urls.py
**정규 표현식(Regex)
1) 정규 표현식이란?
문자열의 패턴, 규칙, Rule을 정의하는 방법
2) 파이썬3 정규 표현식 라이브러리
https://docs.python.org/3/library/re.html
re — Regular expression operations — Python 3.9.1 documentation
This module provides regular expression matching operations similar to those found in Perl. Both patterns and strings to be searched can be Unicode strings (str) as well as 8-bit strings (bytes). However, Unicode strings and 8-bit strings cannot be mixed:
docs.python.org
3) 정규 표현식 예시
-
최대 3자리 숫자 : "[0-9]{1,3}" 혹은 "\d{1,3}"
-
휴대폰번호 : "010[1-9]\d{7}“
-
한글이름 2글자 혹은 3글자 : "[ᄀ-힣]{2,3}"
-
성이 "이" 인 이름 : "이[ᄀ-힣]{1,2}"
4) 다양한 1글자 패턴
-
숫자 1글자 : "[0123456789]" 또는 "[0-9]" 또는 "\d"
-
알파벳 소문자 1글자 : "[abcdefghijklmnopqrstuvwxyz]" 혹은 "[a-z]"
-
알파벳 대문자 1글자 : "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]" 혹은 "[A-Z]"
-
알파벳 대/소문자 1글자 : "[a-zA-Z]"
-
16진수 1글자 : "[0-9a-fA-F]"
-
문자열의 시작을 지정 : "^"
-
문자열의 끝을 지정 :"$"
-
한글 1글자 : "[ᄀ-힣]"
5) 반복횟수 지정
-
"\d?": 숫자 0회 또는 1회
-
"\d*": 숫자 0회 이상
-
"\d+": 숫자 1회 이상
-
"\d{m}" : 숫자 m글자
-
"\d{m,n}" : 숫자 m글자 이상, n글자 이하
-
주의 : 정규 표현식은 띄워 쓰기 하나에도 민감합니다.
6) 휴대폰 번호 example
import re
def validate_phone_number(number):
if not re.match(r'^01[016789][1-9]\d{6,7}$', number):
return False
# 후에 Form Validator에서는 forms.ValidationError예외를 발생시킴
return True
print(validate_phone_number('01012341234')) # True
print(validate_phone_number('010123412')) # False
print(validate_phone_number('01012341234a')) # False
7) url 매핑 example
http://www.mysite.com/post/12345/라는 요청이 있을 때 12345는 글번호 정규표현식으로 url 패턴을 맊들어 숫자 값과 매칭되게 할 수 있음
^post/(\d+)/$.
^post/ : url이(오른쪽부터) post/로 시작합니다.
(\d+) : 숫자(한 개 이상)가 있습니다.
/ : /뒤에 문자가 있습니다.
$ : url 마지막이 /로 끝납니다.
**Django URLConf (configuration) 설정하기
1) main urls.py
: admin/로 시작하는 모듞 URL을 view와 매핑하여 찾아냅니다.
: http://127.0.0.1:8000/' 요청이 오면 views.post_list를 보여준다.
*mydjango/urls.py
from django.contrib import admin
from django.urls import path
from blog import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.post_list),
]
2) blog/urls.py
: blog/urls.py를 작성하여 blog와 관렦된 url들을 따로 정의함
*mydjango/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
]
*blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
]
2) blog/urls.py
:'http://127.0.0.1:8000/' 요청이 오면 views.post_list를 보여준다.
*blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
]
-- blog App 작성 : View
**Django의 Architecture : View

**View
1) View의 역할
-
View는 애플리케이션의 "로직"을 포함하며 모델에서 필요한 정보(querySet)를 받아 와서 템플릿에 전달하는 역할을 한다.
-
View는 Model과 Template을 연결하는 역할을 한다.
-
URLConf에 매핑된 Callable Object
첫번째 인자로 HttpRequest 인스턴스를 받습니다.
반드시 HttpResponse 인스턴스를 리턴 해야 합니다.
https://docs.djangoproject.com/en/1.11/ref/request-response/
Request and response objects | Django documentation | Django
Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate
docs.djangoproject.com
2) blog/views.py
: post_list라는 함수(def) 만들어 요청(request)을 받아서 직접 문자열로
HTML형식 응답(response)하기
*blog/views.py
from django.http import HttpResponse
def post_list(request):
name = '장고'
return HttpResponse('''<h1>Hello Django</h1>
<p>{name}</p>'''.format(name=name))
3) blog/views.py 수정
: post_list라는 함수(def) 만들어 요청(request)을 넘겨받아 render 메서드를 호출합니다.
: 함수는 호출하여 받은(return) blog/post_list.html 템플릿을 보여줍니다.
*blog/views.py
from django.shortcuts import render
def post_list(request):
return render(request,'blog/post_list.html')
1)mydjango_prj/urls.py :
-> 2)blog/urls.py
-> 3)blog/views.py/post_list()
-- blog App 작성 : Template
**Django의 Architecture : Template

**Template
1) Template의 역할
-
Template은 정보를 일정한 형태로 표시하기 위해 재사용 가능한 파일을 말함
-
Django의 template 양식은 HTML을 사용합니다.
-
템플릿은 blog/templates/blog 디렉토리에 저장합니다.
*blog/templates/blog/post_list.html
<html>
<head>
<title>Django blog</title>
</head>
<body>
<p>Hi there!</p>
<p>It works!</p>
</body>
</html>
--구조
mydjango
-blog
-templates
-blog
-xx.html
-product
-templates
-product
-xxmhtml
2) post_list.html 템플릿 수정
*blog/templates/blog/post_list.html
<html>
<head>
<title>Django blog</title>
</head>
<body>
<div>
<h1><a href="">Django’s Blog</a></h1>
</div>
<div>
<p>published: 14.06.2014, 12:14</p>
<h2><a href="">My first post</a></h2>
<p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
</p>
</div>
<div>
<p>published: 14.06.2014, 12:14</p>
<h2><a href="">My second post</a></h2>
<p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.
</p>
</div>
</body>
</html>
-- blog App 작성 : 템플릿에서 동적 데이터 처리
**Django의 Architecture : 동적(dynamic) 데이터 처리하기

**View에서 동적(dynamic) 데이터 생성하기
1) View의 수정
-
View는 DB에 저장되는 Model에서 정보를 가져올 때 쿼리셋(QuerySet)을 사용하며, 템플릿에 전달하는 역할을 한다.
-
# 게시일(published_date) 기준으로 과거에 작성한 글을 필터링하여 정렧하여 글 목록 가져오기
*blog/views.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).\
order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
2-1) Template의 수정
-
Template에서는 view에서 저장한 posts 변수를 받아와서 HTML에 출력한다.
-
변수의 값을 출력하려면 중괄호를 사용한다.
-
{% for %} 와 {% endfor %} 사이에서 목록의 모듞 객체를 반복하여 출력함.
*blog/templates/blog/post_list.html
<div>
<h1><a href="/">Django’s Blog</a></h1>
</div>
{% for post in posts %}
{{ post }}
{% endfor %}
2-2) Template의 수정
-
|linebreaksbr 같이 파이프 문자(|)를 사용하여, 블로그 글 텍스트에서 행이 바뀌면 문단으로 변홖하여 출력한다.
*blog/templates/blog/post_list.html
<div>
<h1><a href="/">Django’s Blog</a></h1>
</div>
{% for post in posts %}
<div>
<p>published: {{ post.published_date }}</p>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
**Template Engine
-
Django Template Engine : Django 기본 지원 템플릿 엔진
-
Django Template Engine Syntax
{% extends "base.html" %}
{% for row in rows %}
<tr>
{% for name in row %}
<td>{{ name }}</td>
{% endfor %}
</tr>
{% endfor %}
**Template Engine 문법
1) Variables
-
{{ first_name }}
-
{{ mydict.key }} : dict의 key에 attr 처럼 접근
-
{{ myobj.attr }}
-
{{myobj.func}}: 함수 호출도 attr 처럼 접근. 인자 있는 함수 호출 불가
-
{{ mylist.0 }} : 인덱스 접근도 attr 처럼 접근
2) Django Template Tag
-
{% %} 1개 쓰이기도 하며,2개 이상이 조합되기도 함.
-
빌트인 Tag가 지원되며, 장고앱 별로 커스텀 Tag 추가 가능
block, comment, csrf_token, extends, for, for ... empty, if, ifchanged, include, load, lorem, now, url, verbatim, with 등
3) block tag
-
템플릿 상속에서 사용
-
자식 템플릿이 오버라이딩 할 block 영역을 정의
-
자식 템플릿은 부모가 정의한 block에 한해서 재 정의만 가능.그 외는 모두 무시됩니다.
{% block block-name %}
block 내에 내용을 쓰실 수 있습니다.
{% endblock %}
4) Comment Tag : 템플릿 주석
{% comment "Optional note" %}
이 부분은 렌더링 되지 않습니다.
{% endcomment %}
5) csrf_token tag
-
Cross Site Request Forgeries를 막기 위해 CSRF Middleware가 제공
-
이는 HTML Form의 POST요청에서 CSRF토큰을 체크하며, 이때 CSRF토큰이 필요
-
csrf_token tag를 통해 CSRF토큰을 발급받을 수 있습니다.
<form method="POST" action="">
{% csrf_token %}
<input type="text" name="author" />
<textarea name="message"></textarea>
<input type="submit" />
</form>
6) extends tag
-
자식 템플릿에서 부모 템플릿 상속을 명시
-
extends tag는 항상 템플릿의 처음에 위치해야 합니다.
-
상속받은 자식 템플릿은 부모 템플릿에서 정의한 block만 재정의할 수 있습니다.
{% extends "base.html" %}
7) for tag
-
지정 객체를 순회하며 파이썬의 for문과 동일
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
7) for ... empty tag
-
for tag 내에서 지정 object를 찾을 수 없거나, 비었을 때 empty block이 수행
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
8) if tag
-
파이썬의 if문과 동일
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
9) url tag
-
URL Reverse를 수행한 URL문자열을 출력
-
인자 처리는 django.shortcuts.resolve_url 함수와 유사하게 처리하나, get_absolute_url 처리는 하지 않음.
{% url "some-url-name-1" %}
{% url "some-url-name-2" arg arg2 %}
{% url "some-url-name-2" arg arg2 as the_url %}
Django Templates Tag Documentation
https://docs.djangoproject.com/en/3.0/ref/templates/builtins/
Built-in template tags and filters | Django documentation | Django
Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate
docs.djangoproject.com
-- blog App 작성 : 템플릿에 CSS 적용하기
**Django의 Architecture : Template에 css 적용
**정적(static) 파일 처리하기
1) CSS 파일 작성
-
static 디렉토리 안에 css 디렉토리를 만들고 blog.css라는 파일을 작성.
*blog/static/css/blog.css
h1 a {
color: #FCA205;
font-family: 'Lobster';
}
body { padding-left: 15px;}
*blog/templates/blog/post_list.html
{% load static %}
<html>
<head>
<title>Django's blog</title>
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
</head>
2) 부트스트랩(Bootstrap) 적용하기
-
Bootstrap을 설치하려면.html파일 내 <head>에 아래의 링크를 넣어야 합니다.
*blog/templates/blog/post_list.html
{% load static %}
<html>
<head>
<title>Django's blog</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<link rel="stylesheet"
href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" type="text/css">
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
</head>
3) 완성된 blog.css
*blog/static/css/blog.css
.page-header {
background-color: #ff9400;
margin-top: 0;
padding: 20px 20px 20px 40px;
}
.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active {
color: #ffffff;
font-size: 36pt;
text-decoration: none;
}
.content { margin-left: 40px; }
h1, h2, h3, h4 { font-family: 'Lobster', cursive; }
.date { color: #828282; }
.save { float: right; }
.post-form textarea, .post-form input { width: 100%; }
.top-menu, .top-menu:hover, .top-menu:visited {
color: #ffffff;
float: right;
font-size: 26pt;
margin-right: 20px;
}
.post { margin-bottom: 70px; }
.post h1 a, .post h1 a:visited { color: #000000; }
4) 완성된 post_list.html
*blog/templates/blog/post_list.html
<body>
<div class="page-header">
<h1><a href="/">Django Blog</a></h1>
</div>
<div class="content container">
<div class="row">
<div class="col-md-8">
{% for post in posts %}
<div class="post">
<div class="date">
<p>published: {{ post.published_date }}</p>
</div>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
</div>
</div>
</div>
</body>
</html>
<bootstrap 참고>

-- blog App 작성 : 템플릿 상속하기(Template Inheritance)
**Django의 Architecture : Template Inheritance

**Template 상속(Inheritance) 하기
1) Template 상속(Inheritance)이란?
-
Template 상속을 사용하면 동일한 정보/레이아웃을 사용 하고자 할 때, 모든 파일마다 같은 내용을 반복해서 입력 할 필요가 없게 됩니다.
-
또한 수정할 부분이 생겼을 때도, 각각 모든 파일을 수정 할 필요 없이 한번만 수정하면 됩니다.
2) 기본 템플릿 html 생성하기
-
기본 템플릿은 웹사이트 내 모든 페이지에 확장되어 사용되는 가장 기본적인 템플릿입니다.
-
blog/templates/blog/에 base.html 파일을 생성한다.
-
post_list.html에 있는 모든 내용을 base.html에 아래 내용을 복사해 붙여 넣는다.
3) 기본 템플릿 (base.html)
{% for post in posts %}{% endfor %} 사이에 있는 코드를 제거하고
{% block content %}{% endblock %} 으로 변경한다.
*blog/templates/blog/base.html
<body>
<div class="page-header">
<h1><a href="/">Django Blog</a></h1>
</div>
<div class="content container">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
</body>
4) post_list.html 수정하기
-
{% block content %}와 {% endblock %} 사이에 {% for post in posts %}부터 {% endfor %} 코드를 넣는다.
-
두 템플릿을 연결하기 위해 {% extends 'blog/base.html' %} 코드를 추가한다.
*blog/templates/blog/post_list.html
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
{% endblock %}
--blog App 작성 : Post Detail (글 상세) 페이지 작성하기
1) urls.py에 url 추가
-
^은 "시작"을 뜻합니다.
-
post/란 URL이 post 문자를 포함해야 한다는 것을 말합니다
-
(?P<pk>\d+) 정규표현식은 장고가 pk 변수에 값을 넣어 view로 전송하겠다는 뜻입니다. \d은 숫자만 올 수 있다는 것을 말합니다. +는 하나 또는 그 이상의 숫자가 올 수 있습니다
-
/은 다음에/가 한 번 더 와야 한다는 의미입니다.
-
$는"마지막"을 말합니다.그 뒤로 더는 문자가 오면 안 됩니다.
따라서 http://127.0.0.1:8000/post/5/라고 입력하면, post_detail view를 찾아 매개변수 pk가 5인 값을 찾아 view로 전달합니다.
*blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
]
2) post_list.html에 Post detail 페이지 링크 추가
-
{% %}는 장고 템플릿 태그이며, post_detail은 url에서 정의한 view name이다.
-
post.pk는 Post 모델의 primary key(기본키)를 의미합니다.
*blog/templates/blog/post_list.html
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h1><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
{% endblock %}
3) views.py에 post_detail() 함수 추가
-
def post_detail(request, pk):라고 정의하며, urls(pk)과 동읷하게 이름을 사용해야 합니다.
-
블로그 게시글 한 개만 보려면 Post.objects.get(pk=pk) 쿼리셋을 작성해야 하는데 만약 해당 primary key(pk)의 Post를 찾지 못하면 오류가 날 수 있으므로 Django에서는 이를 해결하기 위해 get_object_or_404라는 특별한 기능을 제공한다.
*blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
4) post_detail.html 페이지 추가
-
base.html을 확장하고, content블록에서 블로그 글의 게시일, 제목과 내용을 보이게 한다.
-
{% if ... %} ... {% endif %}라는 템플릿 태그에서는 post의 게시일(published_date)이 있는지, 없는지를 확인합니다.
*blog/templates/blog/post_detail.html
{% extends 'blog/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endblock %}
1)mydjango_prj/urls.py :
-> 2)blog/urls.py <- URL Mapping
path('', views.post_list, name='post_list'),
-> 3)blog/views.py/post_list() <- View
return render(request, 'blog/post_list.html', {'posts': posts}) <- Template
**render 함수(response 객체를 내부적으로 생성해서 반환해줌)
request객체를 넘겨줌 -> template에서 사용함
1/13일 과제
django project 생성
project name : mydjango_product
app name : product
Product 모델
: name
: price
: stock_quantity
: description
python manage.py runserver 8080




'CLOUD > Django' 카테고리의 다른 글
1/21 Django - 복습 2차시(with VS Code) (0) | 2021.01.21 |
---|---|
1/20 - Django 복습(with VS Code) (0) | 2021.01.20 |
1/15 Django 4차시 - blog app 만들기(Maria DB, 페이징처리, django REST frame) (0) | 2021.01.15 |
1/14 Django 3차시 - blog app만들기(CRUD + 로그인/로그아웃 + reply) (0) | 2021.01.14 |
1/12 Django 1차시 - blog만들기 (0) | 2021.01.12 |