https://vicapor.tistory.com/109

 

Django Ninja Tutorial 4

https://vicapor.tistory.com/108 Django Ninja Tutorial 3 https://vicapor.tistory.com/107 Django Ninja Tutorial 2 https://vicapor.tistory.com/7 Django Ninja Tutorial 1 Django Ninja 공식 페이지 : https..

vicapor.tistory.com

 

이번에는 Schema를 작성하는 방법에 대해서 알아보려고 한다. 

 

초기 버전 Django Ninja에서는 직접 자료형을 명시해줘야했다. 

 

1.

class TrackSchema(Schema):
    title: str
    artist: str
    duration: float
    last_play: datetime

 

 

하지만 버전이 업그레이드가 되고 다음과 같은 2가지 방법으로 작성이 가능하다. 

 

2.

from ninja import ModelSchema

class TrackSchema(ModelSchema):
    class Config:
        model = Track
        model_fields = ['title', 'last_play', 'artist', 'duration']

 

 

3.

from ninja.orm import create_schema
from .models import Track

TrackSchema = create_schema(Track, fields=['title', 'last_play', 'artist', 'duration'])

 

작성한 모델에 대해 자동으로 Schema를 만들어주니 더욱 편리하게 사용할 수 있을 것이다. 

'Back-End > Django-ninja' 카테고리의 다른 글

Django Ninja Router  (0) 2021.12.07
Django Ninja Render  (0) 2021.11.30
Django Ninja Tutorial 4  (0) 2021.11.30
Django Ninja Tutorial 3  (0) 2021.11.29
Django Ninja Tutorial 2  (0) 2021.11.29

https://vicapor.tistory.com/108

 

Django Ninja Tutorial 3

https://vicapor.tistory.com/107 Django Ninja Tutorial 2 https://vicapor.tistory.com/7 Django Ninja Tutorial 1 Django Ninja 공식 페이지 : https://django-ninja.rest-framework.com/ 장고 닌자는 FAST API..

vicapor.tistory.com

3편에 이은 4편이다. 이번에는 파일을 업로드 하는 api를 구현해보려고 한다. 

 

 

1. Template 생성

 

1) url

djninja/urls.py

from django.contrib import admin
from django.urls import path
from tracks.api import api
from tracks.views import index

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', api.urls),
    path("index/", index, name='index')
]

 

 

2) view

tracks/views.py

from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, 'index.html', {})

 

3) template

tracks/templates/index.html

<form method="post" action="{% url 'api-1.0.0:upload' %}" enctype='multipart/form-data'>
    <input type="file" name="file">
    <button type="submit">Submit</button>
</form>

 

 

2. File upload 구현

 

tracks/api.py

@api.post("/upload", url_name='upload')
def upload(request, file: UploadedFile = File(...)):
    data = file.read().decode()
    return {
        'name': file.name,
        'data': data,
    }

 

 

추가)

Django Ninja는 기본적으로 Swagger 기능을 제공해주는데

 

http://127.0.0.1:8000/api/docs 로 접속하면 확인할 수 있다. 

'Back-End > Django-ninja' 카테고리의 다른 글

Django Ninja Render  (0) 2021.11.30
Django Ninja Tutorial 5  (0) 2021.11.30
Django Ninja Tutorial 3  (0) 2021.11.29
Django Ninja Tutorial 2  (0) 2021.11.29
Django Ninja Tutorial 1  (0) 2021.07.09

https://vicapor.tistory.com/107

 

Django Ninja Tutorial 2

https://vicapor.tistory.com/7 Django Ninja Tutorial 1 Django Ninja 공식 페이지 : https://django-ninja.rest-framework.com/ 장고 닌자는 FAST API에서 영감을 받아서 만들어진 Web FrameWork이다. 빠른속도..

vicapor.tistory.com

Django Ninja Tutorial 2편에 이은 3편이다. 오늘은 API CRUD를 구현해보는 튜토리얼이다. 

 

 

1. POST Method

@api.post("/tracks", response={201: TrackSchema})
def create_track(request, track: TrackSchema):
    track = Track.objects.create(**track.dict())
    return track

