반응형

1.Rest Architecture 

-REST란? : Representational State Transfer  / “자원을 이름으로 구분하여 상태를 전송하는 방법”

 

-Rest 설계 필요 충분 조건

   1. SERVER – CLIENT 

   2. STATELESS #클라이언트의 이전 상태를 기록하지 않는 연결방식을 취함 

   3. CACHE #캐쉬 처리기능 

   4. UNIFORM INTERFACE #일관된 인터페이스 

  • Resource가 URI로 식별이 되어야한다.
  • CRUD를 HTTP메세지로 수행 가능해야한다.
  • 메세지는 자체로 모든 것이 설명 가능해야한다.
  • 어플리케이션의 상태는 하이퍼링크를 이용해 전이되야한다.(HATEOAS)

   5. LAYERED SYSTEM #다칭적인 구성

   6. CODE-ON-DEMAND #JS처럼 서버와 같이 원격지에서 보낸 코드로 메소드를 실행시킬 수 있는 것

 

-API란? Application Program Interface / Request, Response로 오가는 구조화된 데이터

-Rest API  : REST의 설계방식을 잘 따르는 API / 대부분의 API는 rest를 잘 따르지 않는다 / Json은 모든 태그가 만들어져 있지않고, 만든 이가 정의하기 나름이기 때문에

 

    -> 필요한 이유?

         : 백엔드, 프론트엔드 분리 / 독립적인 네트워크 향상 가능 / 클라이언트 플랫폼 다양화 지원 가능

 

Django VS Django Rest Framework

  Django Djnago Rest Framework
만들어지는 것 웹 어플리케이션 RESTful API
전달하는 데이터 HTML Form(HTML, CSS, JS) JSON 데이터
데이터를 담는 곳  Form / ModelForm Serializer/ ModelSerialier
model로 부터 Field 읽어온다
유효성 검사

 

Form VS Serializer

 

 

Serializer vs ModelSerialier

Form과 ModelForm이 존재하듯이 Model만 작성할 줄 알면
더 간편하게 Serializer를 사용할 수 있게하는 ModelSerialier에 대해서 공부한다.
ModelSerialier는 쿼리셋과 모델 직렬화를 알아서 해준다.

 

2.Serializer 실습 

가상환경 생성

$python -m venv myvenv

 

필요 패키지 설치

$pip install djangorestframework

$pip install django

 

django 프로젝트 생성

$django-admin startproject rest

-> 생성 후 cd rest 로 폴더 이동

 

django app 생성

$ python manage.py startapp post

 

settings.py에 앱 추가(장고 프레임워크도 등록)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'post',
]

url 관리

   -> 앱 폴더 내부에 urls.py 생성(계층적 url 관리 위해 분할) ##아니 나는 urls.py를 완성하지 못하면 마이그레이트가 안된다.. 이거먼저!

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter() #ROUTER 객체 생성
router.register('post', views.PostViewSet) #ROUTER 객체의 REGISTER 함수(첫번째 인자 = URL, 함수)

urlpatterns = [
    path('', include(router.urls))
]

#rest_framework는 ROUTER을 사용해 URL을 결정한다
#CRUD 기반으로 URL을 설정한다

  

    -> 프로젝트 폴더 urls.py 에 모듈 추가

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


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

앱 폴더의 models.py 에 모델 클래스 정의 (post/models.py)

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
# Create your models here.

앱 폴더 내부에 serializer.py 생성 및 작성 (어떤 클래스의 어떤 필드를 사용할 것인지)

from .models import Post
from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['title', 'body'] 
        # 모든 필드를 사용할 경우 '__all__' 사용 가능

views.py 작성하기

-> rest_framework 의 viewsets 모듈과 작성한 모델serializer 추가

 

from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    
Django Rest Framework는 Class base View 이기에 
view로서 class를 작성한다
viewsets의 ModelViewSet을 상속받는다.

 

##ROUTER

▪ ViewSet에는 여러가지 메소드(함수)들이 있다 

      ex) retrieve() , destroy(), …

▪ 이 모든 것을 하나의 path()로 처리해 주는 것은 불가능하다.

▪ Path함수를 묶어준다 == path함수의 두번째 인자로 오는 함수를 묶는다 

     -> Path(요청을 처리할 url, 요청을 인자로 받아 처리할 함수, namespace)

 

#실행 결과(api 서버 보기)

