본문 바로가기

Python/Django

Django (Migrate / URLConf / View / Template / QuerySet / Bootstrap)

1. admin.ModelAdmin -> list_display 사용하여 admin 게시판 리스트 양식 바꾸기

https://www.kite.com/python/docs/django.contrib.admin.ModelAdmin.list_display

 

Kite - AI Coding Assistant for Python and JavaScript

Code faster with Kite’s AI-powered autocomplete plugin for Python and JavaScript developers, featuring Multi-Line Completions. Works 100% locally.

www.kite.com

1) 관리자 페이지에서 blog앱에 보이는 게시판 양식을 변경해보자

- 기존: title만 노출 -> id, title, count_text 세 가지가 노출되도록 변경해보자

- blog/admin.py 파일에 코딩

from django.contrib import admin
from .models import Post

class PostAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'count_text']
    list_display_links = ['title']

    def count_text(self, obj):
        return '{}글자'.format(len(obj.text))
    count_text.short_description = 'text 글자수'

# Register your models here.
admin.site.register(Post, PostAdmin)

 

 

2) 결과화면

- ID필드, TEXT글자수 필드가 추가된 것을 볼 수 있다.

(단 디비에 기존에 없던 필드인 TEXT글자수 필드가 저장이 되는 건 아님을 주의. 그저 보여지는 화면에서만 나오는 것)

 

3) 참고문서 

https://docs.djangoproject.com/en/2.0/ref/models/fields/#field-types

 

Model field reference | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

 

2. 필드 추가 및 삭제

>> 필드 추가

1) Post테이블에 test필드 추가하기 위해 모델 클래스에 필수 필드를 추가

 

2) 기존 모델 클래스에 필수 필드를 추가하여 makemigrations 수행

- 필수 입력 필드를 추가하므로, 기존 Row들에 필드를 추가할 때, 어떤 값으로 채워 넣을지 묻는다.

   선택 1) 지금 값을 입력

   선택 2) 모뎅 클래스를 수정하여 디폴트 값을 제공

 

3) 0002_post_test.py라는 migrations파일 생성된 것 확인

 

4) migration 적용 현황

- x표시가 없으면 아직 DB에 반영이 안됐단 의미

 

5) migration 적용

- DB에 반영

 

6) 결과화면

- DB에 반영된 모습

 

- Post게시판에 Test 컬럼에 anonymous값이 추가되어 보이는 모습

 

7) 지정 migration의 SQL 내역

- 실제 디비에서 실행되는 sql실행문 보여주는 명령어

 

 

>> 필드 제거

1) models.py에서 test필드 주석처리

 

2) remove migrations 파일 생성

 

3) migration 적용 현황

- x표시가 없으면 아직 DB에 반영이 안됐단 의미

 

4) migration 적용

- DB에 반영

 

5) 지정 migration의 SQL 내역

- 실제 디비에서 실행되는 sql실행문 보여주는 명령어

 

 

** 참고 문서 자료

https://south.readthedocs.io/en/latest/

 

South documentation — South 1.0 documentation

South is a tool to provide consistent, easy-to-use and database-agnostic migrations for Django applications.

south.readthedocs.io

 

3. URL Routing - Django URLConf 설정하기

 

1) post_list라는 함수(def) 만들어 요청(request)을 받아서 직접 문자열로 HTML형식 응답(response) 하기

- blog/views.py

from django.shortcuts import render
from django.http import HttpResponse

# Post 목록
def post_list(request):
    name = 'Django'
    return HttpResponse('''
        <h2>Post List</h>
        <p>웰컴 {name}!!!</p>
        <p>{content}<p/>'''.format(name=name, content=request.content_type))

 

2) http://127.0.0.1:8000/ 요청이 오면 post_list를 보여준다.

- blog/urls.py

from django.urls import path
from . import views


urlpatterns = [
    # loacalhost:8080/
    path('', views.post_list, name='post_list')
]

 

3) mydjango/urls.py 에서 blog/urls.py를 불러와 포함시킨다.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls'))
]

 

4) 결과화면

 

 

4. View

1) view의 역할

- 애플리케이션의 '로직'을 포함하며 모델에서 필요한 정보를 받아와서 템플릿에 전달하는 역할을 한다.

- Model과 Template을 연결하는 역할을 한다.

