[8월 첫째주 TIL]

Choi Rim·2021년 8월 8일
0

Django

목록 보기
17/21
post-thumbnail

on_delete=models.SET_NULL 속성

user = models.ForeignKey('users.user', on_delete=models.SET_NULL, null=True)
  • ForeignKey가 가르키고 있는 값이 삭제될 때 Field값을 null로 바꿈.
  • null=True 속성일 때 가능
  • User 속성이 삭제되어도 좋아요는 사라지지 않게 처리

unique = True

email     = models.CharField(max_length=100, unique=True)
  • 해당 필드의 값이 겹치지 않게 하는 속성
  • user의 email을 고유한 값으로 두기 위해 사용

별점 구현 시 데이터베이스에 들어간 데이터 create, update, delete 세 가지 로직

get_or_create method

>>> star, flag = StarRating.objects.get_or_create(cafe_id=1, user_id=1)
>>> star
<StarRating: StarRating object (6)>
>>> flag
False
  • get_or_create method는 데이터베이스에 요청한 데이터가 존재하면 가져오고(get) 존재하지 않으면 생성한다.(create)
star, flag = StarRating.objects.get_or_create(cafe_id=cafe_id, user_id=user.id)

if not flag:
	if star.score == data['score']:
    	star.delete()
        return JsonResponse({'MESSAGE' : 'SCORE_DELETED'}, status=200)

	else:
    	star.score = data['score']
        star.save()
        return JsonResponse({'MESSAGE' : 'SCORE_UPDATED'}, status=200)
else:
	StarRating.objects.filter(cafe_id=cafe_id, user_id=user.id).update(score=data['score'])
        return JsonResponse({'MESSAGE' : 'SCORE_CREATED'}, status=200)
  • not flag라면 flag = False라는 뜻이다.
  • flag = False면 데이터베이스에 데이터를 create하지 않았다는 뜻이므로 cafe_id=cafe_id, user_id=user_id에 모두 해당하는 객체가 데이터 베이스에 존재한다는 뜻이다.
    • 여기서 사용자의 별점(score)도 같이 일치한다면 데이터를 삭제한다.
    • 별점이 일치하지 않는다면 별점을 수정한다.(update)
      • 위에서는 update대신 star.score = data['score']을 사용했다.
      • save()를 적지 않는다면 저장이 되지 않으니 주의
  • flag = True일 경우 객체를 생성한다.

대댓글 foreignkey self

comment_on_review = models.ForeignKey('self', on_delete=models.CASCADE, null=True)
  • 대댓글 기능을 구현할 때는 ForeignKey를 'self'로 주어 자기 자신을 가르키도록 한다.

annotation, aggregation

annotation

>>> star_ratings = StarRating.objects.values('cafe_id', 'score')
>>> star_ratings
<QuerySet [{'cafe_id': 1, 'score': Decimal('4.0')}, {'cafe_id': 1, 'score': Decimal('2.0')}, {'cafe_id': 1, 'score': Decimal('2.0')}, {'cafe_id': 2, 'score': Decimal('3.5')}, {'cafe_id': 3, 'score': Decimal('5.0')}, {'cafe_id': 3, 'score': Decimal('4.0')}, {'cafe_id': 10, 'score': Decimal('4.0')}, {'cafe_id': 8, 'score': Decimal('2.0')}, {'cafe_id': 1, 'score': Decimal('1.0')}, {'cafe_id': 2, 'score': Decimal('3.0')}, {'cafe_id': 2, 'score': Decimal('2.0')}, {'cafe_id': 2, 'score': Decimal('1.0')}]>
  • 모델이름.objects.values를 출력하면 모델에 해당하는 모든 객체의 QuerySet의 values가 출력된다.
>>> from django.db.models import Avg
>>> cafe_avg_rating = star_ratings.values('cafe_id').annotate(avg_score=Avg('score'))
>>> cafe_avg_rating
<QuerySet [{'cafe_id': 1, 'avg_score': Decimal('2.25000')}, {'cafe_id': 2, 'avg_score': Decimal('2.37500')}, {'cafe_id': 3, 'avg_score': Decimal('4.50000')}, {'cafe_id': 8, 'avg_score': Decimal('2.00000')}, {'cafe_id': 10, 'avg_score': Decimal('4.00000')}]>
  • django.db.models 에서 Avg 를 import 해온다.
  • annotate를 이용해서 일치하는 cafe_id에 해당하는 score을 구해준다.
  • 'annotate는 조건에 해당하는 가상 테이블을 생성한다'라고 보면된다.
>>> cafe_ranking = cafe_avg_rating.order_by('-avg_score')
>>> cafe_ranking
<QuerySet [{'cafe_id': 3, 'avg_score': Decimal('4.50000')}, {'cafe_id': 10, 'avg_score': Decimal('4.00000')}, {'cafe_id': 2, 'avg_score': Decimal('2.37500')}, {'cafe_id': 1, 'avg_score': Decimal('2.25000')}, {'cafe_id': 8, 'avg_score': Decimal('2.00000')}]>
  • order_by를 사용하면 조건에 맞게 정렬해준다.
  • -를 붙이면 반대로 정렬한다.

aggregation

>>> average_score = StarRating.objects.filter(cafe_id=1).aggregate(average=Avg('score'))
>>> average_score
{'average': Decimal('2.25000')}
>>> average_score['average']
Decimal('2.25000')
  • aggregate는 객체의 조건에 맞는 필드를 뽑아와 결과를 보여준다.
  • 위에서는 cafe_id=1에 해당하는 객체의 score값 평균을 뽑아서 보여주었다.

__isnull=True

  • __isnull = True 속성은 null = True인 속성값을 뽑아서 보여준다.
reviews  = Review.objects.filter(cafe_id = cafe_id, comment_on_review_id__isnull = True)
  • 위는 cafe_id에 해당하는 값, commen_on_review_id가 null인 값에 모두 일치하는 객체를 filtering 해준다.

'{:.0f}원'.format(menu.price)

  • format함수를 이용하면 원하는 소수점의 숫자를 출력할 수 있다.
>>> '{:.1f}원'.format(45000.000)
'45000.0원'
>>> '{:.0f}원'.format(45000.456)
'45000원'

<참고>

profile
https://rimi0108.github.io/

0개의 댓글