31. 과제를 모델폼으로 변경하기

Creating forms from modes

  • ForeignKey는 django.forms.ModelChoiceField로 표현
  • ManyToManyField는 django.forms.ModelMultipleChoiceField로 표현
  • 모델 필드가 blank = True면, 폼 필드에서 required = False로 설정된다.
  • 필드의 labelverbose_name으로 설정된다.

The save() method

  • 폼에 바인딩 된 데이터로 부터 데이터베이스 객체를 만들고 저장한다.
  • ModelForm의 subclass는 모델의 인스턴스를 instance 키워드 인자로 받을 수 있다.
    • instance가 있으면, save()는 인스턴스를 update
    • instance가 없으면, save()는 인스턴스 create
# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# 객체 생성
# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()

# Create a form instance with POST data.
>>> a = Author()

# instance는 기존데이터, request.POST는 새로운 데이터
>>> f = AuthorForm(request.POST, instance=a)

# Create and save the new author instance. There's no need to do anything else.
>>> new_author = f.save()
# Post.objetcts.create()
# p = Post()
# p.save()
# 위의 두 가지  방법과 비슷한 개념

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# 객체가 만들어져서 메모리상에 있는 상태
# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()

Model fromsets은 잘 안쓴다. formsets을 쓸 정도가 되면 fontend에서 처리한다.

32. signup 폼도 signup 모델 폼으로 변경

UserCreationForm

youtube 프로젝트

프로젝트 설정

$ mkdir youtube
$ cd youtube

$ pyenv virtualenv 3.4.3 youtube
$ pyenv local youtube
$ pip install django
$ pip install --upgrade google-api-python-client
$ pip freeze > requirements.txt

$ django-admin startproject youtube
$ mv youtube django_app
$ cp ~/django_girls_class/.gitignore .

$ tree
.
├── django_app
│   ├── manage.py
│   └── youtube
│       ├── __init__.py
│       ├── settings.py
│       ├── urls.py
│       └── wsgi.py
└── requirements.txt

$ mkdir .conf
$ vi .gitignore
# Config folders 추가
.conf/

youtube api key 생성 및 관리

아래의 페이지에서 프로젝트를 만들어 키를 발급받는다.

https://console.developers.google.com/iam-admin/projects

발급받은 API 키는 잘 보관해야 한다. 생성한 .conf 폴더 안에 settigs_local.json 파일 생성

{
  "youtube": {
    "API_KEY": "your_key"
  }
}
# youtube/settings.py
ROOT_DIR = os.path.dirname(BASE_DIR)
CONF_DIR = os.path.join(ROOT_DIR, '.conf')
content = open(os.path.join(CONF_DIR, 'settings_local.json')).read()
config = json.loads(content)
print(content)
print(type(content))

print(config)
print(type(config))
$ ./manage.py runserver
{
  "youtube": {
    "API_KEY": "your_key"
  }
}
<class 'str'>
{'youtube': {'API_KEY': 'your_key'}}
<class 'dict'>
{
  "youtube": {
    "API_KEY": "your_key"
  }
}
<class 'str'>
{'youtube': {'API_KEY': 'your_key'}}
<class 'dict'>

관련 링크

Postman

요청 테스트해보기

  • https://www.googleapis.com/youtube/v3/search?part=snippet&q=book

기능 구현

1. api 요청하여 title 출력

  1. .conf 폴더의 settings_local.json을 읽어서
  2. 해당 내용을 json.loads()를 이용해 str -> dict 형태로 변환
  3. requests 라이브러리를 이용(pip install requests), GET요청으로 테이터를 받아온 후
  4. 해당 내용을 다시 json.loads()를 이용해 파이썬 객체로 변환
  5. 이후 내부에 있는 검색결과를 적절히 루프하여 print 해주기

requests quickstart

import os

# 현재 파일의 절대 경로
current_file_path = os.path.abspath(__file__)

# 상위로 이동
go_to_parent_path = os.path.dirname(current_file_path)

# 하위로 이동
go_to_child_path_or_files = os.path.join(go_to_parent_path, 'youtube.py')

print(current_file_path)
print(go_to_parent_path)
print(go_to_child_path_or_files)
# 파이썬이 알아서 파일 자동관리, 파일이 열고 쓰지 않는다는걸 알면 닫아준다.
# 그래도 아래와 같이 써주는게 제일 깔끔하다.
with open(os.path.join(CONF_DIR, 'settings_local.json'), 'r') as f:
    config_str = f.read()
print(config_str)
# 모르면 다 프린트해보자
# 디버그문은 정성스럽게 작성하자
import json
import os

import requests

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CONF_DIR = os.path.join(ROOT_DIR, '.conf')
# print('ROOT_DIR \n {}'.format(ROOT_DIR))
# print('CONF_DIR \n {}'.format(CONF_DIR))

content = json.loads(open(os.path.join(CONF_DIR, 'settings_local.json')).read())
# print(content)


payload = {
    'part': 'snippet',
    'q': 'grizemanmm',
    'key': content['youtube']['API_KEY'],
    'maxResults': 50,
}
r = requests.get('https://www.googleapis.com/youtube/v3/search', params=payload)
# print(type(r.content))

raw_data = r.json()
# title = raw_data['items'][0]['snippet']['title']
# print(title)

items = raw_data['items']
for index, item in enumerate(items):
    title = item['snippet']['title']
    print('title: {}'.format(title))

2. 검색 요청 결과를 데이터베이스에 저장하기

  1. video app을 생성하고

  2. 유튜브 영상의 정보를 저장할 수 있는 Model구현, Migrations

  3. POST요청을 받으면 요청에서 온 키워드로 유튜브를 검색 후 결과를 DB에 저장하는 View구현 방금 작성한 code/youtube.py파일의 내용을 하나의 함수로 구현 3-1. GET요청시에는 검색 input이 하나 있는 페이지를 단순 render

    ​ 3-1-1. 해당 페이지에는 form요소가 있어야 함

    3-2. POST요청은 GET요청에 있는 form을 통해서 이루어짐

    3-2-1. POST요청으로는 keyword 또는 q라는 이름으로 검색키워드 정보를 전달

    ​ 3-2-2. 전달받아온 키워드를 이용해 유튜브 검색 API실행 ​ 3-2-3. 이후 해당 결과를 적절히 순회하며 DB에 저장 ​ 3-2-4. 저장되어있는 모든 데이터를 템플릿에 전달

  4. 위 View를 나타낼 수 있는 Template구현

  5. View와 Template연결

published_date_str = item['snippet']['publishedAt']

# pip install python-dateutil
# 자동으로 스트링을 데이트타입으로 변환
published_date = parse(published_date_str)