- URLConf에 매핑된 Callable Object

   : 첫번째 인자로 HttpRequest인스턴스를 받는다. 반드시 HttpResponse인스턴스를 리턴해야한다.

 

2) blog/views.py

- post_list 함수를 만들어 요청을 넘겨받아 render메서드를 호출한다.

- 함수는 호출하여 받은 blog/post_list.html템플릿을 보여준다.

from django.shortcuts import render
from django.http import HttpResponse

# Post 목록
def post_list(request):
    #name = 'Django'
    # return HttpResponse('''
    #     <h2>Post List</h>
    #     <p>웰컴 {name}!!!</p>
    #     <p>{content}<p/>'''.format(name=name, content=request.content_type))
    return render(request, 'blog/post_list.html')

 

5. Template

1) Template의 역할

- 정보를 일정한 형태로 표시하기 위해 재사용 가능한 파일을 말함.

- Django의 template 양식은 HTML을 사용한다.

- 템플릿은 blog/templates/blog 디렉토리에 저장한다.

- 엔진 자체는 templates밑에 있는걸 한번에 찾기 때문에 blog건지, board건지 몰름, 그러니까 teamplates밑에 또 폴더이름을 써줘야함

 

2) blog/templates/blog/post_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Blog List</title>
</head>
<body>
<h2>Blog List</h2>
<p>request.user : {{request.user}}</p>
<p>request.content_type : {{request.content_type}}!!!</p>
<p>Http Method : {{request.method}}</p>
</body>
</html>

 

3) 결과화면

 

4) 참고 문서

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

 

 

6. QuerySet

1) QuerySet이란?

- DB로부터 데이터를 읽고, 필터링을 하거나, 정렬을 할 수 있따.

 

2) 쿼리셋을 사용하기 위해 먼저 python shell을 실행한다.

 

3) 모든 객체 조회하기

- 모든 객체를 조회하기 위해 all()함수를 사용한다.

 

4) 객체 생성하기

- User(사용자) 모델의 인스턴스를 가져와 전달해준다.

- 객체를 저장하기 위해 create() 함수를 사용한다.

 

5) 필터링하기

- 원하는 조건으로 데이터를 필더링 한다. filter() 괄호 안에 원하는 조건을 넣어주면 된다.

 

글의 제목에 'title'이라는 글자가 들어간 글을 찾고자 할 때

 

글의 내용에 '내용'이라는 글자가 들어간 글을 찾고자 할 때

 

게시일로 과거에 작성한 글을 필터링하여 목록을 다시 가져온다.

 

- 이전에 만들어논 publish함수를 사용해보자

- 가져온 Post인스턴스를 publish()메서드를 이용하여 게시한다.

- Sample title에 published_date가 저장되어 조건에 맞는 것으로 변해 조회에 나타난 것을 볼 수 있다.

 

6) 정렬하기

- 작성일 기준으로 오름차순 / 내림차순 으로 정렬하기

 

7) 참고 문서 자료

https://docs.djangoproject.com/en/3.0/ref/models/querysets/

 

QuerySet API reference | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

7. View에서 동적 데이터 생성하기

 

1) view의 수정

- view는 DB에서 저장되는 Model에서 정보를 가져올 때 쿼리셋(Query Set)을 사용하며, 템플릿에 전달하는 역할을 한다.

- 게시일을 기준으로 과거에 자겅한 글을 필터링하여 정렬하여 글 목록 가져오기

- blog/views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.utils import timezone
from .models import Post

# Post 목록
def post_list(request):
    #name = 'Django'
    # return HttpResponse('''
    #     <h2>Post List</h>
    #     <p>웰컴 {name}!!!</p>
    #     <p>{content}<p/>'''.format(name=name, content=request.content_type))
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    return render(request, 'blog/post_list.html', {'posts': posts})

 

2) Template의 수정

- Template에서는 view에서 저장한 posts변수를 받아와서 HTML에 출력한다.

- 변수의 값을 출력하려면 중괄호를 사용한다.

- {% for %}와 {% endfor %} 사이에서 목록의 모든 객체를 반복하여 출력함

- | linebreaksbr 같이 파이프 문자( | )를 사용하여, 블로그 글 텍스트에서 행이 바뀌면 문단으로 변환하여 출력한다.

