Westagram_2

Jina·2020년 4월 11일
0

Django

목록 보기
5/11

objects.get()과 objects.filter()

exists()

회원가입 로직을 짤 때 이미 존재하는 이메일인지 확인하기 위해서 exists()를 사용했다. 그런데 이 로직이 filter에서는 가능하고 get에서는 되지않아서 차이를 찾아보았다.

get

클래스명.objects.get(찾고싶은 데이터)는 찾고싶은 데이터 한 개객체로 가져온다.

만약 data=class_name.objects.get(id=3)면 data는 객체!
객체에는 exists 함수가 존재하지 않는다.
따라서 get으로 가져온 데이터에는 exists를 적용할 수 없다!

filter

클래스명.objects.filter(찾고싶은 데이터)는 찾고싶은 데이터를 있는만큼 쿼리셋으로 가져온다.

만약 data2=class_name.objects.get(id=3)면 data2는 쿼리셋으로 가져온다.
쿼리셋의 함수에는 exists()가 존재한다! 따라서 filter로 가져온 데이터에는 exists를 적용할 수 있다.

여기에서 쿼리셋의 다른 함수들을 확인 할 수 있다.

get은 한 개의 데이터를 가져온다

get()은 한 개의 데이터를 가지고온다. 만약 get으로 가져오는 데이터가 두 개 이상이라면 MultipleObjectsReturned라는 오류를 반환한다.

데이터가 한 개도 없는 경우에도 오류를 반환한다! 이 때는 DoesNotExist라는 오류를 반환한다.

따라서 get으로 데이터의 존재여부를 확인하고 싶다면 try, except 구문을 사용하여 DoesNotExist오류가 발생했을 경우의 예외처리를 해주어야한다.

try, except, DoesNotExist 구문 사용하기

DoesNotExist 오류를 처리하기 위해서는 django.core.exceptions.ObjectDoesNotExist 함수를 가져와서 사용해야한다.

위의 함수를 이용하기 위해서 아래와 같이 import하여 사용한다.
from django.core.exceptions import ObjectDoesNotExist

account/views.py 에서 적용하면 아래와 같다.

import json
from django.views import View
from django.http import JsonResponse, HttpResponse
from .models import Account
from django.core.exceptions import ObjectDoesNotExist
   
class AccountView(View):
     def post(self,request):
         data = json.loads(request.body)
         try:
            if Account.objects.get(email=data['email']):
                 return JsonResponse({"message":"no"},status=401)
         except ObjectDoesNotExist:
             Account.objects.create(
                     name = data['name'],
                     email = data['email'],
                     password = data['password']
              )
             return HttpResponse(status=200 )

--> 이러한 코드는 사용을 추천하지는 않는다.

try가 정상코드로 가정 (정상 처리과정)
except에서 오류를 처리하는 것인데 여기서는 except에서 정상 처리 과정을 하고 있기 때문

이 코드는 회원가입을 하고싶은 코드이다. 즉, 정상 처리과정이 회원가입인 것.
여기서는 오류가 발생(DoesNotExist)해야지 정상처리(회원가입 진행)가 되는 경우라서 좋은 코드는 아니다.

중복 가입 방지

중복 가입을 위해서 위와 같은 복잡한 코드를 이용했다. 간단하게 이용하기 위해서는 model을 생성할 때 unique=True 지정해주면 된다.

account/models.py 에서 아래와 같이 지정해주면 된다.

 from django.db import models

 class Account(models.Model):
     name = models.CharField(max_length=200, unique=True)
     email = models.CharField(max_length=200, unique=True)
     password = models.CharField(max_length=400)
     created_date = models.DateTimeField(auto_now_add=True)
     updated_date = models.DateTimeField(auto_now=True)

     class Meta:
         db_table = "accounts"

이후 migration해주기!

account/views.py 에서 코드를 짜면 아래와 같다.

import json

from django.views import View
from django.http import JsonResponse, HttpResponse

from .models import Account
from django.db import IntegrityError

 class AccountView(View):
      def post(self,request):
          data = json.loads(request.body)
          try:
              Account.objects.create(
                          name = data['name'],
                          email = data['email'],
                          password = data['password']
                  )
              return HttpResponse(status=200 )
          except IntegrityError:
              return HttpResponse(status=400)

이 때 from django.db import IntegrityError 추가해줘야한다!

이메일 또는 이름으로 로그인하기

이메일 / 이름이 고유한 경우에 해당되는 내용이다.
만약 이메일, 이름이 여러개가 있다면 그에 대응하는 비밀번호가 무엇인지 알 수 없기 때문이다.

 import json
 
 from django.views import View
 from django.http import JsonResponse, HttpResponse
 from django.db.models import Q
 
 from .models import Account
 
 # import 할 때 분류별로 나열해두는 것이 좋음 
 
 class LoginView(View):
     def post(self,request):
         data = json.loads(request.body)
         password = data.get('password', None)
         email = data.get('email', None)
         name = data.get('name', None)
         if Account.objects.filter(Q(email=email)|Q(name=name)).exists():
             if Account.objects.get(Q(email=email)|Q(name=name)).password == password:
                 return HttpResponse(status=200)
             return JsonResponse({"message":"INVALID_PASSWORD"},status=401)
         return JsonResponse({"message":"INVALID_USER"}, status=401)

