본문 바로가기
국회도서관 자료검색 서비스

django 공공데이터 포털 API 코드, 환경변수 설정, admin 생성하기 #9

by 유니네 라이브러리 2024. 8. 8.

django 코드 작성

django 코드 작성은 이전 프로젝트 구조에 맞춰서 개발한다.

 

☞ django 프로젝트 구조는 이전 글 참고

https://yuneenelife.tistory.com/entry/django-cycle-프로젝트-구조-및-language-timezone-변경하기-3

 

django cycle, 프로젝트 구조 및 language, timezone 변경하기 #3

django cycledjango는 아래와 같은 사이클로 작동되며, 소스 코드도 아래 사이클에 맞춰 개발한다.WSGI (Web Server Gateway Interface)파이썬 스크립트(웹 어플리케이션)가 웹 서버와 통신하기 위한 인터페이

yuneenelife.tistory.com

작성할 코드 흐름

  • urls.py
    • path는 /api/pubd/
    • 상세 URL들은 pubdapp 앱 내 urls.py 생성하여 관리한다.
  • views.py
    • nanet_search() 함수 생성한다.
    • nanet_post() 함수 생성한다.
  • settings.py
    • git에 공유되지 않아야 할 주요 키 값들 저장
  • api.py
    • api 호출되는 함수 모음 파일 신규 생성한다.
    • axios로 연계되는 로직은 모두 이 파일에 작성한다.
    • nanet_api() 함수 생성한다.
  • models.py
    • request와 response를 저장하기 위한 기초 작업
    • nanet 클래스 생성한다.

urls.py

  • urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('rest_framework.urls')),
    path('api/pubd/', include('pubdapp.urls')), #공공데이터 포탈 API URL 모음
]
  • pubdapp/urls.py
from django.urls import path
from .views import nanet_search

urlpatterns = [
    path('nanet_main/', nanet_search),
]

views.py

 

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from .api import nanet_api
from .models import Nanet

# Create your views here.
@api_view(['GET'])
@permission_classes([AllowAny])
def nanet_search(request):    
    param = []
    test = []
    param.append(request.GET.get('search'))
    param.append(request.GET.get('pageno'))
    param.append(request.GET.get('displaylines'))
    
    if param[0] is not None:
        create_nanet_log(param)
    else:
        test.append('자체 테스트중')
        test.append(1)
        test.append(10)
        create_nanet_log(test)

    res = nanet_api(param)    
    
    return Response(res)

def create_nanet_log(param):
    nanet_save = Nanet(search=param[0], pageno = param[1], displaylines=param[2])
    nanet_save.save()

환경변수 settings.py 에 추가

URL과 git으로 공유되지 않아야 할 API KEY 값 들은 별도 환경변수에 저장하여 활용한다.

  • INSTALLED_APPS에 pubdapp 추가
  • EXTERNAL_URLS에 공공데이터 포털 API 입력
  • EXTERNAL_KEYS에 공공데이터 포털 KEY 입력
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'corsheaders',
    'pubdapp',

]

EXTERNAL_URLS = {
    'NANET_API': 'http://apis.data.go.kr/9720000/searchservice/basic',
}
EXTERNAL_KEYS = {
    'NANET_KEY': '공공데이터 포털에서 받은 API KEY 기입',
}

api.py

  • api 주요 정보는 settings 모듈을 통해 환경변수에서 가져온다.
from django.conf import settings
from urllib.parse import urlencode, unquote, quote_plus
import requests, xmltodict

def nanet_api(param):    
    url = settings.EXTERNAL_URLS['NANET_API']
    serviceKey = settings.EXTERNAL_KEYS['NANET_KEY']
    serviceKeyDecoded = unquote(serviceKey, 'UTF-8')
    
    P = validation_api('nanet', param)
    if (P[0] == 'noapi'):
        return False    
    #print("param :", P)

    queryParams = '?' + urlencode({ quote_plus('ServiceKey') : serviceKeyDecoded
                                  , quote_plus('pageno') : P[1]
                                  , quote_plus('displaylines') : P[2]
                                  , quote_plus('search') : P[0] })
    res = requests.get(url + queryParams)
    xml = res.text  
    rsp = xmltodict.parse(xml)
    #print("rsp :", rsp)
    
    return rsp

def validation_api(apiNm, param):    
    rtn = []
    try:
        if (apiNm == 'nanet'):                
            if param[0] is None:
                param[0] = '자료명,삼국지'
                param[1] = 1
                param[2] = 10
            else:
                param[0] = str(param[0])
        else:
            return rtn.append("noapi")        
        return param
    except Exception as ex:
        print("ERROR validation_api()", ex)