Json으로 이루어진 데이터가 정상적으로 통신되었을 때, 201를 응답해주고 Schema의 검증을 통해서 데이터 형식을 확인하고 데이터를 만들어준다. 

 

 

2. PUT Method

@api.put("/tracks/{track_id}", response={200: TrackSchema, 404: NotFoundSchema})
def change_track(request, track_id: int, data: TrackSchema):
    try:
        track = Track.objects.get(pk=track_id)
        for attribute, value in data.dict().items():
            setattr(track, attribute, value)
        track.save()
        return 200, track
    except Track.DoesNotExist as e:
        return 404, {"message": "Track does not exist"}

수정은 먼저 track_id를 통해 수정할 데이터를 가져오고 수정할 데이터를 data에 TrackSchema를 통해 검증한다. 

그리고 setattr을 통해 atrribute와 value를 딕셔너리 형태(Json)로 저장해놓는다. 

 

201: 성공, 400: 문제

 

 

3. DELETE Method

@api.delete("/tracks/{track_id}", response={200: None, 404: NotFoundSchema})
def delete_track(request, track_id: int):
    # curl -X DELETE http://localhost:8000/api/tracks/7729
    try:
        track = Track.objects.get(pk=track_id)
        track.delete()
        return 200
    except Track.DoesNotExist as e:
        return 404, {"message": "Could not find track"}

delete method는 검증할 데이터가 없기 때문에 track을 리턴하지 않는다.

response는 응답 온 데이터 즉 return 한 데이터를 의미한다. 검증할 리턴 값이 없기 때문에 None으로 설정해준다.

'Back-End > Django-ninja' 카테고리의 다른 글

Django Ninja Render  (0) 2021.11.30
Django Ninja Tutorial 5  (0) 2021.11.30
Django Ninja Tutorial 4  (0) 2021.11.30
Django Ninja Tutorial 2  (0) 2021.11.29
Django Ninja Tutorial 1  (0) 2021.07.09

https://vicapor.tistory.com/7

 

Django Ninja Tutorial 1

Django Ninja 공식 페이지 : https://django-ninja.rest-framework.com/ 장고 닌자는 FAST API에서 영감을 받아서 만들어진 Web FrameWork이다. 빠른속도와 쉬운 사용법 Swagger 기능 지원을 제공하고 있다. 아직..

vicapor.tistory.com

 

1편에서 이어진 튜토리얼 2이다. 1편을 먼저 확인하고 2편을 진행하면 된다. 이번 튜토리얼에서는 GET 메소드를 구현해보는 시간을 갖는다. 

 

 

1. schema.py 작성

tracks/schema.py 를 생성해주고 아래 코드를 입력해준다.

from datetime import datetime
from ninja import Schema


class TrackSchema(Schema):
    title: str
    artist: str
    duration: float
    last_play: datetime
    

class NotFoundSchema(Schema):
    message: str

이것이 Django Ninja에서 말했던 Pydantic Data Validation을 말한다. 필드에 정확한 값이 전달되는지 검증하기 위해서 사용한다. 각 field의 변수 타입을 명시해주는 것을 통해 잘못된 데이터 값이 들어오는 것을 방지한다. 

 

 

2. api.py 수정

 

1) 모든 데이터 GET

from typing import List

from ninja import NinjaAPI
from tracks.models import Track
from tracks.schema import TrackSchema, NotFoundSchema


api = NinjaAPI()

@api.get("/tracks", response=List[TrackSchema])
def tracks(request):
    return Track.objects.all()

사용방법은 아주 간단하다. 데코레이터를 통해 메소드를 표시한다. get 메소드를 통해 모든 track의 정보를 가져와보겠다. tracks라는 이름의 함수로 Track 모델의 모든 데이터을 return 한다. 

 

response=List[TrackSchema]는 1에서 작성한 Schema의 자료 값을 검증한다음 List로 반환한다. 

 

참고)

typing에 대해 더 알아보고 싶다면 아래 사이트를 참고하면 된다. 

https://www.daleseo.com/python-typing/

 

 

2) 원하는 데이터를 id값으로 GET

@api.get('/tracks/{track_id}', response={200: TrackSchema, 404: NotFoundSchema})
def track(request, track_id: int):
    try:
        track = Track.objects.get(pk=track_id)
        return track
    except Track.DoesNotExist as e:
        return 404, {"message": "Track does not exist"}

