- 세션과 쿠키를 이용한 Django 인증 시스템 2023.12.06
- Django의 사용자 인증 및 관리를 위한 유틸리티 함수 2023.11.26
- DRF) serializer에서 validation 메소드 만들기 2023.10.01
- Django 소유자 여부 확인(DRF) 2023.08.28
- Serializer에서 method 사용하기 2023.08.27
- Django에서의 Transactions 2023.08.26
- 세션과 쿠키의 작동 방식:
- Django에서 로그인 시, 사용자의 세션 정보는 서버의 데이터베이스에 저장됩니다. 이 세션에는 랜덤으로 생성된 세션 ID가 포함되어 있습니다.
- 서버는 이 세션 ID를 쿠키에 담아 브라우저로 보냅니다. 브라우저는 이 쿠키를 저장하고, 이후 동일한 도메인으로 요청을 보낼 때마다 이 쿠키를 함께 전송합니다.
- 도메인 기반 쿠키:
- 쿠키는 도메인을 기준으로 작동합니다. 특정 도메인에서 생성된 쿠키는 해당 도메인에 대한 요청 시에만 브라우저에 의해 전송됩니다. 이는 보안과 관련된 중요한 특징입니다.
- CORS 설정:
- 프론트엔드(예: React)와 백엔드(Django)가 다른 도메인 또는 포트에서 실행될 때, 백엔드에 대한 AJAX 요청을 위해
CORS_ALLOWED_ORIGINS설정이 필요합니다. 이 설정은 백엔드가 어떤 오리진에서 오는 요청을 허용할지 지정합니다.
- 프론트엔드(예: React)와 백엔드(Django)가 다른 도메인 또는 포트에서 실행될 때, 백엔드에 대한 AJAX 요청을 위해
- Axios와 쿠키 전송:
- JavaScript 또는 Axios를 사용하여 요청을 보낼 때,
withCredentials: true설정을 추가해야 합니다. 이 설정은 AJAX 요청에 쿠키를 포함시키기 위해 필요합니다.
- JavaScript 또는 Axios를 사용하여 요청을 보낼 때,
- 백엔드 설정:
- Django 백엔드에서
CORS_ALLOW_CREDENTIALS = True를 설정해야만, AJAX 요청에 포함된 쿠키를 받아들일 준비가 됩니다.
- Django 백엔드에서
Django와 React에서 세션과 쿠키를 사용한 인증을 구현하기 위한 기본적인 설정 예시를 제공하겠습니다.
Django 설정
django-cors-headers 설치 이후
settings.py에서 CORS 설정
# settings.p
INSTALLED_APPS = [
# ... 기타 설치된 앱들 ...
'corsheaders', # corsheaders 앱 추가
# ... 기타 설치된 앱들 ...
]
MIDDLEWARE = [
# ... 기타 미들웨어 ...
'corsheaders.middleware.CorsMiddleware', # CORS 미들웨어 추가, 꼭 아래의 미들웨어 보다는 먼저 작성
'django.middleware.common.CommonMiddleware',
# ... 기타 미들웨어 ...
]
# 모든 오리진을 허용하거나 특정 오리진만 허용
CORS_ALLOW_ALL_ORIGINS = True
# 또는
# CORS_ALLOWED_ORIGINS = [
# "http://localhost:3000", # React 앱의 URL
# ]
# AJAX 요청에 쿠키를 포함하기 위해
CORS_ALLOW_CREDENTIALS = True
React 설정 (Axios 사용 예시)
Axios 인스턴스 생성
// Axios 설정
import axios from 'axios';
const instance = axios.create({
baseURL: "http://127.0.0.1:8000/api/v1", // Django 서버 주소
withCredentials: true, // 쿠키를 포함시키기 위해
});
export default instance;
CSRF
Django에서 CSRF(Cross-Site Request Forgery) 토큰은 중요한 보안 기능 중 하나입니다. CSRF 토큰은 사용자의 세션을 보호하기 위해 사용되며, 사이트 간 요청 위조 공격을 방지하는 데 도움이 됩니다. Django의 CSRF 보호 기능을 사용하려면 다음과 같은 설정이 필요합니다.
Django CSRF 설정
settings.py에서 CSRF 설정
# settings.py
CSRF_TRUSTED_ORIGINS = ["http://127.0.0.1:3000"] # front 도메인 주소
템플릿에서 CSRF 토큰 사용
<form method="post">
{% csrf_token %}
<!-- 폼 필드 -->
</form>
AJAX 요청에 CSRF 토큰 포함
Django에서는 AJAX 요청에도 CSRF 토큰을 포함해야 합니다. 이를 위해 React 애플리케이션에서 요청을 보낼 때, CSRF 토큰을 요청 헤더에 포함해야 합니다.
React 설정 (Axios 사용 예시)
Axios 인스턴스에 CSRF 토큰 추가
// Axios 설정
import axios from 'axios';
const getCsrfToken = () => {
return document.cookie.split('; ').find(row => row.startsWith('csrftoken=')).split('=')[1];
};
const instance = axios.create({
baseURL: "http://127.0.0.1:8000/api/v1", // Django 서버 주소
withCredentials: true, // 쿠키를 포함시키기 위해
headers: {
'X-CSRFToken': getCsrfToken(), // CSRF 토큰 추가
}
});
export default instance;
위의 코드는 React 앱에서 Django 서버로 보내는 모든 요청에 CSRF 토큰을 포함시키는 방법을 보여줍니다. getCsrfToken 함수는 브라우저의 쿠키에서 CSRF 토큰을 추출하고, Axios 인스턴스는 이 토큰을 요청 헤더에 추가하여 서버에 전송합니다. 이 방법으로 Django 서버의 CSRF 보호 기능을 충족시킬 수 있습니다.
'Python > Django' 카테고리의 다른 글
| Django의 사용자 인증 및 관리를 위한 유틸리티 함수 (1) | 2023.11.26 |
|---|---|
| DRF) serializer에서 validation 메소드 만들기 (0) | 2023.10.01 |
| Django 소유자 여부 확인(DRF) (0) | 2023.08.28 |
| Serializer에서 method 사용하기 (0) | 2023.08.27 |
| Django에서의 Transactions (0) | 2023.08.26 |
Django는 사용자 인증 및 관리를 위해 여러 유틸리티 함수를 제공합니다. check_password, set_password, authenticate, login, logout 함수들을 예시로 들 수 있습니다.
1. check_password()
- 용도: 사용자의 비밀번호가 입력된 비밀번호와 일치하는지 확인합니다.
- 예시:
from django.contrib.auth.models import User user = User.objects.get(username='myusername') if user.check_password('mypassword'): print("비밀번호가 일치합니다.") else: print("비밀번호가 일치하지 않습니다.")
2. set_password()
- 용도: 사용자의 비밀번호를 새로 설정합니다.
- 예시:
user = User.objects.get(username='myusername') user.set_password('newpassword') user.save()
3. authenticate()
- 용도: 사용자 이름과 비밀번호가 유효한지 확인하고, 해당하는
User객체를 반환합니다. - 예시:
from django.contrib.auth import authenticate user = authenticate(request, username='myusername', password='mypassword') if user is not None: print("인증에 성공했습니다.") else: print("인증에 실패했습니다.")
4. login()
- 용도: 주어진
HttpRequest객체와User객체를 사용하여 세션을 시작합니다. - 예시:
from django.contrib.auth import login def my_view(request): # 사용자 인증이 이미 이루어진 상황 가정 user = authenticate(request, username='myusername', password='mypassword') if user is not None: login(request, user) # 로그인 후 처리
5. logout()
- 용도: 현재 세션을 종료합니다.
- 예시:
from django.contrib.auth import logout def my_view(request): logout(request) # 로그아웃 후 처리
'Python > Django' 카테고리의 다른 글
| 세션과 쿠키를 이용한 Django 인증 시스템 (0) | 2023.12.06 |
|---|---|
| DRF) serializer에서 validation 메소드 만들기 (0) | 2023.10.01 |
| Django 소유자 여부 확인(DRF) (0) | 2023.08.28 |
| Serializer에서 method 사용하기 (0) | 2023.08.27 |
| Django에서의 Transactions (0) | 2023.08.26 |
Django Rest Framework에서 serializer에서 각 필드에 대한 validation 로직을 추가할 수 있습니다. 검증을 위한 메서드 명은 validate_필드이름 라고 작성하고 검증할 로직을 구현하면 됩니다.
예
간단한 방 정보를 다루는 예시를 통해서 사용법을 설명하겠습니다.
모델
class Room(model.Model):
name = models.CharField(max_length=100)
price = models.PositiveIntegerField()
description = models.TextField()
시리얼라이저
class RoomSerializer(serializers.ModelSerializer):
class Meta:
model = Room
fields = ["name", "price", "description"]
def validate_name(self, value):
if len(value) < 3:
raise serializers.ValidationError("방 이름은 최소 3글자 이상이어야 합니다.")
return value
def validate_price(self, value):
if value < 0:
raise serializers.ValidationError("가격은 음수일 수 없습니다.")
return value
이 예시에서는 Room 모델을 정의하고, 이를 시리얼라이저로 변환하는 RoomSerializer를 만들었습니다. RoomSerializer는 Room 모델과 연결되어 있습니다.
RoomSerializer 내부에서 validate_name 메소드와 validate_price 메소드를 정의했습니다.
validate_name메소드는name필드의 값을 검증합니다. 만약 이름이 3글자 미만이면serializers.ValidationError을 발생시켜 에러를 일으킵니다.validate_price메소드는price필드의 값을 검증합니다. 만약 가격이 음수라면 마찬가지로 에러를 발생시킵니다.
이런 식으로 각 필드에 대한 검증 로직을 추가할 수 있습니다. 이제 이 시리얼라이저를 사용하면, 입력된 데이터가 검증되고 필요한 처리가 이루어집니다.
serializer = RoomSerializer(data=data)
if serializer.is_valid():
# 유효한 경우, 데이터를 저장하거나 다른 처리를 할 수 있습니다.
room = serializer.save()
else:
# 유효하지 않은 경우, 에러 메시지를 확인할 수 있습니다.
errors = serializer.errors
이렇게 하면 시리얼라이저를 통해 데이터를 검증하고 처리할 수 있습니다.
'Python > Django' 카테고리의 다른 글
| 세션과 쿠키를 이용한 Django 인증 시스템 (0) | 2023.12.06 |
|---|---|
| Django의 사용자 인증 및 관리를 위한 유틸리티 함수 (1) | 2023.11.26 |
| Django 소유자 여부 확인(DRF) (0) | 2023.08.28 |
| Serializer에서 method 사용하기 (0) | 2023.08.27 |
| Django에서의 Transactions (0) | 2023.08.26 |
Django 소유자 여부 확인(DRF)
Room 모델이 있고, 각 방은 owner가 있습니다.
방 정보를 조회하는 API를 만들려고 하는데, 로그인한 사용자가 각 방의 owner인지 여부를 확인하려고 합니다.
models.py
from django.db import models
from django.contrib.auth.models import User
class Room(models.Model):
name = models.CharField(max_length=100)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
serializers.py
from rest_framewok import serializers
from .models import Room
class RoomSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
def get_is_owner(self, room):
request = self.context["request"]
return room.owner == request.user
class Meta:
model = Room
fields = ["id", "name", "is_owner"]
views.py
from rest_framework import generics
from .models import Room
from .serializers import RoomSerializer
class RoomList(generics.ListAPIView):
queryset = Room.objects.all()
serializer_class = RoomSerializer
위 코드에서 Room 모델과 그에 맞는 시리얼라이저, APIView를 정의했습니다.
이때 is_owwner필드는 RoomSerializer클래스에 추가된 SerializerMethodField로, 방의 소유자 여부를 나타냅니다.get_is_owner 메서드에서는 self.context를 통해 현재 요청의 정보에 접근하고, 이를 활용하여 방의 소유자와 현재 사용자를 비교하여 is_owner 값을 결정하고 있습니다.
이렇게 context를 활용하여 요청 정보를 활용하는 것은 API의 동작을 더욱 유연하게 커스터마이징하고 필요한 정보를 포함시킬 수 있습니다.
'Python > Django' 카테고리의 다른 글
| Django의 사용자 인증 및 관리를 위한 유틸리티 함수 (1) | 2023.11.26 |
|---|---|
| DRF) serializer에서 validation 메소드 만들기 (0) | 2023.10.01 |
| Serializer에서 method 사용하기 (0) | 2023.08.27 |
| Django에서의 Transactions (0) | 2023.08.26 |
| values_list() (0) | 2023.08.09 |
Serializer에서 method 사용하기
Serializer클래스 내에서 method field를 사용해서, 데이터를 가공하거나 계산된 값을 직접 필드로 추가할 수 있습니다.
이는 데이터 모델에는 없지만, 응답에 포함되어야 하는 데이터를 생산할 때 유용합니다.
method field는 serializer클래스 내에 선언되며, 해당 클래스의 인스턴스에 의해 호출될 때 값을 반환합니다.
예
from rest_framework import serializers
class ProductSerializer(serializers.Serializer):
name = serializers.CharField(max_length=100)
price = serializers.DecimalField(max_digits=10, decimal_places=2)
discount_price = serializers.SerializerMethodField()
def get_discount_price(self, obj):
# obj는 시리얼라이저가 직렬화하고 있는 모델 객체입니다.
discount = 0.1
discount_price = obj.price * (1 - discount)
return discount_price
위의 예시에서 get_discount_price 메서드는 price 필드를 기반으로 할인된 가격을 계산하여 반환합니다.
이 메서드를 method field로 사용하기 위해 Serializer 클래스 내에 discount_price 필드를 선언합니다.
이렇게 하면 discount_price 필드는 get_discount_price 메서드의 반환값을 포함해, 실제 데이터베이스 모델에 없는 값을 계산해 API 응답에 추가합니다.
그리고 메서드는 꼭 사용할 필드명 앞에 get_이 붙는 형태입니다. 예를 들어 rating 필드를 사용한다면, 메서드는 get_rating이 되어야 합니다.
'Python > Django' 카테고리의 다른 글
| DRF) serializer에서 validation 메소드 만들기 (0) | 2023.10.01 |
|---|---|
| Django 소유자 여부 확인(DRF) (0) | 2023.08.28 |
| Django에서의 Transactions (0) | 2023.08.26 |
| values_list() (0) | 2023.08.09 |
| annotate() 메서드와 가변 키워드 인자 (0) | 2023.07.25 |
Django에서의 Transactions
트랜잭션(Transaction)이란?
트랜잭션은 데이터베이스에서 한 번에 수행되어야 할 일련의 연산들을 의미합니다. 트랜잭션은 아래의 4가지 속성을 가져야 합니다.
1. 원자성 (Atomicity)
트랜잭션의 모든 연산은 완전히 수행되거나, 아니면 전혀 수행되지 않아야 합니다. 연산 중 하나라도 실패하면 전체 트랜잭션은 취소되어야 하며, 모든 변경 사항이 롤백되어야 합니다.
예)
a가 b에게 100만 원을 이체하려고 할 때 a계좌에서 100만 원 차감 후 시스템 오류로 b계좌에 입금을 실패하면 돈은 사라지게 됩니다. 그래서 이를 오류 발생 시 전체 연산을 취소(롤백)하는 트랜잭션으로 해결할 수 있습니다.
2. 일관성 (Consistency)
트랜잭션이 성공적으로 완료되면 데이터베이스는 언제나 일관된 상태로 유지되어야 합니다.
예)
온라인 쇼핑몰에서 재고가 0이 되면 판매를 중지 해야 하기에,
제품 판매 후 재고 감소 처리를 원자적으로 수행하고, 재고가 0일 경우 판매를 중지하면서 재고와 판매 상태의 일관성을 유지해야 합니다.
3. 고립성 (Isolation)
하나의 트랜잭션이 실행되는 동안, 다른 트랜잭션의 연산은 이 트랜잭션에 영향을 주어서는 안 됩니다.
예)
경매 시스템에서 각 입찰을 독립된 트랜잭션으로 처리해야 합니다. 그래서 동시에 여러 사람이 입찰해도 서로에게 영향을 미치면 안 됩니다.
4. 지속성 (Durability)
트랜잭션이 성공적으로 완료되면, 그 결과는 영구적으로 데이터베이스에 저장되어야 합니다.
예)
만약 고객이 항공편 좌석을 예약하고 결제에 성공하면, 시스템에 장애가 발생하더라도 데이터베이스에 영구적으로 저장해야 합니다. 이러한 장애 상황 후에도 고객의 예약 정보를 유지해야 합니다.
이러한 원자성, 일관성, 고립성 및 지속성을 보장함으로써 데이터의 정확성과 안정성을 유지하고, 동시에 여러 사용자가 동시에 데이터에 액세스 할 수 있게 해 줍니다.
Django에서 트랜잭션 사용하기
1. transaction.atomic 데코레이터 사용
transaction.atomic 데코레이터를 사용하면 특정 함수 또는 메서드의 실행을 원자적으로 만들 수 있습니다.
from django.db import transaction
@transaction.atomic
def my_view(request):
# 이 함수 내의 데이터베이스 연산은 원자성을 가집니다.
2. transaction.atomic 컨텍스트 관리자 사용
컨텍스트 관리자를 사용하면 with 문 내에서만 원자성을 갖는 연산을 수행할 수 있습니다.
from django.db import transaction
with transaction.atomic():
# 이 코드 블록 내의 데이터베이스 연산은 원자성을 가집니다.
3. 수동으로 커밋 및 롤백 관리
Django에서는 수동으로 트랜잭션을 관리할 수 있는 방법도 제공합니다. transaction.set_autocommit를 사용하면 자동 커밋을 비활성화할 수 있으며, transaction.commit 및 transaction.rollback을 사용하여 트랜잭션을 직접 관리할 수 있습니다.
from django.db import transaction
transaction.set_autocommit(False)
try:
# 여기에 연산 코드를 작성
transaction.commit()
except:
transaction.rollback()
finally:
transaction.set_autocommit(True)
4. transaction.on_commit 사용
이 방법은 트랜잭션이 성공적으로 커밋된 후에만 특정 코드를 실행하고 싶을 때 사용합니다.
from django.db import transaction
def something_to_do():
# 커밋 후에 실행할 작업
pass
with transaction.atomic():
# 데이터베이스 연산
transaction.on_commit(something_to_do)
이러한 다양한 방법을 통해 Django에서 트랜잭션을 효과적으로 관리하고 원하는 동작을 구현할 수 있습니다.
'Python > Django' 카테고리의 다른 글
| Django 소유자 여부 확인(DRF) (0) | 2023.08.28 |
|---|---|
| Serializer에서 method 사용하기 (0) | 2023.08.27 |
| values_list() (0) | 2023.08.09 |
| annotate() 메서드와 가변 키워드 인자 (0) | 2023.07.25 |
| django에서 *args, **kwargs (0) | 2023.07.25 |