내일배움캠프 - DRF 5일차 과제

Dongwoo Kim·2022년 6월 22일
0

내일배움캠프 - DRF

목록 보기
9/12

스파르타코딩클럽

내일배움캠프 AI 웹개발자양성과정 2회차

DRF 강의 5일차 과제

0. 과제 내용

  1. product라는 앱을 새로 생성해주세요
  2. product 앱에서 <작성자, 제목, 썸네일, 설명, 등록일자, 노출 시작 일, 노출 종료일>가 포함된 product 테이블을 생성해주세요
  3. django serializer에서 기본적으로 제공하는 validate / create / update 기능을 사용해 event 테이블의 생성/수정 기능을 구현해주세요
    • postman으로 파일을 업로드 할 때는 raw 대신 form-data를 사용하고, Key type을 File로 설정해주세요
  4. 등록된 이벤트 중 현재 시간이 노출 시작 일과 노출 종료 일의 사이에 있거나, 로그인 한 사용자가 작성한 product 쿼리셋을 직렬화 해서 리턴해주는 serializer를 만들어주세요
  5. product field를 admin에서 관리할 수 있도록 등록해주세요

1. product라는 앱을 새로 생성해주세요

django-admin startapp prduct

# settings.py
INSTALLED_APPS = [
	...
    'user',
    'blog',
    'product',
]

2. product 앱에서 <작성자, 제목, 썸네일, 설명, 등록일자, 노출 시작 일, 노출 종료일>가 포함된 product 테이블을 생성해주세요

# product/models.py
from user.models import User as UserModel

class Product(models.Model):
    author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    title = models.CharField(max_length=30)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    show_start_at = models.DateTimeField(default="2022-06-20 00:00:00")
    show_end_at = models.DateTimeField(default="2022-06-25 00:00:00")
    thumbnail = models.ImageField(upload_to='product/img', height_field=None, width_field=None, max_length=100)
    
    def __str__(self):
        return f'Product : {self.title} - {self.author}'

3. django serializer에서 기본적으로 제공하는 validate / create / update 기능을 사용해 event 테이블의 생성/수정 기능을 구현해주세요

  • postman으로 파일을 업로드 할 때는 raw 대신 form-data를 사용하고, Key type을 File로 설정해주세요
# product/serializers.py
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
    author = serializers.SerializerMethodField()
    
    def get_author(self, obj):
        author_name = obj.author.username
        return author_name

    class Meta:
        model = Product
        fields = ["title", "author", "content", "created_at", "show_start_at",
                  "show_end_at"]

    def validate(self, data):
        if 'babo' in data.get('title'):
            raise serializers.ValidationError(
                    detail={"error": "부적절한 단어를 사용할 수 없습니다."},
                )

        return data

    def create(self, validated_data):
        author = self.context.get('request').user
        files = self.context.get('request').FILES
        thumbnail = files.get('thumbnail')

        product = Product(author=author, thumbnail=thumbnail, **validated_data)
        product.save()

        return product

    # instance : 수정할 object
    # validated_data : 수정할 내용
    def update(self, instance, validated_data):
        for key, value in validated_data.items():
            setattr(instance, key, value)
        instance.save()
        return instance
# product/views.py
from .models import Product
from .serializers import ProductSerializer
from django.utils import timezone
from django.db.models.query_utils import Q


# 제품 관련 기능
class ProductView(APIView):
    # 제품 조회 기능
    def get(self, request):
        ...

    # 제품 생성 기능
    def post(self, request):
        product_serializer = ProductSerializer(data=request.data, context={'request': request})
        if product_serializer.is_valid():
            product_serializer.save()
            return Response({'message': '저장 완료!'}, status=status.HTTP_200_OK)

        return Response(product_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # 제품 수정 기능
    def put(self, request):
        product_id = request.data.pop('product_id')[0]
        product = Product.objects.get(id=product_id)
        product_serializer = ProductSerializer(product, data=request.data, partial=True)

        if product_serializer.is_valid():
            product_serializer.save()
            return Response({"message": "수정 완료!!"}, status=status.HTTP_200_OK)
        
        return Response(product_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  • postman request example

4. 등록된 이벤트 중 현재 시간이 노출 시작 일과 노출 종료 일의 사이에 있거나, 로그인 한 사용자가 작성한 product 쿼리셋을 직렬화 해서 리턴해주는 serializer를 만들어주세요

# product/views.py

# 제품 관련 기능
class ProductView(APIView):
    # 제품 조회 기능
    def get(self, request):
        user = request.user             # 현재 로그인한 유저
        show_now_at = timezone.now()    # 현재 시간
        # show_now_at = "2022-06-24 00:00:00"   # 임의 시간

        # 작성자가 현재 로그인한 유저 이거나
        # 현재시간이 노출 시작시간과 종료시간 사이인 제품만 조회
        query = Q(author=user) | (Q(show_start_at__lte=show_now_at) & Q(show_end_at__gte=show_now_at))
        products = Product.objects.filter(query)
        
        # 모든 제품 조회
        # products = Product.objects.all()
        return Response(ProductSerializer(products, many=True).data)

    # 제품 생성 기능
    def post(self, request):
    	...
        
    # 제품 수정 기능
    def put(self, request):
    	...

5. product field를 admin에서 관리할 수 있도록 등록해주세요

# product/admin.py
from django.contrib import admin
from .models import Product
from django.utils.html import mark_safe

class ProductAdmin(admin.ModelAdmin):
    list_display = ['id', 'image_preview','title', 'author']
    list_display_links = ('id', 'title', 'author')
    list_filter = ('author', )
    search_fields = ('title', 'author')

    fieldsets = (
        ("info", {'fields': ('title', 'content', 'created_at',)}),
        ('show_date', {'fields': ('show_start_at', 'show_end_at', )}),
        ('thumbnail', {'fields': ('thumbnail', 'image_tag', )}),
        )
    
    def get_readonly_fields(self, request, obj=None):
        return ('created_at', 'image_tag', )

    def image_tag(self, obj):
        if obj.thumbnail:
            return mark_safe(f'<img src="{obj.thumbnail.url}" width="150" height="150" />')
        return None

    def image_preview(self, obj):
        if obj.thumbnail:
            return mark_safe(f'<img src="{obj.thumbnail.url}" width="50" height="50" />')
        return None
    
    image_tag.short_description = 'Image'
    image_tag.allow_tags = True

admin.site.register(Product, ProductAdmin)
# setting.py
MEDIA_URL = '/media/'		
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

product admin page

Github

https://github.com/kimphysicsman/nbcamp-drf-2

profile
kimphysicsman

0개의 댓글