1. api root : urls.py 에 작성된 DefaultRouter 에 의해 만들어진 기본적인 환경 / 처음 보여지는 화면은 GET 요청을 할 수 있는 URL이 보여진다.

 

2.POST API

-request : 127.0.0.1/8000/post

 

-response

 

post 후 post/1로 들어가면 allow 부분에 put이 들어간 것을 볼 수 있음

각 객체에 pk 값 부여하기 

-> serializer.py 파일의 PostSerializer 을 수정한다

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'body'] 

새로 고침 후 보면 id 값을 직접 확인할 수 있는 것을 볼 수 있다. 

id 값 : 각 인스턴스에 붙는 고유 번호

Read Only 설정하기

 -> serializer.py 파일의 PostSerializer을 수정한다

 -> read_only_fields 에 read_only 속성을 적용할 필드를 tuple에 추가한다

 -> 수정 시 read_only 부분이 true로 바뀌는 것을 볼 수 있다.

 -> write_only부분도 같은 방법으로 수정하면된다!

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = "__all__"
        read_only_fields = ("title",)

반응형

'Web > Django' 카테고리의 다른 글

[Django] Instagram 클론 코딩(1)  (0) 2020.03.17
[Django_심화]3 - viewset & router  (2) 2019.11.03
[Django_심화]1 - 준비운동  (0) 2019.11.02
[6주차]Form  (0) 2019.03.06
[5.5주차]Faker  (0) 2019.03.05
반응형

1. JSON & Http Resquest & Response & Httpie

  • JSON 
    • Java Script Object Notation 의 약자
    • 데이터 송수신을 자바스크립트의 문법으로 표현된 객체로 수행할 수 있게 만든 가벼운 문자열 데이터 표현식
    • 자바스크립트를 사용하지 않아도 사용 가능하다!
    •  웹에서는 Server와 Client 사이에는 여러 항목을 주고 받음. /구조를 나타내는 HTML /스타일을 표현하는 CSS /논리를 구현하는 Javascript
    • 앞으로의 강의들은 데이터인 JSON 만 주고 받음!
  • JSON 문법 형식
    • Python 의 딕셔너리와 비슷한 구조
    • name : value
    • 숫자, 문자(열), Boolean, 배열, 객체 등으로 구성 가능 
    • JSON  데이터를 보낼 때에는 직렬화(Serialization) 과정을 거쳐 JSON 데이터를 문자열로 바꾸어 상대방에게 보낸다.
    • 데이터를 보낼 때에는 JSON  -> 문자열로 / 데이터를 받을 때에는 문자열 -> JSON으로 바꾸어 받는다.
json_example = { 
	"string_name": "something",
    "number_name": 3,
    "null_name": null,
    "bool_name": true
}
  • Python에서 JSON 사용하기
    • Python 딕셔너리 자료형을 반환해보자
import json //Json을 처리하는 라이브러리를 제공
diary = {
	"id": 3,
    "title": “멋쟁이사자처럼”,
    "body“: “2학기도 파이팅”
}

print(diary)
//{‘id’: 3, 'title': ‘멋쟁이사자처럼’, ‘body’: ‘2학기도 파이팅’}

print(type(diary))
//<class ‘dict’>
  • Dict to JSON 
    • JSON의 dumps 함수를 이용해 변환 진행
    • 데이터를 송신할 때 사용할 수 있다.
    • dic 이였던 자료형이 str로 변환
diary_s = json.dumps(diary)
print(diary_s) 
//{‘id’: 3, 'title': ‘멋쟁이사자처럼’, 'body': ‘2학기도 파이팅’}
print(type(diary_s)) 
//<class ‘str’>
  • JSON to Dict
    • JSON 의 load 함수를 이용해 변환을 진행
    • 데이터를 수신할 때 사용할 수 있다
    • Str 자료형이 dict로 다시 변환되었음을 볼 수 있다.
diary_b = json.loads(diary)
print(diary_b) 
//{‘id’: 3, 'title': ‘멋쟁이사자처럼’, 'body': ‘2학기도 파이팅’}
print(type(diary_b)) 
//<class ‘dict’>

Http Requsest & Response

  • 정의
    • Http란?
      • 웹 상에서 통신을 주고 받을 수 있는 주체, Client와 Server 그 중, Server의 역할은 Request 를 가공해서 처리해주는 역할
      • Web 상에서 지원하는 통신 규약을 Http
      • 한마디로 정의한다면?
        • HttpRequest : 요청에 대한 메타 정보를 가지고 있는 객체 
        • HttpResponse : 요청에 대한 메타 정보를 가지고 있는 객체
    • Django 에서 Http Method
