2023/0727
2023.07.26 - [LG 헬로비전 DX DATA SCHOOL/Python] - Django
Django
2023/07/26 2023.07.25 - [LG 헬로비전 DX DATA SCHOOL/DATA BASE] - 데이터 베이스 데이터 베이스 2023-07-25 1. 데이터 베이스 1.1) SQR 사용에 따른 분류 RDBMS : 테이블 구조를 이용하는 데이터베이스, SQL을 이용해서
dxdata.tistory.com
저번 Django의 기본적인 내용을 보고 오시면 좋을 겁니다!
기본 적인 내용들은 반복될 예정입니다.
1. API(Application Programming Interface)
- 프로그램과 프로그램을 연결시켜주는 매개체
- 데이터의 형태로 제공될 수도 있고 함수나 클래스 또는 패키지 또는 프레임워크 형태로 제공될 수도 있습니다.
- Open API : API를 누구나사용할 수 있도록 공개한 것
2. CSR(Client Side Rending)
- API Server는 화면 구성은 하지 않고 데이터만 제공하고 클라이언트 프로그램에서 데이터를 받아서 화면 출력을 하게되는데 이런 구조를 Client Side Rendering 이라고 합니다.
- API Server를 구축할 때 Restful 하게 구성하는 것을 권장
3. REST
- REpresentational State Transfer 의 약자로 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍쳐의 종류
- 원칙 :
인터페이스 일관성 : 어떤 기기에서 접근을 하던 동일한 작업은 동일한 URL로 처리
무상태(Stateless) : 클라이언트의 컨텍스트를 서버에 저장하지 않아야 한다.
캐싱 기능 활용
계층화
Code on Demand : 기능을 확장할 수 있도록 생성
클라이언트와 서버 분리
Client <-> 연결 서버 <-> Middel Ware(Security, Load Balancing) <-> API Server(일을 하고 결과를 생성) <-> Data Server
4. Rest API Server 프로젝트 생성 및 설정!
4.1) 프로젝트 디렉토리 생성
pycharm의 new 프로젝트를 생성하여 가상환경 생성!
4.2) 필요한 패키지 설치
- django
- djangorestframework
- mysqlclient
pip install django
pip install djangorestframework
pip install mysqlclient
4.3) django 프로젝트 생성
- apiserverproject
django-admin startproject apiserverproject .
4.4) django 애플리케이션 생성
- apiserverapplication
python manage.py startapp apiserverapplication
4.5) settings.py 에서 필요한 내용 수정
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"apiserverapplication",
"rest_framework"
]
- 데이터 베이스 접속 정보 수정
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "svng",
"USER": "root",
"PASSWORD": "252585",
"HOST": "127.0.0.1",
"PORT": "3306"
}
}
- 시간 변경
TIME_ZONE = "Asia/Seoul"
4.6) 프로젝트 실행
python manage.py runserver (터미널에서 작성)
4.7) 브라우저에서 접속
초기 django의 기본 페이지 형식이 나타납니다.
5. 프로젝트에 사용할 테이블 생성 및 연결 확인
5.1) models.py 파일에 필요한 모델을 작성
class Item(models.Model):
itemid = models.IntegerField(max_length=10)
title = models.CharField(max_length=50)
author = models.CharField(max_length=50)
category = models.CharField(max_length=10)
pages = models.IntegerField()
price = models.IntegerField()
published_date = models.DateField()
description = models.CharField(max_length=150)
5.2) models.py 의 변경 내용을 데이터베이스에 적용
python manage.py makemigarations
python manage.py migrate
5.3) 변경 내용이 적용되었는지 확인
use 데이터베이스이름;
show tables;
desc 테이블이름(애플리케이션이름_모델이름);
6. 직렬화
- Serializable(직렬화) : 프로그래밍 언어에서 만든 객체를 전송하기 위한 작업
- Client 에서 받은 데이터를 Python 객체로 변환해주고 Python 객체를 Client에게 전송하기 위한 JSON 문자열로 변환해주는 역할을 수행
- 이 작업 수행시, Response로 return 해야하고, 이 작업을 수행하지 않을 시, JsonResponse로 return 해주면 된다.
- 애플리케이션에 serializers.py 파일을 만들고 작성
from rest_framework import serializers
from .models import Item
class ItemSerializer(serializers) :
class Meta :
model = Item
fields = ['itemid', 'title', 'author',
'category', 'pages', 'price',
'published_date', 'description']
7. 샘플 URL 처리
7.1) 프로젝트 urls.py 파일에 가서 URL을 처리할 함수 나 클래스와 URL을 연결
- 프로젝트의 urls.py 에 직접 연결을 시키게 되면 애플리케이션이 여러 개 일 때 코드가 너무 길어지고 가독성이 떨어짐.
- 따라서 각 Application이 URL을 처리하도록 설정하는 것이 좋다.
기존 : path("URL", 함수) 형태로 직접 연결하여 사용
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
#example로 시작하는 url은 apiserverapplicaion.urls.py에서 처리하도록 설정
path("example/", include("apiserverapplication.urls"))
7.2) 애플리케이션에 urls.py 파일을 추가하고 URL 과 처리할 함수나 클래스를 연결
from django.contrib import admin
from django.urls import path
from .views import helloAPI
urlpatterns = [
#/example/hello/ 요청이 오면 helloAPI 함수가 처리
path("hello/", helloAPI)
#아직 helloAPI를 만들지 않아 에러
#그럼 이제 helloAPI 만들러 고고!
7.3) 애플리케이션의 views.py 파일에 helloAPI 함수를 작성
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
# Create your views here.
#GET 요청만 처리
@api_view(['GET'])
def helloAPI(request):
return Response("HELLLO REST API")
7.4) 서버를 재실행하고 브라우저에서 확인 (로컬 주소 + /example/hello/)
여기서 잠깐!
example/ 을 호출후 hello/를 호출하였을 때 나타나는 기능만 구현함.
따라서 example/만 치거나, hello/만 치면 아무런 기능이 구현되지 않아 page not found 에러가 발생한다
7.5) Response 클래스
- 응답 결과를 위한 클래스
- 첫번째 매개변수는 데이터이고 status는 상태 코드
- 첫번째 매개변수만을 이용하면, 성공한 경우에는 괜찮으나 실패할 경우 어떤 이유로 실패했는지 알 수가 없음.
- 상태코드
200 번대 - 정상
300 번대 - Redirect 중
400 번대 - Client 오류 (403: Forbidden -> 권한 부족, 404 -> URL오류)
500 번대 - Server 오류
8. 데이터 삽입 처리 : 삽입은 POST방식
8.1) 처리할 함수를 생성 - views.py
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
# Create your views here.
from serializers import ItemSerializer
from rest_framework import status
#GET 요청만 처리
@api_view(['GET'])
def helloAPI(request):
return Response("HELLLO REST API")
@api_view(['POST'])
def itemsAPI(request):
#클라이언트가 전송한 데이터를 모델이 사용할 수 있는 데이터로 변환
serializer = ItemSerializer(data = request.data)
#유효성 검사
if serializer.is_valid():
serializer.save() #데이터 저장
#성공시, 전송한 데이터를 다시 전송
return Response(serializer.data, status.HTTP_201_CREATED)
#실패시 처리
Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
8.2) URL과 함수를 연결 - urls.py
from django.contrib import admin
from django.urls import path
from .views import helloAPI, itemsAPI
urlpatterns = [
#/example/hello/ 요청이 오면 helloAPI 함수가 처리
path("hello/", helloAPI),
#example/fbv/items 요청이 오면 itemsAPI 함수가 처리
path("fbv/items", itemsAPI)
]
serializers.py
from rest_framework import serializers
from .models import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ['itemid', 'title', 'author',
'category', 'pages', 'price',
'published_date','description']
서버 실행 후 아래의 데이터 삽입 -> 200 번대의 결과 -> 성공
{
"itemid":1,
"title":"POST",
"author":"writer",
"category":"분류",
"pages":300,
"price":12000,
"published_date":"2023-07-27",
"description":"설명"
}
#post 에 넣을 데이트
8.3) 실행 한 후 브라우저에 lacalhost:8000/example/fbv/books 를 입력
- 화면의 상자에 데이터를 입력하고 POST를 눌러서 데이터가 전송되는지 확인
- 에러가 발생하면 urls 의 url 과 views의 함수 이름을 먼저 확인하고 models와 serializers에 작성한 클래스의 필드 이름을 확인하고 브라우저에서 입력한 이름과 같은지 확인.
- models에 작성한 모델과 serializers에 입력한 내용은 처음 한 번만 확인하면 됩니다.
9. 전체 데이터 가져오기 구현 - GET
9.1) views.py 파일의 itemAPI 함수만 수정
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .serializers import ItemSerializer
from rest_framework import status
from .models import Item
@api_view(['POST','GET'])
def itemsAPI(request):
#전송 방식을 확인하는 방법은 request.method를 확인하면 됩니다.
if request.method=='GET':
#전체 데이터 가져오기
serializer = ItemSerializer(data=request.data)
items = Item.objects.all()
return Response(serializer.data, status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = ItemSerializer(data=request.data)
if serializer.is_valid():
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
9.2) URL은 동일하게 출력되는지 확인
완료!
10. 데이터 1개 가져오기
- 기본키 값을 매개변수로 받아야 한다.
매개변수 1개를 받을 때는 직접 입력하지 않고 URL 뒤에 붙여서 전송.
- 애플리케이션 urls.py 에 URL을 처리할 수 있는 함수를 등록
- views.py 에 itemAPI 함수를 추가
#urls.py 속 urlpatterns에 추가
#itemid 값을 받아, 1개의 데이터를 찾아오는 것을 bookAPI함수가 처리
path("fbv/book/<int:itemid>", itemAPI)
#views.py 내용에 추가
#기본키를 가지고 데이터를 1개 찾아오는데 없으면 404에러 발생
from rest_framework.generics import get_object_or_404
@api_view(['GET'])
def itemAPI(request, itemid) :
#기본키를 바탕으로 데이터 1개 가져오기
item = get_object_or_404(Item, itemid=itemid)
serializer = ItemSerializer(item)
return Response(serializer.data, status=status.HTTP_200_OK)
11. Web Client 에서 서버에 데이터 요청
11.1) ajax(Asynchronous Javascript XML)
- 비동기적으로 Server에게 데이터를 요청하는 것
- 한 번 요청하고 응답이 오면, 연결이 해제됩니다.
11.2) Web Socket
- TCP 연결을 이용해서 Web Server 와 데이터를 주고 받을 수 있는 HTML5 API
- 연결 한 후 명시적으로 close()를 호출하지 않으면 연결 유지
- ajax는 헤더의 크기가 websocket 보다 큼
- 짧은 메시지를 자주 전송하는 경우에는 websocket이 ajax 보다 효율적
11.3) SSE(Server Sent Event - Web Push)
- 서버에게 구독 신청을 하면 서버가 데이터를 일방적으로 보내주는 방식
- 구독 신청을 하면 이후에는 데이터 요청을 하지 않아도 데이터를 받을 수 있습니다.
- 알림을 받는 방식입니다.
APNS(Apple Push Notification Service)
FCM(Firebase Cloud Messaging Service)
11.4) 모바일 푸시
- 스마트 폰 애플리케이션에서 알림을 받고자 하는 경우 아래 2개 중 하나를 학습
APNS(Apple Push Notification Service)
FCM(Firebase Cloud Messaging Service)
12. 비동기 통신
12.1) 구현 방법
- ajax 이용 : XMLHttpResquest 이용
- Promise 이용
- Fetch API 이용 - 가장 권장
- axios 같은 외부 라이브러리 이용 - 가장 많이 사용
12.2) ajax
- 객체 생성
new XMLHttpRequest()
- 객체 속성
responseText : XML 이외의 데이터를 받았을 때 데이터
responseXML : XML 데이터를 받은 경우 받은 내용
- 객체의 메서드
setRequestHeader(헤더이름, 데이터): 헤더 설정
open(전송방식, 전송할 URL, 비동기 전송 여부): 연결 설정
send(데이터) : 요청 전송
sendAsBinary(데이터): 바이너리 데이터(파일) 전송시 호출
- 이벤트
load : 데이터를 전부 전송받으면 호출되는 이벤트
error : 데이터를 전송받는 도중 에러가 발생한 경우 호출되는 이벤트
12.3) 실습을 위해서 화면 생성
- 프로젝트의 urls.py 파일에 요청을 생성
from django.contrib import admin
from django.urls import path, include
from apiserverapplication import ajax
urlpatterns = [
path("admin/", admin.site.urls),
#example로 시작하는 url은 apiserverapplicaion.urls.py에서 처리하도록 설정
path("example/", include("apiserverapplication.urls")),
path("ajax/", views.ajax)
- 애플리케이션의 views.py 파일에 ajax 함수를 생성
#views 파일에서 ajax 함수 생성
def ajax(request):
return render(request, 'ajax.html')
- templates 디렉토리 생성 후, ajax.html 생성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AJAX</title>
</head>
<body>
<div id="display"></div>
<button id="allbtn">전체 데이터 가져오기</button>
</body>
<script>
document.getElementById("allbtn").addEventListener("click",
(e) => {
let request = new XMLHttpRequest();
//출력하는 함수에 객체 대입하면 toString 메서드를 호출합니다.
//python은 __str__ 메서드를 호출합니다.
//위 메서드를 재정의하면 그 내용이 출력되지만, 재정의를 하지 않으면
//기본적으로 설정된 값이 출력된다.
alert(request)
//요청 생성
//http://localhost:8000/example/fbv/items
//현재는 http://localhost:8000/ajax
request.open('GET', '../example/fbv/items', true);
//요청전송
request.send('')
//응답이 오면 호출
request.addEventListener('load', (e) => {
alert(request.responseText)
})
})
- 실행결과 :
이후 ajax.html 의 페이지를 수정한다면 조금더 괜찮은 페이지를 만들 수 있다.
저 버튼을 클릭하게 되면,
이렇게 데이터를 가져올 수 있음을 확인할 수 있다.
12.4) 해당 문자열을 JavaScript 데이터로 변환!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AJAX</title>
</head>
<body>
<div id="display"></div>
<button id="allbtn">전체 데이터 가져오기</button>
</body>
<script>
document.getElementById("allbtn").addEventListener("click",
(e) => {
let request = new XMLHttpRequest();
//출력하는 함수에 객체 대입하면 toString 메서드를 호출합니다.
//python은 __str__ 메서드를 호출합니다.
//위 메서드를 재정의하면 그 내용이 출력되지만, 재정의를 하지 않으면
//기본적으로 설정된 값이 출력된다.
alert(request)
//요청 생성
//http://localhost:8000/example/fbv/items
//현재는 http://localhost:8000/ajax
request.open('GET', '../example/fbv/items', true);
//요청전송
request.send('')
//응답이 오면 호출
request.addEventListener('load', (e) => {
//문자열
//alert(request.responseText)
//문자열을 자바스크립트 데이터로 변환
// 객체들의 배열
let data = JSON.parse(request.responseText);
let txt = '';
for(let item of data){
txt += '<h5>' + item.title + '</h5>';
txt += '<p>' + item.price + '</p>';
txt += '<p>' + item.published_date + '</p>';
}
document.getElementById('display').innerHTML =
txt;
})
})
</script>
실행결과 :
- 함수 생성 시 여러 개의 데이터 리턴
def f() :
result = [ ]
result 값 대입
return result
- 1개 리턴하는 함수
def f() :
result = None
result 값을 대입
return result
12.5) ajax.html을 수정하여 데이터를 입력받아 해당하는 값을 가져오는 프로그램 구현
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AJAX</title>
</head>
<body>
<div id="display"></div>
<button id="allbtn">전체 데이터 가져오기</button>
itemid <input type="text" id="itemid" />
<button id="getbtn">데이터 1개 가져오기</button>
</body>
<script>
document.getElementById("getbtn").addEventListener('click',
(e) => {
// 아이디가 itemid인 입력의 값을 가져온다
let itemid = document.getElementById("itemid").value;
//alert(itemid);
let request = new XMLHttpRequest();
request.open('GET', '../example/fbv/book/' + itemid, true);
request.send('');
request.addEventListener('load', (e) => {
//없는 번호인 경우는 detail에 NotFound 값이 넘어옵니다.
//alert(request.responseText)
// Parsing 진행
let data = JSON.parse(request.responseText);
//alert('detail' in data)
let txt = "";
if('detail' in data){
// 데이터가 없을 때 처리
txt = "<h3>해당 되는 itemid가 없습니다.</h3>";
}else {
//데이터가 있을 때 처리
txt += "<h3>" + data.itemid + "</h3>"
txt += "<h3>" + data.title + "</h3>"
txt += "<h3>" + data.price + "</h3>"
}
document.getElementById('display').innerHTML = txt;
})
});
이제
실행시켜서 어떤 table에 id 값을 입력하고, 그 데이터가 있으면 출력, 없으면 해당 되는 id가 없다는 문장을 출력하는지 확인해보겠습니다.
- 해당되는 id가 존재하는 번호로 출력
- 해당되는 id가 없는 번호로 출력
## 입력받은 데이터 null 여부 확인 다른 방법
x = " ";
if(x.trim().length == 0);
오늘은 여기까지!
오늘 하루 모두 내일의 자신에게 혼나지 않을 삶을 보냈나요? 하루 하루만 보면 아무것도 아닌 듯 보이나
그 하루가 모이면 1달, 1년이 됩니다.
하루하루 소중히 우리 모두 더 나아가려 한 발자국 내밀어 봅시다
'LG 헬로비전 DX DATA SCHOOL > Python' 카테고리의 다른 글
Python 데이터 분석 Pandas 2 (0) | 2023.08.09 |
---|---|
데이터 분석 Python (with numpy & pandas) (0) | 2023.08.07 |
Django (0) | 2023.07.26 |
Python 예외처리 / File handling (0) | 2023.07.14 |
파이썬 Data Type 및 처리 (0) | 2023.07.11 |