[ISSUE] Tag ํฌํจ๋ Site ๋ชจ๋ธ์ serialize ์ฒ๋ฆฌ
- -
[22.11.27]
๐ ๊ตฌํํ๊ณ ์ ํ๋ ํ๋ฉด
1. ์ด์ ๊ฐ๋ฐ ๋จ๊ณ์์ ์ฌ์ดํธ๋ฅผ ๋ฑ๋กํ์ฌ ํด๋น ์ฌ์ดํธ์ Tag๋ฅผ Many-to-Many๊ด๊ณ๋ก ๋ฑ๋กํ๋ ์งํ
2. ์ด์ ํ๊ทธ๊ฐ ๋ฑ๋ก๋ ์ฌ์ดํธ๋ฅผ ์ต์ ์์ผ๋ก 4~6๊ฐ ์กฐํ ํ ๋ฑ๋ก๋ ๋ชจ๋ ํ๊ทธ๋ฅผ ์กฐํํ์ฌ ํ๋จ์ Tag buttonํํ๋ก ๋์ ์ผ๋ก ๋ฟ๋ ค์ฃผ๋ ์์ ์ ์งํํ ๊ฒ์ด๋ค.
3. ์์ ๊ฐ์ด ์งํํ๊ธฐ ์ํด์ Siteํญ๋ชฉ์ ์กฐํํ ๋ฟ ์๋๋ผ Many-to-Many๊ด๊ณ๋ก ๋ฑ๋ก๋ ํ๊ทธ๋ ์กฐํ๋ฅผ ํด์ผํ๊ธฐ ๋๋ฌธ์ Serializer ์์ ์ ์งํํ๊ฒ ๋์๋ค.
- ๋ฌผ๋ก api 2๊ฐ๋ฅผ ์์ฒญํ์ฌ ๊ฐ๊ฐ ์ฌ์ดํธ ๋ฐ์ดํฐ, ํ๊ทธ ๋ฐ์ดํฐ ์กฐํํ ์๋ ์์ง๋ง 2๋ฒ์ ์์ฒญํ๋ค๋ ๊ฒ ์์ฒด๊ฐ ๋นํจ์จ์ ์ด๋ฉฐ drf์ ์กด์ฌํ๋ serialize๋ฅผ ํ์ฉํ์ง ๋ชปํ๋ค๊ณ ํ๋จ
1. views.py > TagsAPIView ๊ตฌํ
class TagsAPIView(APIView):
"""
Site model์ Tag model๊ฐ์ด ์กด์ฌํ๋ ๊ฒ๋ง ์กฐํ
"""
def get(self, request):
word: str = request.GET['word']
tags = [tag for tag in Tag.objects.all()]
list_qs = Site.objects.filter(
(Q(tag__in=tags))&(
Q(title__contains=word)|
Q(host_name__contains=word))).distinct()
serializer = SiteSerializer(list_qs, many=True)
return Response(serializer.data)
- /api/tags?word= api์์ฒญ์ผ๋ก ๋ค์ด์ค๋ view ๋จ ์์ ์ฝ๋์ด๋ค.
- word๋ ๊ฒ์์ผ๋ก ์กฐํ ์ ์์ฒญ๋๋ ๊ฐ์ด๋ฏ๋ก ์์ธํ ์ค๋ช ์ ์๋ตํ๊ฒ ๋ค.
- ๋จผ์ ํ๊ทธ๊ฐ ๋ฑ๋ก๋ ์ฌ์ดํธ ํญ๋ชฉ์ ์กฐํํ๊ธฐ ์ํด ๋ชจ๋ ํ๊ทธ๋ฅผ ์กฐํํ์ฌ tags์ ํ ๋น
- Site๋ชจ๋ธ์ tag๊ฐ ์์์ ํ ๋น๋ฐ์ tags๊ฐ ํฌํจ๋๋ฉฐ word๋ก ๋์ด์จ ๊ฐ์ด ํฌํจํ ๊ฐ์ด ์กฐํ ๋๊ฒ filter๋ฅผ ์์ฑ
- ๋จ, ์ค๋ณต๋ ๊ฐ์ด ์กฐํ๋์ง ์๊ฒ distinct()๋ฅผ ์ฌ์ฉ
- serializer๋ฅผ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ ์
๋ฐ ๋ชจ๋ธ ์ธ์คํด์ค์ ๊ฐ์ ๋ณต์กํ ๋ฐ์ดํฐ๋ฅผ Python ๋ฐ์ดํฐ ํ์
์ผ๋ก ๋ณํํ ๋ค์
JSON
,XML ๋๋
๋ค๋ฅธ ์ฝํ ์ธ ์ ํ์ผ๋ก ์ฝ๊ฒ ๋ ๋๋ง ํ ์ ์๊ธฐ ๋๋ฌธ์ queryset์ SiteSerializer์ ๋ฃ์ด ๋ฐํ๋ฐ์ ๋ฆฌํด ์์ผฐ๋ค.
๐ SiteSerializer
lass SiteSerializer(ModelSerializer):
CATEGORY_CHOICES = [(1, 'python'), (2, 'django'), (3, 'javascript'), (4, 'orm'), (5, 'mysql'), (6, 'drf'), (7, 'docker'), (8, 'os'), (9, 'aws'), (10, 'html'), (11, 'css'), (12, 'git'), (13, 'linux')]
title = serializers.CharField(max_length=100, allow_blank=False, trim_whitespace=True)
thumbnail_url = serializers.URLField(max_length=200, min_length=None, allow_blank=False)
host_name = serializers.CharField(max_length=30, allow_blank=False, trim_whitespace=True)
content = serializers.CharField(max_length=2000, allow_blank=True)
category = serializers.ChoiceField(choices=CATEGORY_CHOICES)
user = serializers.CharField(max_length=10, allow_blank=False, trim_whitespace=True)
favorite = serializers.BooleanField(default=False)
video = serializers.BooleanField(default=False)
def create(self, validated_data):
return Site.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.category = validated_data.get('category', instance.category)
instance.favorite = validated_data.get('favorite', instance.favorite)
instance.video = validated_data.get('video', instance.video)
instance.save()
return instance
class Meta:
model = Site
exclude = ["created_at", "updated_at"]
- ํ์ฌ ์ฌ์ดํธ ์๋ฆฌ์ผ๋ผ์ด์ฆ๋ ์์ ๊ฐ์ด Site๋ชจ๋ธ์ด ๊ฐ์ง๊ณ ์๋ field๋ฅผ ์๋จ์ ์ ์ธ
- create์ update ์์ ์ด ์ด๋ฃจ์ด์ง ๋ validation์์ ์ ํ ์ ์๊ฒ ํจ์ ์์ฑ
- ๋ฐํ๋๋ ๊ฐ์ created_at์ updated_at๋ฅผ ์ ์ธํ ๋ชจ๋ ๊ฐ์ด ์กฐํ๋๊ฒ exclude์
created_at
,updated_at
์ ํ ๋นํด ์ฃผ์๋ค.
2. ๊ธฐ์กด serializer๋ฅผ ์ด์ฉํ response
โ๏ธ [http://127.0.0.1:8000/api/tags?word=](http://127.0.0.1:8000/api/tags?word=)
api๋ฅผ ํธ์ถ, ํ์ฌ response๊ฐ
โ๏ธ ํ์ฌ response๊ฐ์ ์ด์ฉํด์ ์ฌ์ดํธ๋ฅผ ๊ตฌํํ ์ ์์ง๋ง ํ๊ทธ ๊ฐ์ด ์กด์ฌํ์ง ์์ ์์ ์ด๋ฏธ์ง์ฒ๋ผ ํ๋จ์ ํ๊ทธ๋ฅผ buttonํ์์ผ๋ก ๊ตฌํํ ์ ์๋ค.
โ๏ธ serializer๋ ํ ๋ฒ๋ง ๊ฑธ์ณ์ tag๊ฐ์ด ํฌํจ๋ site๊ฐ์ ์กฐํํ๊ธฐ ์ํด models.py์ serializers.py๋ฅผ ์์ ํด ์ฃผ๊ฒ ๋ค.
๐ serializers.py
โ๏ธ drf ์ ์ ๋ฌธ์๋ฅผ ๋ณด์ฌ ํ๋์ ์๋ฆฌ์ผ๋ผ์ด์ฆ์์ many-to-many๊ด๊ณ๋ฅผ ๊ฐ์ง ๋ ๊ฐ์ ๋ชจ๋ธ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ์กฐํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ฐพ์๋ณด์๋ค.
โ๏ธ Nested relationships ์ด๋ผ๊ณ ํ๋ฉฐ ์๋ก ๋ ๋ชจ๋ธ ๊ฐ ๊ด๊ณ๊ฐ ์ค์ ๋์ด ์๋ ๊ฒฝ์ฐ ๊ฐ์ ธ์ฌ ์ ์๋ค.
class SiteSerializer(ModelSerializer):
CATEGORY_CHOICES = [(1, 'python'), (2, 'django'), (3, 'javascript'), (4, 'orm'), (5, 'mysql'), (6, 'drf'), (7, 'docker'), (8, 'os'), (9, 'aws'), (10, 'html'), (11, 'css'), (12, 'git'), (13, 'linux')]
title = serializers.CharField(max_length=100, allow_blank=False, trim_whitespace=True)
thumbnail_url = serializers.URLField(max_length=200, min_length=None, allow_blank=False)
host_name = serializers.CharField(max_length=30, allow_blank=False, trim_whitespace=True)
content = serializers.CharField(max_length=2000, allow_blank=True)
category = serializers.ChoiceField(choices=CATEGORY_CHOICES)
user = serializers.CharField(max_length=10, allow_blank=False, trim_whitespace=True)
favorite = serializers.BooleanField(default=False)
video = serializers.BooleanField(default=False)
**tag = TagSerializer(many=True, read_only=True)**
def create(self, validated_data):
return Site.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.category = validated_data.get('category', instance.category)
instance.favorite = validated_data.get('favorite', instance.favorite)
instance.video = validated_data.get('video', instance.video)
instance.save()
return instance
class Meta:
model = Site
# exclude = ["created_at", "updated_at"]
fields = ['title', 'thumbnail_url'
, 'host_name', 'content'
, 'category', 'user', 'favorite', 'video', **'tag'**]
1. ๋ฐํ๋๋ fields์ tag๋ฅผ ํฌํจํ์ฌ ๋ณด๋ผ ์ ์๊ฒ ์ถ๊ฐ
2. SiteSerializer๊ฐ tag๋ฅผ ์ธ์ํ ์ ์๊ฒ ์๋จ์ tag ํ๋ ์ค์
3. tagํ๋๋ฅผ ์ค์ ํ๊ธฐ ์ํด TagSerializer์์ฑ
- site์ ๋ฌถ์ธ ๋ชจ๋ tag๋ฅผ ์กฐํํ๊ธฐ ์ํด many=True, read_only=True์์ฑ ์ถ๊ฐ
class TagSerializer(ModelSerializer):
name = serializers.CharField(max_length=20, allow_blank=False, trim_whitespace=True)
class Meta:
model = Tag
fields = ['id', 'name']
1. name ํ๋ ๊ฐ์ ์ค์
2. ๋ฐํ๋๋ field ์ค์
- ํ๊ทธ ์ด๋ฆ์ ํ๋ฉด์ ๋ฐ์ธ๋ฉํ ๋ ์ฌ์ฉ
- id ๊ฐ์ ํด๋น ํ๊ทธ ์ ํ ์ api ํธ์ถ์ ๋ํ ์๋ณ์ ๊ฐ์ผ๋ก ๋ณด๋ด๊ธฐ ์ํด ์ฌ์ฉ
โ๏ธ ์ด๋ ๊ฒ TagSerializer๋ ์์ฑ์ ํ๊ณ SiteSerializer๋ฅผ ํธ์ถํ ๋ ๋ฐํ๋๋ ๊ฐ์ tag๊ฐ ํฌํจ๋๊ฒ ์ฝ๋์์ฑ์ ํด ์ฃผ์๋ค.
โ๏ธํ์ง๋ง ๊ฒฐ๊ณผ๋ ๋์ผํ๊ฒ tag๋ ํฌํจ๋์ง ์๊ณ response๊ฐ์ด ๋์จ ๊ฑธ ํ์ธํ ์ ์๋ค.
3. models.py related_name ์ค์
class Tag(models.Model):
""" ์น ํญ๋ชฉ ํ๊ทธ ๋ชฉ๋ก ๋ชจ๋ธ """
name = models.CharField(verbose_name='์ด๋ฆ', max_length=20)
site = models.ManyToManyField(Site, **related_name='tag'**,verbose_name='๋ฆฌ์คํธ')
def __str__(self):
return f"{self.name}"
class Meta:
verbose_name = 'ํ๊ทธ'
verbose_name_plural = 'ํ๊ทธ ๋ชฉ๋ก'
โ๏ธ Tag ๋ชจ๋ธ์ ํ์งํ ๋ site์์ ๊ฐ์ ์ฝ์ด ๋ผ ์ ์๋๋ก related_name์ tag๋ก ์ค์ ํ ๋ค์ migrate ํ๊ณ ์งํํ์ฌ ๋ณด๊ฒ ๋ค.
4. ์์ ํ serializer๋ฅผ ์ด์ฉํ response
๐ ์ฐธ๊ณ
'ISSUE > Django' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ISSUE] ManytoMany ๊ด๊ณ๋ฅผ ๊ฐ์ง ๋ ๋ชจ๋ธ Bulk Create ์์ (1) | 2023.05.06 |
---|---|
[ISSUE]decorator๋ฅผ ์ด์ฉํ ์ค๋ณต์์ ์ ์ฒ๋ฆฌ (0) | 2023.05.05 |
[ISSUE] signup AbstractBaseUser class (0) | 2023.05.05 |
์์คํ ๊ณต๊ฐ ๊ฐ์ฌํฉ๋๋ค