- blog/templates/blog/post_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Blog List</title>
</head>
<body>
    <h2>Blog List</h2>
    <p>request.user : {{request.user}}</p>
    <p>request.content_type : {{request.content_type}}!!!</p>
    <p>Http Method : {{request.method}}</p>
    {% 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 %}
</body>
</html>

 

3) 결과화면

 

4) 참고 문서

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

8. 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" %}
    Server comment 
{% 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>

 

 

9. css - 정적(static)파일 처리하기

1) css파일 작성

- static 디렉토리 안에 css디렉토리를 만들고 blog.css 파일 작성

h1 a {
    color:#f8ffa6;
    font-family:'Lobster';
}
body{
    padding-left:15px;
}

 

2) html파일 작성

<!DOCTYPE html>
{% load static %}
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Blog List</title>
    {% load static %}
    <link rel="stylesheet"
    href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"
    type="text/css">
    <link rel="stylesheet" href="{% static 'css/blog.css' %}">
</head>
<body>
    <h2>Blog List</h2>
    <p>request.user : {{request.user}}</p>
    <p>request.content_type : {{request.content_type}}!!!</p>
    <p>Http Method : {{request.method}}</p>
    {% for post in posts %}
        <div>
            <p>published : {{post.published_date}}</p>
            <h1><a href="https://naver.com">{{post.title|title}}</a></h1>
            <p>{{post.text|linebreaksbr}}</p>
        </div>
    {% empty %}
        <div>요청하신 Post가 존재하지 않습니다. </div>
    {% endfor %}

    {% comment "Optional note" %}
        Server comment
    {% endcomment %}
    <!-- html Client Comment -->
</body>
</html>

 

3) 결과화면

 

10. boot-strap

1) 부트스트랩 페이지 이다. 참고바람

https://getbootstrap.com/

 

Bootstrap

The most popular HTML, CSS, and JS library in the world.

getbootstrap.com

2) CDN(Content Delivery Network)

- 아래와 같이 링크로 되어있는것을 CDN이라한다.

CDN이란.... 사용자가 리소스를 다운로드할 수 있는 대체 서버노드를 제공하여 작동한다. 이러한 노드는 전 세계에 퍼져있기 떄문에 지연 시간 감소로 인해 컨텐츠의 빠른 응답과 다운로드 시간을 제공함으로써 사용자에게 더 가까운 전략적 이점을 제공한다.

 

 

- 해당 링크를 들어가보면 다음과 같이 필요한 명령어들이 압축되어 있는 파일인 것을 볼 수 있다.

 

3) HTML 파일

<!DOCTYPE html>
{% load static %}
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Blog List</title>
    {% load static %}
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <!-- Optional theme -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">
    <!-- google lobster font-->
    <link rel="stylesheet"
    href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext"
    type="text/css">
    <!-- 개발자 정의 CSS-->
    <link rel="stylesheet" href="{% static 'css/blog.css' %}">
</head>
<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="https://naver.com">{{post.title|title}}</a></h1>
                    <p>{{post.text|linebreaksbr}}</p>
            </div>
            {% empty %}
                <div>요청하신 Post가 존재하지 않습니다. </div>
            {% endfor %}
            </div>
        </div>
    </div>


    {% comment "Optional note" %}
        Server comment
    {% endcomment %}
    <!-- html Client Comment -->
</body>
</html>

 

4) 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;
}
h1, h2, h3, h4{
    font-family:'Lobster', cursive;
}
.content{
    margin-left:40px;
}
.date{color: #828282;}
.save{float:right;}
.post-from 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;}

 

5) 결과화면

 

 

 

11. favicon 적용하기

1) 사이트로 들어간다.

 

https://favicon.io/favicon-generator/

 

The best Favicon Generator (completely free)

With Favicon.io you can quickly generate a favicon for your website for free!

favicon.io

 

2) 원하는 문구, 배경색, 폰트사이즈 등등을 설정 후 다운로드 클릭

 

3) 원하는 파일에 저장

 

4) 압축을 풀고 favicon.io파일을 복사한다.

 

5) 이미지는 변하지 않는 파일이므로 static폴더 아래에 붙혀넣는다.

6) <link rel="shortcut icon" href="{%static 'favicon.ico'%}"> 로 불러온다.

 

7) 적용이 완료된 모습