GET POST
빈 입력공간 가져와 입력한 내용 처리
URL에 데이터 정보 포함 URL에 데이터 정보 포함 안함

        ▪ Django 에서 Rest FrameWork에서 Http Method

Method 기능
GET 요청받은 URL의 정보 검색하여 응답
POST 요청된 자원을 생성(CREATE)
DELETE 요청된 자원 삭제
PATCH 요청된 자원 일부 수정
OPTION 웹 서버에 지원된 메소드 종류 확인

 

 

 Django Rest FrameWork?

-> 장고 안에서 RESTful API 서버를 쉽게 구축할 수 있도록 도와주는 오픈 소스라이브러리

 

-Rest?

    -> HTTP 의 URL과 HTTP Method(GET, POST, PUT, DELETE)를 사용해서

         API 사용 가독성을 높인 구조화된 시스템 아키텍쳐(Framework)

 

-RESTful 아키텍쳐를 HTTP Method와 함께 사용해서 웹, 데스크탑 앱, 어플리케이션 까지 구동할 수 있는 서버를 만든다고 생각!

 

  • Django Rest Framework API Server에서는 JSON을 주고 받음
  • 서버 Response 종류 
    • 1XX (정보) -> 요청을 받았으며 프로세스를 계속한다.
    • 2XX(성공) -> 요청을 성공적으로 받았으며 인식했고 수용했다. 
    • 3XX(리다이렉션) -> 요청을 완료하기 위해 추가 작업 조치가 필요하다.
    • 4XX(클라이언트 오류) -> 요청의 문법이 잘못되었거나 요청을 처리할 수 없다.
    • 5XX(서버 오류) -> 서버가 명백히 유효한 요청에 대해 충족에 실패했다.

Httpie

- 요청을 Command Line으로 동작하는 파이썬 기반 프로그램 (=http client)

- 다른 http Client 보다 가볍고 설치하기 편하기 떄문에 사용

 

-httpie 설치

>>pip install --upgrade httpie

 

-httpie 명령어

>>http [flags] [METHOD] URL [ITEM[ITEM]]

 

flags : 옵션

▪ METHOD : HTTP METHOD

▪ URL : 요청이나 응답의 대상 URL

▪ ITEM : 처리할 값 (인자)

▪ POST / PUT : =로 표현

▪ GET : ==로 표현

 

▪ Httpie 명령어 사용 예시 

     ▪ GET

          http(GET) 대상주소 인자 ==값

 http (GET) example.org a==1 b==2
 http example.org a==1 b==2 


      ▪ PUT

           http(PUT) 대상주소 GET인자 ==값 PUT인자=값

 http PUT example.com a==1 b==2


▪ Get 인자가 있으면 쓰고 없으면 안쓴다. ▪ Put 인자가 있으면 쓰고 없으면 안쓴다.

 

2. CBV

-장고의 view

    - 호출 가능한 객체(callable object) 로 정의

        -> 함수 / 클래스

    - 함수와 클래스의 차이 : 함수 (상속x) / 클래스 (상속o)

    - 상속을 사용하는 이유는 ? 중복의 제거 / 코드의 재사용

 

따라서 CBV를 사용하는 이유는 상속을 사용해 코드를 더 간단하게 작성하기 위해 사용

 

-FBV(Function Based View)  : 함수 기반 뷰 

 

##실습하면서 익혀봅시다

순서 : 프로젝트 생성 -> 앱 생성 -> 템플릿 추가

 

가상환경 생성 및 활성화

$python -m venv myvenv

$ source myvenv/Scripts/activate

 

프로젝트 생성

$ django-admin startproject CBV

$ cd CBV

 

앱 생성 

$python manage.py startapp classBaseCrud

 

settings.py 에 앱 추가

INSTALLED_APPS = [
    'classBaseCrud',
]

 models.py 작성하기

- 클래스 생성

from django.db import models

# 클래스를 생성하여 제목, 생성일, 수정일, 본문 필드 작성

class ClassBlog(models.Model):
    title = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)
    #auto_now_add 옵션 : model이 최초 저장시에만 현재 날짜 적용
    updated_at = models.DateTimeField(auto_now=True)
    #auto_now 옵션 : 데이터가 저장 될 때마다 현재 날짜로 갱신
    body = models.TextField()

    def __str__(self):
        return self.title

