django ORM

0

장고 프로젝트

목록 보기
5/15
post-thumbnail

DB오류(feat.browser)

오늘은 서로 다른 Col이 가지고 있는 숫자형 row값들을 모두 더하여 변수로 만들고, 그 변수를 return하는 코드를 짜보려고 했다.

DB Browser for SQLite를 설치해서 좀 편하게 구경도 해보고 수정도 해보고 그렇게 하려다가 아래와 같은 오류를 겪었다.

django.db.utils.OperationalError: no such column: 'field이름'

서버를 열고 Insomnia로 Get Request를 보냈는데 뜬금 없이 저런 오류가 나왔다. 이게 무슨 일인가 싶었다.

사실 내가 Browser에서 테이블 하나를 냅다 밀어서 일어난 일이다.
좀 헤맸다. 이거 해결하는 데에 1시간은 걸린 것 같다.

🌐 해결법 출처: 이 링크의 댓글에 있음

해결 방법

  • 해당 앱의 migration 디렉터리에 있는 파일을 모두 삭제
    __init__.py는 반드시 남겨둔다

  • window 탐색기 또는 macOS 파인더로 프로젝트의 해당 앱 migrations 디렉터리를 확인해보면 __pycache__라는 하위 디렉터리가 있다
    여기서도 init 파일을 제외한 나머지 파일을 삭제해준다

  • 마지막으로
    프로젝트 루트 디렉터리의 db.sqlite3 파일을 삭제한다

  • PyCharm 터미널 또는 기본 터미널을 열고 프로젝트 디렉터리에 접근
    $ python manage.py showmigrations으로 migrate 기록 확인

  • 목록 가장 앞 부분의 체크박스 [ ]가 모두 다 비워져있으면 데이터베이스 초기화 성공

  • 이후 makemigration 및 migrate 수행

따라서 완료하고 나니 서버에 Request를 보내도 에러가 나지 않았다.
다만 POST Request를 와장창 보내서 DB에 데이터를 다시 쌓아야 했다.

You are trying to add a non-nullable field

이런 오류도 한 번 겪은 적이 있었는데, 그땐 그냥 migration 디렉터리를 한번 밀어주는 것으로 간단하게 해결했다.
하지만 이번 건 좀 더 복잡한 문제였다.
DB를 함부로 건드려서 그런 건 알겠는데 migration 디렉터리도 함부로 삭제해서 엉킨 것(?) 같다.
내부적으로 이유를 확실히 알 수 있으면 좋을 텐데 그건 잘 모르겠다.
아무튼 당연하게도 조심해야겠단 생각이 든다.


Aggregate

row값들을 합치는 건 aggregate가 답이었다.
django ORM을 이용하여 특정 테이블의 특정 칼럼의 합 구하기.
진짜 내가 딱 원하던 기능이었다.

🌐 이거 보고 따라했음

# 이거 import 해줘야함!
from django.db.models import Sum

@csrf_exempt
def total_biceps(request):
    if request.method == 'GET':

        data = JSONParser().parse(request)
        print(data)
        # Request를 파싱해서 pid만 뽑아내서 변수로 저장
        # account는 요청자의 pid
        pid_get = data['pid']
        print(pid_get)
        # Reuqset를 파싱해서 요청받은 데이터 내용의 이름을 저장
        type_get = data['type']
        print(type_get)
        # 요청받은 데이터가 COUNT의 합계일 경우
        if type_get == 'count':
            sum_count = BicepsCurl.objects.filter(pid=pid_get).aggregate(Sum('count'))
            print(sum_count)
            # serializer = BicepsTotalSerializer(sum_count, many=True)
            # print(serializer)
            return JsonResponse(sum_count['count__sum'], safe=False)
        # 요청받은 데이터가 TIMES의 합계일 경우
        elif type_get == 'times':
            sum_times = BicepsCurl.objects.filter(pid=pid_get).aggregate(Sum('times'))
            print(sum_times)
            # serializer = BicepsTotalSerializer(sum_times, many=True)
            # print(sum_times)
            return JsonResponse(sum_times['times__sum'], safe=False)

        # # ORM으로 요청자의 BicepsCurl 정보를 찾아온다
        # sum_count = BicepsCurl.objects.filter(pid=pid_get).aggregate(Sum('count'))
        # sum_times = BicepsCurl.objects.filter(pid=pid_get).aggregate(Sum('times'))
        #
        # dict_sum = {}
        # dict_sum['sum_count'] = sum_count
        # dict_sum['sum_times'] = sum_times
        #
        # # serializer에 넣고 돌린다 (??)
        # serializer = TotalNumberSerializer(dict_sum, many=True)
        # return JsonResponse(serializer.data, safe=False)

    else:
        return JsonResponse("Http Method Error", safe=False, status=400)

앞쪽에서 썼던 코드와 거의 동일하다.
다만 이번엔 요청자가 원하는 값만 보내기 위해 if문으로 분기를 만들었다.

um_count = BicepsCurl.objects.filter(pid=pid_get).aggregate(Sum('count'))

결국 이 부분만 다시 잘 봐두면 될 것 같다.
BicepsCurl이라는 테이블의. Col값들.
조건에 부합하는 것만 골라낸다
(조건: DB의 Col이름==요청자가 원하는 데이터와 연관된 Col이름).합친다(Sum(Col이름))

개떡같이 적어놨어도 미래의 나는 찰떡 같이 알아먹을 것이다. 확신한다.


직렬화를 해야할 상황과 하지 않아도 될 상황을 구별하는 것이 필요할 것 같다.

serializer를 주석처리했다.
처음 django REST Framework의 튜토리얼 과정을 따라하면서 짜놓았던 코드를 그대로 쓰다보니 의미를 잊는 현상이 발생했다.
정말이지 당황스럽다.

오늘은 정신없이 넘어가버렸지만
REST, Serialize, HTTP 얘들은 계속 봐야겠다.
아직까지 뭔가가 애매한 기분이다.


멘토 선생님의 말씀을 듣고 웬만한 건 print()함수를 통해 찍어보며 넘어가고 있다. 이번 코드를 짜면서도 계속해서 자잘한 예외를 겪었는데 확실히 print()함수가 큰 도움이 되고 있다.

이제 login 과정에서 ID 검증하는 코드를 고민해보면서 VueJs와 django를 잇는 방법을 찾아봐야겠다.

완성이 먼저다. 완성부터 하고 반성한다.

0개의 댓글