[Django] 기상청 단기예보 API 활용하기(2)

Cherry·2022년 3월 30일
0
post-custom-banner


저번 포스팅에서는 파이썬을 가지고 기상청 단기예보 정보를 불러오는 것이었다. 그런데 지금 프로젝트는 django라는 프레임워크를 기반으로 만들어진거기 때문에 장고에서 데이터들을 불러온 후 데이터베이스에 저장하는 api를 만드는게 최종 목표였다. 그러기 위해서는 테이블에 저장하기 위해 우선은 모델을 만들었다.

☀️Model

class Building(models.Model):
    id = models.AutoField(primary_key=True)
    building_name = models.CharField(max_length=150, blank=True, null=True)
    address = models.CharField(max_length=80, null=True, blank=True)
    lon = models.FloatField(blank=True, null=True) #경도
    lat = models.FloatField(blank=True, null=True) #위도
    description = models.CharField(max_length=100, blank=True, null=True)
  
    def __str__(self):
        return str(self.building_name)


class WeatherDB(models.Model):
    building = models.ForeignKey('Building', on_delete=models.CASCADE, null=True, blank=True)
    timestamp = models.DateTimeField(auto_now=True, null=True, blank=True)
    temp = models.IntegerField(blank=True, null=True) #온도
    humidity = models.IntegerField(blank=True, null=True) #습도
    rainType = models.CharField(max_length=20, blank=True, null=True) #한시간 동안 강수량
    sky = models.IntegerField(blank=True, null=True) # 하늘 상태

    def __str__(self):
        return str(self.building) + " - " + str(self.timestamp)

건물의 주소에 해당하는 날씨 정보를 불러오는 거였기 때문에 우선 건물 모델을 하나 생성하고 그 후에 건물에 해당하는 날씨 데이터 모델을 하나 생성했다.
지금 보니까 건물모델이랑 날씨데이터모델을 일대일로 생성했어야 했을듯 하다.

🌤Serializer

class BuildingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Building
        fields = '__all__'


class WeatherDBSerializer(serializers.ModelSerializer):
    class Meta:
        model = WeatherDB
        fields = '__all__'

serializer는 굉장히 단순하게 만들어 주었다.

⛅️View

class WeatherSaveView(APIView):

    def get(self, request):
        buildings = Building.objects.all()
        for building in buildings:
            nx, ny = mapToGrid(building.lat, building.lon) # 이함수는 저번 포스트를 보면 알수 있다. 위도와 경도를 사용해서 기상청 예보에 맞는 x,y로 바꿔주는 함수 이다.
            data = check_weather(nx, ny)
            weather = WeatherDB.objects.get(building=building)
            weather.temp = data['tmp']
            weather.humidity = data['hum']
            weather.rainType = data['rain']
            weather.sky = data['sky']
            weather.save() #필수
        serializer = WeatherDBSerializer(weather)
        return JsonResponse(serializer.data, status=status.HTTP_201_CREATED)

check_weather라는 함수를 통해 날씨 관련 데이터들이 data에 딕셔너리 형식으로 저장되고 건물에 해당하는 날씨 데이터들을 data에서 알맞게 꺼내어 weatherdb테이블에 입력했다. 이 api를 실행시킨 후에 데이터베이스를 확인해보면 건물에 해당하는 날씨 데이터들이 잘 업데이트되고 저장된것을 볼 수 있다.

check_weather
이 함수는 저번 포스팅에도 나왔지만 기상청 데이터들을 위치에 따라 불러오는 함수이다. 다시 한번 전체 코드들을 보여주면

from urllib.parse import urlencode, quote_plus, unquote

import requests # HTTP 요청을 보내는 모듈
import datetime # 날짜시간 모듈
from datetime import date, datetime, timedelta # 현재 날짜 외의 날짜 구하기 위한 모듈


def check_weather(nx, ny):

    url = "https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtFcst"

    serviceKey = "서비스키"
    serviceKeyDecoded = unquote(serviceKey, 'UTF-8')

    now = datetime.now()
    today = datetime.today().strftime("%Y%m%d")
    y = date.today() - timedelta(days=1)
    yesterday = y.strftime("%Y%m%d")

    if now.minute<45: # base_time와 base_date 구하는 함수
        if now.hour==0:
            base_time = "2330"
            base_date = yesterday
        else:
            pre_hour = now.hour-1
            if pre_hour<10:
                base_time = "0" + str(pre_hour) + "30"
            else:
                base_time = str(pre_hour) + "30"
            base_date = today
    else:
        if now.hour < 10:
            base_time = "0" + str(now.hour) + "30"
        else:
            base_time = str(now.hour) + "30"
        base_date = today

    queryParams = '?' + urlencode({ quote_plus('serviceKey') : serviceKeyDecoded, quote_plus('base_date') : base_date,
                                    quote_plus('base_time') : base_time, quote_plus('nx') : nx, quote_plus('ny') : ny,
                                    quote_plus('dataType') : 'json', quote_plus('numOfRows') : '60'})

    # 값 요청 (웹 브라우저 서버에서 요청 - url주소와 )
    res = requests.get(url + queryParams, verify=False)
    items = res.json().get('response').get('body').get('items')
    #print(items)
    data = dict()
    data['date'] = base_date

    weather_data = dict()

    for item in items['item']:
        # 기온
        if item['category'] == 'T1H':
            weather_data['tmp'] = item['fcstValue']
        # 습도
        if item['category'] == 'REH':
            weather_data['hum'] = item['fcstValue']
        # 하늘상태: 맑음(1) 구름많은(3) 흐림(4)
        if item['category'] == 'SKY':
            weather_data['sky'] = item['fcstValue']
        # 1시간 동안 강수량
        if item['category'] == 'RN1':
            weather_data['rain'] = item['fcstValue']

    print("response: ", weather_data)
    #print(weather_data['tmp'])
    return weather_data

끝!!!!🥰

post-custom-banner

0개의 댓글