{track_id}를 통해 원하는 데이터의 정보를 가져올 수 있다. track_id는 정수가 들어가야 하므로 track_id: int를 명시 해준다.

 

(1) 데이터가 존재할 때 (정상적인 통신 : 200) -> TrackSchema을 실행한다.

(2) 데이터가 존재하지 않을 때 (잘못된 통신 :  404) -> NotFoundSchema

 

try, except를 사용해서 데이터가 존재할 때, Track에 pk 값을 통해 원하는 데이터를 반환하고 존재하지 않을 때, messeage에 Track does not exist라는 메세지를 담아서 404와 같이 return한다. 

 

 

3) 특정 정보를 통해 원하는 데이터 GET

@api.get("/tracks", response=List[TrackSchema])
def tracks(request, title: Optional[str] = None):
    if title:
        return Track.objects.filter(title__icontains=title)
    return Track.objects.all()

1) 에서 작성한 tracks를 수정해주자. 

이제 ?title을 통해 title로 데이터를 가져올 수 있다. 항상 title이 포함되지 않기 때문에 Optional로 설정한다. 

title__icontains을 통해 title의 일부 문자만으로 데이터를 가져올 수 있게 한다.

 

 

'Back-End > Django-ninja' 카테고리의 다른 글

Django Ninja Render  (0) 2021.11.30
Django Ninja Tutorial 5  (0) 2021.11.30
Django Ninja Tutorial 4  (0) 2021.11.30
Django Ninja Tutorial 3  (0) 2021.11.29
Django Ninja Tutorial 1  (0) 2021.07.09

Cache에 대해서 알아보자.

 

웹 캐시(영어: web cache) 또는 HTTP 캐시(HTTP cache)는 서버 지연을 줄이기 위해 웹 페이지, 이미지, 기타 유형의 웹 멀티미디어 등의 웹 문서들을 임시 저장하기 위한 정보기술이다. 웹 캐시 시스템은 이를 통과하는 문서들의 사본을 저장하며 이후 요청들은 특정 조건을 충족하는 경우 캐시화가 가능하다.[1] 웹 캐시 시스템은 일종의 어플라이언스나 컴퓨터 프로그램을 의미할 수 있다. 동일한 서버에 다시 접근할 때에는 근처에 있는 프록시 서버의 웹 캐시에 저장된 정보를 불러오므로 더 빠른 열람이 가능하다.

 

출처: https://ko.wikipedia.org/wiki/%EC%9B%B9_%EC%BA%90%EC%8B%9C

 

소규모 사이트에는 굳이 필요 없을 수 있겠으나 사이트의 규모가 커지면 캐시를 적용하는 것을 고려해야한다. (사이트의 응답속도에 큰 차이가 있기 때문이다.)

 

 

1. Settings/dev.py 수정

...

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "wagtail project 폴더의 경로"
    }
}

...

참고로 경로를 복사하면 User\mycomputer\desktop.. 이런 형식으로 되어 있을텐데 \을 /로 경로 수정해줘야한다. 

경로는 cache가 저장될 위치를 의미하는데 원하는 경로가 있으면 수정해주면 된다. 

 

 

2. Templates 사용

 

blog/blog_listing_page.html

{% load cache %}

<div class="container">
        {% for post in posts %}
            {% cache 604800 blog_post_preview post.id %}
                <div class="row mt-5 mb-5">
                    <div class="col-sm-3">
                        {% image post.banner_image fill-250x250 as blog_img %}
                        <a href="{{ post.url }}">
                            <img src="{{ blog_img.url }}" alt="{{ blog_img.alt }}">
                        </a>
                    </div>
                    <div class="col-sm-9">
                            <h2>{{ post.custom_title }}</h2>
                            {% if post.specific.subtitle %}
                                <p>{{ post.specific.subtitle }}</p>
                            {% endif %}
                            <a href="{{ post.url }}" class="btn btn-primary mt-4">{{ post.title }}</a>
                        </a>
                    </div>
                </div>
                <br>
            {% endcache %}
        {% endfor %}
</div>

