🤍 전 강의 25% 할인 중 🤍

2024년 상반기를 돌아보고 하반기에도 함께 성장해요!
인프런이 준비한 25% 할인 받으러 가기 >>

  • 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    미해결

안녕하세요 강사님 강의 수강완료 후 복습 중 페이지 구성에 질문이 있어 글남깁니다.!

22.06.01 23:54 작성 조회수 162

1

안녕하세요 강사님. 

복습 중에 질문이 있어 문의드립니다. 현재  복습을 목적으로

개인 페이지를 만들어보고 있는데.. 

회원가입 버튼을 위 사진과 같이 구성을 하였고,

회원가입의 url은 localhost:3000/accounts/signup

으로 지정한 상태입니다. 

 

제가 질의드리고 싶은것 Create Account 아이콘에

회원가입 url으로 링크를 걸어 버튼이 클릭되면 

회원 가입 Form을 호출하는 방식도 가능한지

문의드립니다.

 

추가로 태그를 포스트 하단에 아래와 같이 자동으로 

입력되게 하기 위해.. 아래 코드만들었고 작동을 잘 하지만..

좀더 간단한 방법도 있는지... 같이 문의드립니다.

- 작업 결과

 

장고 / Post, Tag 모델,

content에서 #으로 시작하는 문자열 추출후 Tag 생성/저장

# models.py
class Post(BaseModel):
	author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='post_author')
	category = models.CharField(max_length=100, default='all')
	title = models.CharField(max_length=100)
	content = models.TextField()
	attached_file = models.FileField(blank=True, upload_to="shareinfo/post/cover/%Y/%m/%d")
	cover_img = models.ImageField(blank=True, upload_to="shareinfo/post/cover/%Y/%m/%d")
	post_tag_set = models.ManyToManyField('Tag', blank=True)
	like_user_set = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='post_likes')
	ip = models.GenericIPAddressField(null=True, editable=False)

	class Meta:
		ordering = ['-id']

	def __str__(self):
		return self.title + ' | ' + str(self.author)

	def cover_img_url(self):
		if self.cover_img:
			return self.cover_img.url
		else:
			return self.title

	def get_absolute_url(self):
		return reverse('shareinfo:post_detail', args=[self.pk])

	def extract_tag_list(self):
		tag_name_list = re.findall(r"#([a-zA-Z\dㄱ-힣]+)", self.content)
		tag_list = []
		for tag_name in tag_name_list:
			tag, _  = Tag.objects.get_or_create(name=tag_name) # tag 반환값, 반환결과에 대한 불리언 값
			tag_list.append(tag)
		return tag_list

	def is_like_user(self, user):
		return self.like_user_set.filter(pk=user.pk).exists()

class Tag(models.Model):
	name = models.CharField(max_length=20, unique=True)

	def __str__(self):
		return self.name

 

#serializer

class PostSerializer(ModelSerializer):
	author = AuthorSerializer(read_only=True)
	is_like = serializers.SerializerMethodField("post_likes_field")
	post_tag_set = serializers.CharField(source='extract_tag_list')

	class Meta:
		model = Post
		fields = '__all__'

 

React / post_tag_set을 받아서 문자열을 

배열 형태로 변경 후 map함수를 활용하여 

태그 컴포넌트 생성

import * as React from 'react';
import Chip from '@mui/material/Chip';

export default function ChipsArray({post}) {
    const handleClick = () => {
        console.info('You clicked the Tag.');
    };

// 문자열로 받은 post_tag_set을 replace와 map을 활용하여 태그 추출 -> 새로운 배열 생성
    const tag_set = post.post_tag_set
    const string_to_array = tag_set.replace(/ /g, '').replace(/\[/, '').replace(/\]/, '').split(',')
    const tag_set_array = string_to_array.map(tag => tag.slice(5, -1))

// 생성 후 map을 이용한 태그 컴포넌트 생성
    return (
        tag_set_array.map((data) => {
            return (
                <Chip label={data} onClick={handleClick} key={data} sx={{fontSize: '15px', marginRight: 1, marginTop: 1}}/>
            );
        })
    );

}

답변 1

답변을 작성해보세요.

1

안녕하세요.

클라이언트 단에서 "회원 가입 Form을 호출하는 방식"이란 없습니다. 클라이언트 단에서 서버로 http 요청을 보내면, 그 http 요청을 뷰 단에서 처리할 때 장고 Form을 통한 유효성 검사 및 이에 대한 응답으로 html form을 렌더링해서 응답으로 주는 것 뿐입니다. // 프로세스를 좀 더 정리해서 질문을 주셨으면 합니다.

Post 모델의 extract_tag_list 메서드를 통해 post.content로부터 Tag 모델 인스턴스를 획득할 수 있는 데요. 이를 PostSerializer에서 extract_tag_list를 호출하여 tag 목록을 획득하셨는 데, 굳이 이렇게 하실 필요가 없습니다. 제가 extract_tag_list를 만든 것은 포스팅을 새롭게 저장할 때 포스팅 내용으로부터 태그 목록을 생성하기 위해서이구요. 이미 저장된 포스팅을 조회하실 때에는 extract_tag_list가 아니라 Post 모델에 M2M('Tag')로 지정하신 필드를 통해 조회를 하시는 것이 맞습니다. 그리고 PostSerializer에서 태그목록을 문자열이 아니라 배열 형태로 받으실 수 있습니다.

그러니 리액트 단에서 굳이 문자열을 파싱하실 필요가 없습니다. 배열을 그대로 받아서 보여주기만 하면 되기 때문이죠.

그리고 함수 컴포넌트에서 속성값으로 주입받은 어떤 값을 계산해야할 때에는 useEffect 훅 내에서 계산하시는 것이 좋습니다. 왜냐하면 지금처럼 훅 밖에서 계산하시면 매번 ChipsArray 컴포넌트가 렌더링될때마다 파싱 계산을 수행하기 때문입니다. 이 파싱 계산은 post 속성값이 변경되지 않는다면 굳이 재계산을 할 필요가 없거든요. // 지금은 ChipsArray 컴포넌트가 작기 때문에 컴포넌트 렌더링 성능에 무리가 없어 보이지만, 컴포넌트가 조금만 커져도 불필요한 재렌더링으로 인해 성능이 매우 낮아질 수 있습니다.

화이팅입니다. :-)

유형주님의 프로필

유형주

질문자

2022.06.02

답변 감사드립니다. 위에 질문은 조금 정리를 해봐야겠습니다.. ㅎㅎ..  리액트에대해서 감이 잡힐듯 말듯하네요

채널톡 아이콘