외부 api에서 값 받아오기
mydjango.py
def index(request):
json_url = "https://raw.githubusercontent.com/pyhub-kr/dump-data/main/melon/melon-20230906.json"
response = requests.get(json_url)
if response.ok:
song_list = response.json()
else:
song_list = []
return render(request, "index.html", {"song_list": song_list})
index.html
<form action="" method="get" autocomplete="off">
<input type="text" name="query" placeholder="검색어를 입력해주세요 : " autofocus
value="{{ query }}">
검색 기능 (filter)
def index(request):
query = request.GET.get("query", "").strip()
json_url = "https://raw.githubusercontent.com/pyhub-kr/dump-data/main/melon/melon-20230906.json"
response = requests.get(json_url)
if response.ok:
song_list = response.json()
else:
song_list = []
if query:
song_list = filter(
lambda song: query in song["가수"],
song_list,
)
return render(request, "index.html", {"song_list": song_list, "query": query})
데이터 베이스
데이터 베이스 연동
- python은 sqlite3를 기본 라이브러리로 갖고 있음
import sqlite3
connection = sqlite3.connect("melon-20230906.sqlite3")
cursor = connection.cursor()
cursor.execute("SELECT * FROM songs")
column_names = [desc[0] for desc in cursor.description]
print(column_names)
songs_list = cursor.fetchall()
for song_tuple in songs_list :
song_dict = dict(zip(column_names, song_tuple))
print(song_dict["곡명"], song_dict["가수"])
connection.close()
데이터 베이스 데이터 검색하기
import sqlite3
query = "악뮤"
print("검색어 : ", query)
connection = sqlite3.connect("melon-20230906.sqlite3")
cursor = connection.cursor()
connection.set_trace_callback(print)
param = '%' + query + '%'
sql = f"SELECT * FROM songs WHERE 가수 LIKE '{param}' OR 곡명 LIKE '{param}'"
cursor.execute(sql)
column_names = [desc[0] for desc in cursor.description]
print(column_names)
songs_list = cursor.fetchall()
print("list size", len(songs_list))
for song_tuple in songs_list :
song_dict = dict(zip(column_names, song_tuple))
print("{곡명} {가수}".format(**song_dict))
connection.close()
SQL Injection 공격 방어하기
param = '%' + query + '%'
sql = "SELECT * FROM songs WHERE 가수 LIKE ? OR 곡명 LIKE ?"
cursor.execute(sql, [param,param])
함수로 만들기
def index(request):
query = request.GET.get("query", "").strip()
song_list = get_song_list(query)
return render(request, "index.html", {"song_list": song_list, "query": query})
def get_song_list(query: str):
connection = sqlite3.connect("melon-20230906.sqlite3")
cursor = connection.cursor()
connection.set_trace_callback(print)
if query:
param = '%' + query + '%'
sql = "SELECT * FROM songs WHERE 가수 LIKE ? OR 곡명 LIKE ?"
cursor.execute(sql, [param, param])
else:
cursor.execute("SELECT * FROM songs")
column_names = [desc[0] for desc in cursor.description]
print(column_names)
songs_list = []
songs_list = [dict(zip(column_names, song_tuple))
for song_tuple in cursor.fetchall()]
connection.close()
return songs_list
장고 DB 추상화 계층 통해서 connection 얻기
- 하나의 장고 프로젝트에서 여러 DB 연결이 가능함
- 이제 이 코드는 DB종류에 상관없이 실행됨
settings.configure(
ROOT_URLCONF=__name__,
DEBUG=True,
SECRET_KEY="secret",
DATABASES={
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": "melon-20230906.sqlite3",
}
},
TEMPLATES=[
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": ["templates"],
}
],
)
- connect에
alt
+ enter
해서 django가 지원하는 연결로 변경
def get_song_list(query: str):
cursor = connection.cursor()
if query:
param = '%' + query + '%'
sql = "SELECT * FROM songs WHERE 가수 LIKE %s OR 곡명 LIKE %s"
cursor.execute(sql, [param, param])
else:
cursor.execute("SELECT * FROM songs")
column_names = [desc[0] for desc in cursor.description]
print(column_names)
songs_list = []
songs_list = [dict(zip(column_names, song_tuple))
for song_tuple in cursor.fetchall()]
return songs_list
장고 ORM인 모델 활용
- DB의 종류와 상관없이 장고가 관리해주는 connection을 가지고 모든 DB에서 동일하게 동작하는 코드
import sys
import django
import requests
from django.db import models
from django.conf import settings
from django.core.management import execute_from_command_line
from django.db import connection
from django.db.models import Q
from django.shortcuts import render
from django.urls import path
settings.configure(
ROOT_URLCONF=__name__,
DEBUG=True,
SECRET_KEY="secret",
DATABASES={
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": "melon-20230906.sqlite3",
}
},
TEMPLATES=[
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": ["templates"],
}
],
)
django.setup()
class Song(models.Model):
id = models.AutoField(primary_key=True)
가수 = models.CharField(max_length=100)
곡명 = models.CharField(max_length=200)
곡일련번호 = models.IntegerField()
순위 = models.IntegerField()
앨범 = models.CharField(max_length=200)
좋아요 = models.IntegerField()
커버이미지_주소 = models.URLField()
class Meta:
db_table = "songs"
app_label = "mydjango"
def index(request):
query = request.GET.get("query", "").strip()
song_list = Song.objects.all()
if query:
song_list = song_list.filter(
Q(곡명__icontains=query) | Q(가수__icontains=query)
)
return render(request, "index.html", {"song_list": song_list, "query": query})
urlpatterns = [
path("", index),
]
execute_from_command_line(sys.argv)
React 맛보기
{# 장고 템플릿 엔진 주석 문법 : templates/index.html 경로의 파일 #}
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8"/>
<title>Melon List</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.16/babel.min.js"></script>
</head>
<body>
<div class="container mx-auto">
<h1 class="font-bold text-2xl">Melon List</h1>
<form action="" method="get" autocomplete="off" class="my-4">
<input type="text" name="query" placeholder="검색어를 입력해주세요 : " autofocus
value="{{ query }}" class="w-full p-2 border rounded focus:outline-none focus:ring">
</form>
<table class="min-w-full bg-white border border-gray-300 divide-y divide-gray-300"
id="song-list-table">
<thead>
<tr class="text-center">
<th class="py-2 px-4 border-b">곡명</th>
<th class="py-2 px-4 border-b">가수</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script type="text/babel">
function SongList() {
const [songList, setSongList] = React.useState([]);
React.useEffect(() => {
fetch("api/song-list.json")
.then(response => response.json())
.then(_songList => {
setSongList(_songList);
});
}, []);
return (
<>
{songList.map(song => {
return (
<tr key={song.id}>
<td>{song.곡명}</td>
<td>{song.가수}</td>
</tr>
)
})}
</>
)
}
ReactDOM.render(
<SongList/>,
document.querySelector("#song-list-table tbody")
)
</script>
</div>
</body>
</html>