604800은 초를 의미하는데 604800초는 1주일을 의미한다. 캐시의 유지 기한이다. 설정을 해놓지 않으면 영원히 캐시가 유지된다. 그리고 blog_post_preview는 캐시 조각의 이름을 정해준 것이다. 마지막 post.id 각각의 post에 고유의 cache 아이디를 부여해준 것이다. 

 

주의)

이미 캐싱 되어 있는 데이터에 추가적인 정보를 넣게 되면 나타나지 않는다. 캐싱 되어 있어 그저 기존의 정보를 던져주기 때문이다. 그럴 때에는 직접 캐시 파일들을 삭제하거나 

from django.core.cache import cache
cache.clear()

Django shell을 열어서 위 명령어를 실행시켜주면 된다. 

 

 

추가)

 

다만 일부 정보만 주기적으로 업데이트 되고 나머지는 그렇지 않다면 모든 캐시를 삭제하는 방법은 비효율적이다. 이럴경우 필요한 곳에서만 캐쉬를 삭제하고 업데이트 해주는 방법이 맞다고 볼 수 있다. 

 

from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key


class BlogDetailPage(Page):

	....

  def save(self, *args, **kwargs):
    key = make_template_fragment_key("blog_post_preview", [self.id])
    cache.delete(key)
    return super().save(*args, **kwargs)

블로그 상세 페이지가 자주 업데이트 된다고 가정한다면 블로그 상세 페이지가 새로 save될 때마다 실행하는 save Magic Method를 만든다. 

 

key = make_template_fragment_key(something)는 something이라는 캐시를 템플릿에서 찾아서 key라는 변수에 저장한다. 그리고 cache.delete(key)를 사용하여 지우고 리턴해준다. 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Tags  (0) 2021.12.01
Wagtail Ajax Template  (0) 2021.12.01
Wagtail Recaptcha  (0) 2021.11.28
Wagtail Rich Editor Extend  (0) 2021.11.27
Wagtail API v2 Serializing Rich Text  (0) 2021.11.25

매크로 공격 방지를 위한 Recaptcha 기술을 사용하는 방법에 대해서 알아보자

 

Google Recaptcha를 사용한다. 

 

https://github.com/springload/wagtail-django-recaptcha

 

1. Google Recaptcha 접속

 

https://www.google.com/recaptcha/about/

 

 

새로 Recaptcha를 생성하고 사이트 Key와 비밀 Key를 따로 저장 해 놓는다. 

 

 

2. 모듈 설치

pip install django-wagtail-recaptcha

 

 

3. settings/base.py 수정

INSTALLED_APPS = [
	...
	'captcha',
      'wagtailcaptcha',
]

...

RECAPTCHA_PUBLIC_KEY = "사이트 KEY"
RECAPTCHA_PRIVATE_KEY = "비밀 KEY"
NOCAPTCHA = True

captcha는 2번에서 설치한 패키지 모듈이고 wagtailcaptcha는 captcha 모듈 기반의 wagtail captcha이다.

 

그리고 아까 Google Recaptcha에서 가져온 키를 넣는다. 

 

 

4. Models.py 수정

from wagtailcaptcha.models import WagtailCaptchaEmailForm


class ContactPage(WagtailCaptchaEmailForm): # AbstractEmailForm
    
    template = 'contact/contact_page.html'
    
    intro = RichTextField(blank=True)
    thank_you_text = RichTextField(blank=True)
    
    content_panels = AbstractEmailForm.content_panels + [
        FieldPanel('intro'),
        InlinePanel('form_fields', label="Form Fields"),
        FieldPanel('thank_you_text'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6")
            ]),
            FieldPanel("subject"),
        ], heading="Email Settings"),
    ]

기존에 AbstractEmailForm로 만들었던 Contact Page를 WagtailCaptchaEmailForm로 바꿔주자. 

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail Ajax Template  (0) 2021.12.01
Wagtail Cache  (0) 2021.11.28
Wagtail Rich Editor Extend  (0) 2021.11.27
Wagtail API v2 Serializing Rich Text  (0) 2021.11.25
Wagtail API v2 Serializing a QuerySet  (0) 2021.11.25

+ Recent posts