-admin.py에 생성한 클래스 등록

from django.contrib import admin
from .models import ClassBlog

admin.site.register(ClassBlog)

-마이그레이션

$ python manage.py makemigrations
$ python manage.py migrate

 

views.py 작성하기

1) 사용할 모듈 추가 - CRUD

게시글 목록 ListView
새로운 게시글 생성 CreateView
게시글 상세 내용 DetailView
게시글 수정 UpdateView
게시글 삭제 DeleteView

    -Generic Views : 웹 개발 시 자주 사용하는 기능을 장고에서 미리 제공 / 외부 모듈 적용이 필요하다

 

      #사용할 모듈 추가 CRUD

from django.utils import timezone

from django.urls import reverse_lazy

from django.views.generic.list import ListView
#게시글 목록 보여줌

from django.views.generic.detail import DetailView
#게시글의 상세 내용을 보여줌

from django.views.generic.edit import CreateView, UpdateView, DeleteView
#게시글 생성, 수정, 삭제 

from .models import ClassBlog

2)모듈을 상속해 클래스 작성(classBaseCrud/views.py)

-CREATE

#CREATE
class BlogCreate(CreateView):
    model = ClassBlog
    fields = ["title", "body"]
    success_url = reverse_lazy('list')
    #reverse_lazy 
    #- redirect 와 같은 기능으로 , generic view에서 주로 사용
    #- reverse_lazy() 함수 사용 인자로 URL 이름을 넣어줌
    #- 작업이 성공적으로 완료되었을 경우 해당 URL로 이동

-READ

#READ
class BlogView(ListView):
    model = ClassBlog
    template_name = 'classBaseCrud/list.html'
    context_object_name = 'blog_list'
    # List Views
    #- Generi view 중 특정 모델의 리스트를 출력해주는 뷰
    #- 모델에 대한 쿼리가 필요하고(queryset)
    #- 어느 템플릿에 (template_name)
    #- 어떤 파라미터명으로 전달할지 (context_object_name) 를 정의
    #- 약속되어있는 html 이름을 사용하지 않고 작성하기 위함
    #- 해당 html을 사용할 class에 template_name을 설정하면 된다
    
    #context_object_name : 임의로 설정하여 기본적으로 설정되어있는 객체를 가져옴
class BlogRead(DetailView):
    context_object_name = 'blog'
    model = ClassBlog
    #DetailView
    #- 특정 모델의 특정 오브젝트에 대한 자세한 정보를 출력해주는 뷰
    #- 어떤 모델의 어떤 오브젝으를 어떤 템플릿에 전달할지 정의

-UPDATE

#UPDATE
class BlogUpdate(UpdateView):
    model = ClassBlog
    fields = ["title", "body"]
    success_url = reverse_lazy("list")

-DELETE

#DELETE
class BlogDelete(DeleteView):
    model = ClassBlog
    success_url = reverse_lazy("list")

앱 내부에 urls.py 생성 및 작성

- 작성할 클래스에 맞는 url path 작성

- (urls.py / classBaseCurd)

from django.urls import path
from .import views

#작성할 클래스에 맞는 url path 작성
urlpatterns = [
    path("", views.BlogView.as_view(), name='list'),
    #as_view : view를 하나 만들어서 이를 return
    #함수가 하나 만들어지는 것과 같음
    #클래스를 정의한 후 이에 해당하는 함수 만들어 사용하는 방식

    path("create/", views.BlogCreate.as_view(), name="create"),
    path("read/<int:pk>/", views.BlogRead.as_view(), name="read"),
    path("update/<int:pk>/", views.BlogUpdate.as_view(), name="update"),
    path("delete/<int:pk>/", views.BlogDelete.as_view(), name="delete"),
]

프로젝트 urls.py 에 앱 urls.py 추가

- (urls.py / CBV)

from django.contrib import admin
from django.urls import path, include
#django.urls 의 include 모듈 추가
#앱의 urls.py 파일을 프로젝트 urls.py에 추가
import classBaseCrud.urls
import classBaseCrud.views

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

templates 생성하기

- 수행 결과를 보여주는 HTML 템플릿이 존재해야하고 
ListView 는 블로그 리스트 HTML / CreateView, UpdateView 는 입력공간(form)을 갖는 HTML

DetailView는 상세 페이지 HTML / DeleteView 는 삭제 작업을 확인하는 HTML 필요

 

- Generic View 에서는 기본적으로 설정된 이름이 존재