request 모듈 설치

  • 가상환경에 들어가서 request 모듈 인스톨한다.
  • pip install requests
(pubd_api) pubdapi % ls
db.sqlite3	manage.py	pubdapi		pubdapp
(pubd_api) pubdapi % pip install requests
Collecting requests
  Using cached requests-2.32.3-py3-none-any.whl.metadata (4.6 kB)
Collecting charset-normalizer<4,>=2 (from requests)
  Using cached charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl.metadata (33 kB)
Collecting idna<4,>=2.5 (from requests)
  Using cached idna-3.7-py3-none-any.whl.metadata (9.9 kB)
Collecting urllib3<3,>=1.21.1 (from requests)
  Using cached urllib3-2.2.2-py3-none-any.whl.metadata (6.4 kB)
Collecting certifi>=2017.4.17 (from requests)
  Downloading certifi-2024.7.4-py3-none-any.whl.metadata (2.2 kB)
Using cached requests-2.32.3-py3-none-any.whl (64 kB)
Downloading certifi-2024.7.4-py3-none-any.whl (162 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 163.0/163.0 kB 2.4 MB/s eta 0:00:00
Using cached charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl (119 kB)
Using cached idna-3.7-py3-none-any.whl (66 kB)
Using cached urllib3-2.2.2-py3-none-any.whl (121 kB)
Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests
Successfully installed certifi-2024.7.4 charset-normalizer-3.3.2 idna-3.7 requests-2.32.3 urllib3-2.2.2
(pubd_api) pubdapi %

xmltodict 모듈 설치

  • XML 데이터를 파싱하고 Dict 형식으로 변환시키기 위해 필요하다.
  • 가상환경에 들어가서 xmltodict 모듈 인스톨한다.
  • pip3 install xmltodict
(pubd_api) pubdapi % pip3 install xmltodict
Collecting xmltodict
  Using cached xmltodict-0.13.0-py2.py3-none-any.whl.metadata (7.7 kB)
Using cached xmltodict-0.13.0-py2.py3-none-any.whl (10.0 kB)
Installing collected packages: xmltodict
Successfully installed xmltodict-0.13.0
(pubd_api) pubdapi %

models.py

  • 요청한 파라미터를 저장하기 위한 모델 작성
from django.db import models

# Create your models here.
class Nanet(models.Model):    
    pageno = models.DecimalField(max_digits=4, decimal_places=0)
    displaylines = models.DecimalField(max_digits=4, decimal_places=0)
    search = models.CharField(max_length=500)
    create_date = models.DateTimeField(auto_now_add=True)
  • 모델을 데이터베이스에 반영
    • makemigrations 실행
    • python3 manage.py makemigrations 
      • 모델을 변경한 것에 기반한 새로운 마이그레이션을 만들 때 사용
(pubd_api) pubdapi % python3 manage.py makemigrations
Migrations for 'pubdapp':
  pubdapp/migrations/0001_initial.py
    - Create model Nanet
(pubd_api) pubdapi %
  • migrate 실행
    • 마이그레이션을 반영하거나 반영하지 않기 위해 사용
    • python3 manage.py migrate
(pubd_api) pubdapi % python3 manage.py migrate    
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, pubdapp, sessions
Running migrations:
  Applying pubdapp.0001_initial... OK
(pubd_api) pubdapi %

데이터 확인을 위한 admin 관리자 페이지 생성

  • 관리자 설정하여 관리자 페이지에서 확인한다.
# 관리자 계정 생성한다.
python manage.py createsuperuser

# 개발 서버 실행한다.
python manage.py runserver

admin.py

from django.contrib import admin
# Register your models here.
from .models import Nanet

# myapp/admin.py
admin.site.register(Nanet)

어드민 페이지

  • http://localhost:8000/admin/pubdapp/nanet/

django admin 관리자 페이지

국회도서관 자료검색 API 조회결과

  • http://localhost:8000/api/pubd/nanet_main/

공공데이터 자료검색 결과

마무리

이로써 django 에서 국회도서관 자료검색 호출하고 응답까지 완성되었다.

다음은 해당 API 요청/응답 문서를 관리하는 swagger를 적용시켜 본다.

 

☞ python, django 설치는 이전 글 참고

https://yuneenelife.tistory.com/entry/API-Server-django-python-Framework-설치-1

 

API Server django python Framework 설치 #1

python framework 인 django를 이용해서 API Server를 구축한다.API는 공공데이터 포털에서 제공하는 국회 도서관 자료검색 서비스를 이용한다. 먼저 작업을 시작하기에 앞서 작업을 진행할 폴더를 생성

yuneenelife.tistory.com