get(key,None)

위의 풀이에서 데이터를 가져오기위해서 아래와 같이 입력했다.

         password = data.get('password', None)
         email = data.get('email', None)
         name = data.get('name', None)

이전에는 data['password']와 같은 형식으로 데이터를 가지고왔다.
이 방식은 password 등 가지고 와야 할 인자가 없으면 keyerror가 발생했다.

위의 새로운 풀이는 keyerror를 방지하기 위해 사용하는 방식으로 password 등을 가지고 오고 만약 값이 없으면 None으로 처리한다는 의미이다.

내가 위의 풀이에서 의문을 가진 부분은 아래의 내용이다.
1. objects.get()에서는 찾아야 할 테이터가 없으면 Error가 발생하는데 여기서는 None으로 처리할 수 있는가?
2. 이전의 data를 가지고오는 방법과의 차이

위의 내용을 설명하면 아래와 같다.

1. objects.get( ) vs data.get( )

글 상단의 objects.get()과 바로 위의 예시에서 사용한 data.get()의 get()은 다른 함수이다.

둘 다 get()으로 쓰여있어서 같은 함수로 착각할 수 있지만 이름이 같을 뿐 다른 함수이다.

objects.get()

위의 get()은 데이터 한 개를 객체로 가져온다.
데이터가 없으면 DoesNotExist 오류
객체가 가지고 있는 get 메서드

data.get( )

위의 get()은 dictionary에 속한 메서드 get

아래와 같이 사용한다.

dict.get(key, value)
  • key
    딕셔너리의 key값을 의미한다.
    key값이 해당 dictionary에 존재하면 value를 return한다.

  • value (필수 x)
    만약 key가 dictionary에 없으면 return할 값
    default는 None이다.
    (None은 dafualt값이라 굳이 입력해주지않아도 된다.)

예시)

wecode = {'name': 'jina', 'gender': 'F'}

# key가 있을 때
print(wecode.get('name'))
# jina

# key가 없을 때
print(wecode.get('age'))
# None

# key가 없고, value가 지정되었을 때
Print(wecode.get('기수','7기')
# 7기

구분 방법

두 함수를 구분하기 위해서는 get을 적용하는 대상이 무엇인지를 봐야한다.

class명.objects.get()을 보면 이 경우 class명.objects는 객체이다.

즉, 위의 경우는 객체의 get메서드이다.

data.get()을 확인하기 위해 data를 보면 data는 아래와 같다.
data = json.loads(request.body)
여기서 loads는 json 형식의 문자열을 파이썬 객체(dictionary)로 변경해주는 함수이다.

data는 딕셔너리이고 딕셔너리.get()이므로 get은 딕셔너리의 메서드임을 알 수 있다.

data[ ] vs data.get()

이전에 데이터를 가지고 온 방식은 아래와 같다.

data['password']

이 경우 data가 딕셔너리 이므로, data 딕셔너리의 password 키의 value값을 가지고 오라는 의미가 된다.
따라서 key값이 인자로 들어오지 않는 경우 에러가 발생하는 것이다. (keyerror)

data.get()의 방식은 key값이 없을 때 value를 지정해줄 수 있으므로(default=none) key값으로 들어올 인자가 존재하지 않아도 에러가 발생하지 않는 것이다.

Q 객체

Q 객체는 filter, exclude, get 과 같은 키워드 인수를 사용하는 조회 함수와 함께 사용할 수 있다.

or문 사용하기

(Q(email=email) | Q(name=name))

and문 사용하기

(Q(email=email) & Q(name=name))

sqlite3 db.sqlite3

장고에서 db 실행하는 명령어

.table

실행한 db내의 테이블 보는 명령어

GET

GET을 이용하여 데이터를 가지고 오면 아래와 같이 사용할 수 있음

   def get(self, request):
        email = request.GET.get('email', None)
        target = {'comment_list':list(Comments.objects.filter(name = email).values('reply'))}
        return JsonResponse(target, status=200)       

쿼리스트링으로 들어온 데이터 받아옴!

ORM

장고는 ORM 기능을 가지고 있다.

ORM이란?

Object Relational Mapping(ORM)은 객체-관계 매핑 기능이다.
객체지향 프로그램(ex : python)은 class를 사용하고, 관계형 db는 테이블을 사용한다. 서로 다른 모델을 사용하기 때문에 두 데이터를 연결해줄 필요가 있다.
ORM은 객체 간의 관계를 바탕으로 SQL을 생성하여 두 모델의 데이터를 자동으로 연결해준다.

ref) https://gmlwjd9405.github.io/2019/02/01/orm.html

1개의 댓글

comment-user-thumbnail
2020년 5월 12일

( ) ( )
(ㅇㅇ)

답글 달기