- 다른 이름으로 HTML 을 작성하기 위해서는 추가 설정이 필요

 

View 이름 HTML 이름
ListView (소문자 모델)_list.html
CreateView (소문자 모델)_form.html
DetailView (소문자 모델)_detail.html
UpdateView (소문자 모델)_form.html
DeleteView (소문자 모델)_confirm_delete.html

 

##template폴더 구성할 때 template 안에 HTML 파일을 작성하는 게 아니라 App 이름의 폴더를 작성하고 그 안에 작성

앱 안에 templates라는 폴더를 만들고 그 안에 앱 이름으로 폴더를 만들어 그 안에 html를 만들어야함

#classblog_list.html

<!DOCTYPE html>
<html lang="ko" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Class Base View</title>
    </head>
    <body>
        <a href="{% url 'create' %}"> 추가 </a>
        
        <br>
        
        {% for blog in blog_list %}
        <h2> {{ blog.title }} </h2>
        <h2> {{ blog.created_at }} </h2>
        <p> {{ blog.body }} </p>
        
        <a href="{% url 'read' blog.id %}"> 자세히보기 </a><br>
        <a href="{% url 'update' blog.id %}"> 수정 </a><br>
        <a href="{% url 'delete' blog.id %}"> 삭제 </a><br>
        {% endfor %}
    </body>
</html>

#classblog_form.html

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="추가하기">
</form>

//HTTP POST, PUT, DELETE 🡪 {% csrf token %} 사용
//{{ form.as_p}} : view에서 전달한 form 객체를 템플릿 변수로 사용 / 폼의 각 필드를 p태그 안에 배치

#classblog_detail.html

<h1> 본문 자세히 보기 페이지 </h1>

<hr>

<h2> 제목 : {{ blog.title }} </h2>
<h4> 날짜 : {{ blog.created_at }} </h4>
본문 : {{ blog.body }}

#classblog_confirm_delete.html

<form method="POST">
    {% csrf_token %}
    <h2>진짜 지울거야?</h2>
    <br>
    <br>
    <input type="submit" value="삭제">
</form>

##결과

CREATE
DETAIL
UPDATE(수정)
DELETE
생성 후 리스트 목록

반응형

'Web > Django' 카테고리의 다른 글

[Django_심화]3 - viewset & router  (2) 2019.11.03
[Django_심화]2 - Rest, Serializer  (0) 2019.11.03
[6주차]Form  (0) 2019.03.06
[5.5주차]Faker  (0) 2019.03.05
[5주차]2.Pagination  (0) 2019.03.05
반응형

<detail.html 생성&연결>

1. template 추가하기 (blog/templates/blog -> detail.html)

-> home.html 똑같이 복사해서 {%for blog in blogs.all %} 지우고 확인 메세지 적음

1
<h1>디테일 페이지입니다.</h1>
cs


2. views.py 수정 (detail.html 템플릿 연결)


1
2
3
4
5
6
7
8
9
10
11
12
from django.shortcuts import render, get_object_or_404
from .models import Blog
 
def home(request):
    blogs = Blog.objects
    return render(request, 'blog/home.html', {'blogs': blogs})
 
def detail(request, blog_id):
    blog_detail = get_object_or_404(Blog, pk=blog_id)
    return render(request, 'blog/detail.html', {'blog': blog_detail})
# Create your views here.
 
cs


##get_object_or_404 : object를 가져오고 없으면 404 에러 띄워라 /모델명(대문자로 시작) + blog 게시글 id 값

   detail 함수는 request,blog_id를 함께 받아 해당 데이터 넘겨줌

   model에서 id기준으로 데이터 가져와 있으면 보여주고 없으면 404 에러

   id값은 기본적으로 django가 기본으로 만들어줌 


3. url config 만들기 -> path 추가 (project폴더 안 -> urls.py)

1
2
3
4
urlpatterns = [
    path('blog/<int:blog_id>',blog.views.detail, name='detail'),
]
 
cs


4. template 수정하기

<detail.html>

1
2
3
4
5
<div class="container jumbotron">
    <h1>{{ blog.title }}</h1>
    <p>{{ blog.pub_date }}</p>
  <p>{{ blog.body }}</p>
</div>
cs


-> 127.0.0.1:8000/blog/blog_id(int)로 접속하면 게시글에 detail로 들어가고 int값이 없으면 404에러 나온다


5. 링크 달기 

