from django.urls import reverse
from rest_framework.test import APITestCase
from .models import User
# Create your tests here.
# 이미지업로드(임시 파일을 만들어 가상 이미지 생성)
from django.test.client import MULTIPART_CONTENT, encode_multipart, BOUNDARY
from PIL import Image
import tempfile # 임시파일을 만드는 라이브러리
def get_temporary_image(temp_file):
size = (200, 200)
color = (255, 0, 0)
image = Image.new("RGBA", size, color)
image.save(temp_file, 'png')
return temp_file
class ArticleCreateTest(APITestCase):
# 테스트를 시작할 때 모든 메서드에 대해서 아래 함수 실행됨
@classmethod
def setUpTestData(cls):
cls.user_data = {"email": "ggg@ggg.com","fullname": "GGG", "password": "ggg"}
cls.article_data = {"title": "some title", "content": "some content"}
cls.user = User.objects.create_user('ggg@ggg.com', 'ggg')
def setUp(self):
self.access_token = self.client.post(reverse('token_obtain_pair'), self.user_data).data['access']
# 테스트 함수 명은 반드시 맨앞에 test_ 가 붙어있어야한다!
# 로그인이 되어있지 않은 유저가 게시글 작성 시도 시 401
def test_fail_if_not_logged_in(self):
url = reverse("article_view")
response = self.client.post(url, self.article_data)
self.assertEqual(response.status_code, 401)
# 글작성 테스트(이미지 없음)
def test_create_article(self):
response = self.client.post(
path=reverse("article_view"),
data=self.article_data,
HTTP_AUTHORIZATION=f"Bearer {self.access_token}"
)
self.assertEqual(response.data["message"], "글 작성 완료!")
self.assertEqual(response.status_code, 200)
# 글작성 테스트(이미지 포함)
def test_create_article_with_image(self):
# 임시 이미지 파일 생성
temp_file = tempfile.NamedTemporaryFile() # 이름이있는 그냥 빈파일 생성
temp_file.name = "image.png" # 이름 지정
image_file = get_temporary_image(temp_file) # 빈파일을 아까 만들어둔 함수에 인자로 줘서 이미지 파일로 생성
image_file.seek(0) # 첫번째 프레임을 가져와야함
# 생성한 이미지 파일을 article_data에 추가
self.article_data["image"] = image_file
# 전송
response = self.client.post(
path=reverse("article_view"),
data=encode_multipart(data=self.article_data, boundary=BOUNDARY),
content_type=MULTIPART_CONTENT,
HTTP_AUTHORIZATION=f"Bearer {self.access_token}"
)
self.assertEqual(response.data["message"], "글 작성 완료!")
self.assertEqual(response.status_code, 200)
python manage.py test (app이름) app 이름을 입력할 경우 해당 앱의 tests.py 만 실행됨
test 함수를 작성할 떄 함수명을 반드시 test_ 로 시작해야 test를 돌릴 수 있다.
단축키 강의
ctrl + alt 멀티커서
alt 클릭
ctrl + f2 같은 단어 드래그
한줄 복사 copy line down
라인에서 ctrl + shift 위아래
라인에서 ctrl + x 한줄 지우기
ctrl + shift + n 파일검색
ctrl + shift + f 단어검색
ctrl K S 눌리면 단축키 변경 가능
폴더 깡통 만든 후
python -m venv venv
pip install django
pip install djangorestframework
pip freeze > requirements.txt
django-damin startproject shopping .
python manage.py startapp user
python manage.py startapp product
#shopping/settings.py
INSTALLED_APP
'rest_framework',
'user',
'product'
STATIC_URL = "static/"
MEDIA_URL = "media/"
ABSTRACT_USER = "user.User"
#user/models.py
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
if not username:
raise ValueError('Users must have an username')
user = self.model(
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
# python manage.py createsuperuser 사용 시 해당 함수가 사용됨
def create_superuser(self, username, password=None):
user = self.create_user(
username=username,
password=password
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
username = models.CharField(unique=True)
password = models.CharField
email = models.EmailField(unique=True)
fullname = models.CharField
phone = models.CharField
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
cart = models.ManyToManyField("product.ProductOption", through="Cart", related_name="carts")
like = models.ManyToManyField("product.Product", reladted_name="likes")
USERNAME_FIELD = 'username'
REQUIRED_FIELD = []
objects = UserManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, perm, obj=None):
return True
@property
def is_staff(self):
return self.is_admin
class Celler(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="users")
approval_date = models.DateTimeField(null=True)
class Cart(models.Model):
user = ForeignKey(User, on_delete=models.CASCADE)
count = models.IntegerField
product_option = models.ForeignKey("product.ProductOption", on_delete=models.CASCADE)
class PurchaseList(models.Model):
STATUS = (
("ready", "배송준비"), ("delivery", "배송중"), ("Done", "배송완료")
)
user = ForeignKey(User, on_delete=models.CASCADE)
count = models.IntegerField
status = models.CharField(choices=STATUS)
class PurchaseHistory(models.Model):
STATUS = (
("card", "카드"), ("cash", "현금"),
)
puerchase_list = models.ManyToManyField(PurchaseList)
payment_type = models.CharField(choices=STATUS)
payment_datetime = models.DataTimeField
#product/models.py
class Category(models.Model):
name = models.CharField
def __str__(self):
return self.name
class Product(models.Model):
user = models.ForeignKey("user.user", on_delete=models.CASCADE)
thumnail = models.FileField("", upload_to="product/thumnail")
detail = models.FileField("", upload_to="product/detail")
category = models.ForeignKey(Category, on_delete=models.SET_NULL)
title = models.CharField
discription = models.TextField
created = modesl.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class productOption(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
name = CharField
price = models.IntegerField
def __str__(self):
return f"{self.product}의 옵션{self.user.username}님이 등록하신 상품"
class Review(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
user = models.ForeignKey("user.user", on_delete=models.CASCADE)
rating = modesl.IntegerField
content = models.CharField
created = models.DateTimeField
# shopping/urls.py
from django.urls import path, include
path('user/', include('user.urls'),
path('product/', include('product.urls'),
#user/urls.py
path('', views.UserView.as_view())
path('cart/', views.UserCartView.as_view())
#user/views.py
from rest_framework.views import APIView
from rest_framework.response imprt Response
from rest_framework import permissions, status
from user.serializers import UserSerializer
class UserView(APIView):
def ger(self, request):
return Response
# 회원가입
def post(self, request):
user_serializer = UserSerializer(data=request.data)
user_serializer.is_valid(raise_exception=True)
user_serializer.save()
return Response(user_serializer.data, status=status.HTTP_200_OK)
# 회원수정
def put(self, request):
return Response
# 회원탈퇴
def delete(self, request):
return Response
class UserAPIView(APIView):
# 로그인
def post(self, request):
user = authenticate(request, **request.data)
if not user:
login(request, user)
return Response("error" : "로그인 실패" , status=status.HTTP_400_BAD_REQUEST)
return Response("message": "로그인 성공", status=stauts.HTTP_200_OK)
#로그아웃
def delete(self, request):
logout(request)
return Response("message": "로그아웃 완료", status=stauts.HTTP_200_OK)
class UserCartView(APIView):
def get(self, request):
carts = CartModel.objects.filter(user=reqeust.user)
return Response(UserCartSerializer(carts, many=True).data, status=status.HTTP_200_OK)
def post(self, request):
request.data["user"] = request.user.id
user_cart_serializer = UserCartSerializer(data=request.data)
user_cart_serializer.is_valid(raise_exception=True)
user_cart_serializer.save()
return Response({})
# user/serializer.py
from rest_framework import serialzers
*User모델들 임포트 해오기
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
password = validated_data.pop("password", "")
user = UserModel(**validated_data)
user.set_password(password)
user.save()
class Meta:
model = UserModel
fields = ["username", "email", "password",
"fullname", "phone", "cart", "like", ]
read_only_fields = ["like", "cart", ]
extra_kwargs = {
"password": {"write_only": True}
}
class UserCartSerializer(seserializers.ModelSerializer):
product_option_id = serializers.IntegerField(write_only=True)
product_info = serializer.SerializerMethodField(read_only=True)
def get_product_info(self, obj):
return obj.product_option.product.title
product_option_info = serializers.SerializerMehtodField(read_only=True)
def get_product_option_info(self, obj):
return obj.product_option.name
price = serializers.SerializerMehtodField(read_only=True)
def get_price(self, obj):
return obj.product_option.price
sum_price = serializers.SerializerMehtodField(read_only=True)
def get_sum_price(self, obj):
return obj.product_option.price * obj.count
class Meta:
model = CartModel
fields = ["user", "count", "product_option_id", "product_info", "product_option_info"]
extra_kwargs = {
"user": {"write_only": True}
}
# user/admin.py
admin.site.register(User)
# product/urls.py
path('', views.ProductView.as_view()),
path('detail/<product_id>', views.ProductDetailView.as_view()),
path('review/update/<product_id>', views.ReviewView.as_view()),
path('review/<product_id>', views.ReviewView.as_view()),
path('<product_id>', views.ProductView.as_view()),
# product/views.py
from rest_framework.views import APIView
from rest_framework.response imprt Response
from rest_framework import permissions, status
from user.serializers import ProductSerializer
class ProductView(APIView):
# 상품 목록 조회
def get(self, request):
return Response(ProductSerializer(ProductModel.objects.all(), many=True), status=status.HTTP_200_OK)
# 상품 등록
def post(self, request):
request.data["user"] = request.user.id
product_serializer = ProductSerializer(data=request.data)
product_serializer.is.valid(raise_exception=True)
product_serializer.save()
return Response(product_serializer.data, status=status.HTTP_200_OK)
# 상품 수정
def put(self, request):
try:
product = ProductModel.objects.get(id=product_id)
except ProductModel.DoesNotExist:
return Response({"error" : "없는 상품 입니다."},
status=status.HTTP_400_BAD_REQUEST)
request.data["user"] = request.user.id
product_serializer = ProductSerializer(product, data=request.data, partial=True)
product_serializer.is_valid(raise_exception=True)
product_serializer.save()
return Response(product_serializer, status=status.HTTP_200_OK)
def delete(self, request):
return Response
class ReviewView(APIView):
def post(self, request):
request.data["user"] = request.user.id
review_serializer = ReviewSerializer(data=request.data)
review_serializer.is.valid(raise_exception=True)
review_serializer.save()
return Response(review_serializer, status=status.HTTP_200_OK)
def put(self, request):
try:
review = ReviewModel.objects.get(id=review_id)
except ReviewModel.DoesNotExist:
return Response({"error" : "없는 리뷰 입니다."},
status=status.HTTP_400_BAD_REQUEST)
request.data["user"] = request.user.id
review_serializer = ReviewSerializer(review, data=request.data, partial=True)
review_serializer.is.valid(raise_exception=True)
review_serializer.save()
return Response(review_serializer, status=status.HTTP_200_OK)
def delete(self, request):
return Response({})
class ProductDetailView(APIView):
def get(self, request, product_id):
try:
product = ProductModel.objects.get(id=product_id)
except ProductModel.DoesNotExist:
return Response({"error" : "없는 상품 입니다."},
status=status.HTTP_400_BAD_REQUEST)
response Response({ProductSerializer(product).data, status=status.HTTP_200_OK})
# product/serializer.py
from rest_framework import serialzers
#Product모델들 임포트 해오기
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = CategoryModel
fields = ["name"]
class ProductSerializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
def get_category(self, obj):
return obj.category.name
class Meta:
model = UserModel
fields = ["user", "thumnail", "detail", "title",
"category", "discription", "created" ]
read_only_fields = ["category", "created", ]
def create(self, validated_data):
password = validated_data.pop("password", "")
user = UserModel(**validated_data)
user.set_password(password)
user.save()
class ReviewSerializer(serializers.ModelSerializer):
class Meta:
model = ReviewModel
fields = "__all__"
extra_kwargs= {
"product": {"write_only": Ture},
}
class ProductOptionSerializer(serializers.ModelSerializer):
class Meta:
medel = ProductOptionModel
fields = ["name", "price"]
class ProductDetailSerializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
def get_category(self, obj):
return obj.category.name
options = ProductOptionSerializer(many=True, source="productoption_set"
reiview = ReviewSerializer(many=Ture, source="review_set")
class Meta:
model = ProductModel
fields = "__all__"
라이브코딩하시는 걸 따라 치는 거다보니 누락된 부분도 있고하다 전체적으로 좋은 코드라고 생각하여 참고용으로 저장
'회고록(TIL&WIL)' 카테고리의 다른 글
TIL 2022.07.14 DRF APIView Pagination (0) | 2022.07.14 |
---|---|
TIL 2022.07.13 SidePro - S.A, 모델링 (0) | 2022.07.13 |
TIL 2022.07.11 DRF TestCode (0) | 2022.07.11 |
TIL 2022.07.11 Docker (0) | 2022.07.11 |
TIL 2022.07.07 javascript fetch api, 이미지 미리보기, radio 값가져오기, 날짜포맷팅, forEach문, arrow function, modal (0) | 2022.07.06 |