<home.html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<html>
<head>
{% comment %} bootstrap4 CSS CDN 부분 {% endcomment %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
{% comment %} bootstrap4 js관련 CDN {% endcomment %}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">
      <class="navbar-brand" href="{% url 'home'%}">Like Lion</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
        </button>
      <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
        <div class="navbar-nav ml-auto">
          <class="nav-item nav-link active" href="{% url 'home'%}">Home</a>
        <class="nav-item nav-link" href="#">Blog</a>
        <class="nav-item nav-link" href="#">수료증</a>
            </div>
    </div>
    </div>
</nav>
 
{% for blog in blogs.all %}
    <div class="container">
        <a href="{% url 'detail' blog.id %}">
            <h1>{{ blog.title }}</h1>
        </a>    
        <p>{{ blog.pub_date }}</p>
        <p>{{ blog.body }}</p>
    </div>
{% endfor %}
</body>
</html>
cs


<detail.html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">
      <class="navbar-brand" href="{% url 'home' %}">Like Lion</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
        </button>
      <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
        <div class="navbar-nav ml-auto">
          <class="nav-item nav-link active" href="{% url 'home' %}">Home</a>
        <class="nav-item nav-link" href="#">Blog</a>
        <class="nav-item nav-link" href="#">수료증</a>
            </div>
    </div>
    </div>
</nav>
 
<h1> detail 페이지 입니다 </h1>
<div class="container jumbotron">
    <h1>{{ blog.title }}</h1>
    <p>{{ blog.pub_date }}</p>
    <p>{{ blog.body }}</p>
    <a href="{% url 'home' %}">돌아가기</a>
</div>
 
</body>
</html>
cs

<블로그 본문 내용 줄여서 보여주기>


1.models.py (클래스에 정의된 body에서 100 글자만 출력)

1
2
     def summary(self):
        return self.body[:100]
cs


2.template 고치기 -> home.html -> {{blog.body}} => {{blog.summary}} ->잘린것처럼 보이니 ...more추가

1
<p>{{ blog.summary }}<a href="{% url 'detail' blog.id %}">....more</a></p>
cs


<글 작성할 수 있는 페이지 만들기>

#제목과 본문 내용을 입력받아야함

1. new.html 생성 -> home.html navbar만 복사 -> 글쓰기 링크 생성

1
<class="nav-item nav-link" href="#">글쓰기</a>
cs


2. form 태그 이용해 글 작성할 수 있게 만들어줌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<br>
<div class="container">
    <form action="">
      <h4>제목: </h4>
      <input type="text" name="title">
      <br>
      <br>
      <h4>본문: </h4>
      <textarea cols=40 rows=10 name="body"></textarea>
      <br>
      <br>
      <input class="btn btn-dark" type="submit" value="제출하기">
  </form>
</div>
cs


3. views.py & url 설정 & template 링크 넣기 

-><views.py>

1
2
def new(request):
    return render(request, 'blog/new.html')
cs


->urls.py

1
path('blog/new/', blog.views.new, name='new'),
cs


->.html에 링크 넣어야할 부분에 

1
{% url 'new' %}
cs



<제출하기 버튼 작동하게 하기>


1. <views.py> :추가된 것

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
 
from .models import Blog
# Create your views here.
 
def create(request):
    blog = Blog()
    blog.title = request.GET['title']
    blog.body = request.GET['body']
    blog.pub_date = timezone.datetime.now()
    blog.save()
    return redirect('/blog/' + str(blog.id))
cs


#

-blog.pub_date :입력한 시간이 자동으로 넘어감/ timezone이라는 패키지를 사용해 import

-redirect  : 요청을 처리하고 보여주는 페이지/ 

-render: '요청이 들어오면 이 html 파일을 보여줘 라는 녀석' <-> redirect: '요청을 들어오면 저쪽 url로 보내버려' 

2.url 설정

1
path('blog/create/', blog.views.create, name='create'),
cs


3. template 수정(new.html -> form 태그)

1
<form action="{% url 'create' %}">
cs




####여기까지완료하면 글쓰기 버튼까지 만들기 완료 

반응형

'Web > Django' 카테고리의 다른 글

[5주차]1.로그인,회원가입  (0) 2019.03.05
[4주차]2.blog-(3)  (0) 2019.03.05
[4주차]2.blog-(1)  (0) 2019.03.04
[4주차]1.pk, path converter, get_object_or_404  (0) 2019.03.03
[3.5주차]Bootstrap  (0) 2019.03.03

+ Recent posts