inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

model 설계, 데이터 저장

347

gbch526

작성한 질문수 2

0

안녕하세요. 장고를 활용하여 웹사이트를 만들고 있는 중입니다.

제가 지금 구현 중인 부분은 식단표 페이지로, 모델 단과 데이터 입력 단에서 막혀서 질문을 드립니다.

우선, "menu_list.html" 화면을 아래와 같이 띄우려고 합니다. 이를 위해 모델 구현부터 질문드리겠습니다.

Untitled (1)-20.jpg

첫번째 질문은 모델 구현에 대한 부분입니다. 최초 모델보다 수정 모델이 더 바람직한 방향인지 궁금합니다.

#최초 model
class Menu(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author_menu')
    date = models.DateField(unique=True)
    breakfast = models.TextField()
    lunch = models.TextField()
    dinner = models.TextField()
    voter = models.ManyToManyField(User, related_name='voter_menu')
    
    def __str__(self):
        return self.breakfast
#수정 model
TYPE_CHOICES = (
    ("아침", "아침"),
    ("브런치", "브런치"),
    ("점심", "점심"),
    ("저녁", "저녁"),
)

class Dish(models.Model):
    dish = models.CharField(max_length=10)
    voter = models.ManyToManyField(User)   

    def __str__(self):
        return self.dish

class Menu(models.Model):
    type = models.CharField(choices=TYPE_CHOICES, max_length=3)
    date = models.DateField() 
    dish = models.ManyToManyField(Dish)

최초 모델은 아무런 고민 없이 TextField로 식사 정보를 모두 받아왔으나 성능 측면에서 비효율적일 수 있다는 생각이 들어 고민을 하고 수정하였습니다. 수정된 설계가 더 바람직한 것인지 의문이 들어 질문드립니다. 더 바람직한 방향이 있다면 가르쳐주세요!!

두번째 질문은, 수정된 model을 통해 값을 받아오는 것에 대해 질문드리고 싶습니다.

#forms.py
TYPE_CHOICES = (
    ("아침", "아침"),
    ("브런치", "브런치"),
    ("점심", "점심"),
    ("저녁", "저녁"),
)

class DishMenuForm(forms.Form):
    date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}, format="%Y-%M-%d"),label='date')
    type = forms.ChoiceField(choices=TYPE_CHOICES, label='type')
    dish = forms.CharField(label='dish', max_length=10)

    def save(self, commit=True):
        menu = Menu(**self.cleaned_data)
        if commit:
            menu.save()
        return menu
#menu_form.html
{% extends 'layout.html' %}
{% load static %}
{% block content %}
<script src ="{% static 'js/menu.js' %}"></script>
<div class="container">
    <h5 class="my-3 border-bottom pb-2">메뉴 입력하기</h5>
    <form method="post">
        {% csrf_token %}
        <div id ="dishMenuForm">
        <div class="mb-3">
            <label for="date" class="form-label">날짜</label>
            <input type="date" class="form-control" name="date" id="date" width='50px'>
        </div>
        <div class="mb-3">
            <label for="breakfast" class="form-label">아침</label>
            <select name='type' id ='type' class='form-control'>
            <option value="">시간대를 정해주세요.</option>
            <option value='아침'>아침</option>
            <option value='점심'>점심</option>
            <option value='저녁'>저녁</option>
            <option value='브런치'>브런치</option>
            </select>
        </div>
        <div class="mb-3">
            <label for="dish" class="form-label">요리</label>
            <textarea class="form-control" name="dish[]"
                    id="dish" rows="1"></textarea>
        </div>
        <div class="mb-3">
            <label for="dish" class="form-label">요리</label>
            <textarea class="form-control" name="dish[]"
                    id="dish" rows="1"></textarea>
        </div>
        <div class="mb-3">
            <label for="dish" class="form-label">요리</label>
            <textarea class="form-control" name="dish[]"
                    id="dish" rows="1"></textarea>
                </div>
        </div>
        <input type='submit' value='입력' />
    </form>
</div>
{% endblock %}

Untitled (1)-21.jpg사진처럼 form.html 화면에서 dish의 form들을 동적으로 추가하여 저장하고 싶습니다.

템플릿 파일에서 dish의 name을 배열로 받아와 view 단에서 반복문을 사용하여 데이터를 저장할 수 있는지 궁금합니다. 성능을 위해 매번 데이터를 저장할때마다 dish 테이블에 이미 값이 있는지를 확인하고 저장해야하는 것인지, 데이터를 저장할때마다 분기를 돈다면 성능에 더 악영향을 미칠 것 같은데 어떤 방향으로 개발해야 하는지 궁금합니다. 이런 식의 방향이 맞는지 아니면 더 잘 쓰이는 방법이 있는지 알려주세요..

질문이 길고 장황하지만 답변 부탁드립니다.

django docker python react

답변 2

1

이진석

 

안녕하세요.

막연히 성능/비효율을 떠올리지 마시고, 그 성능/비효율을 어떻게 하면 측정할 수 있을까를 고민해보시는 것이 좋습니다.

데이터를 정규화하여 모델을 설계하시면 장고 모델과 폼의 혜택을 좀 더 누릴 수 있는 것이고,

CharField/TextField에 여러 데이터를 담게 되면 데이터를 직렬화하여 저장하는 것일테니, 저장하신 값들에 대해서는 직접 직렬화/역직렬화를 해주셔야하고, DB 조회시에도 인덱스 활용이 어려우실 수도 있습니다. 하지만 정규화하기 어려운 데이터일 경우 한 필드에 넣는 경우도 있습니다. // 모든 결정에는 Trade off가 있는 것이죠. 이와 유사한 역할로서 models.JSONField도 있습니다.

수많은 경우의 수가 존재하며, 모든 경우를 해결할 수 있는 단 하나의 정답이란 존재하지 않습니다. 구현해보시면서 끊임없는 고민을 통해 조금씩 나아갈 뿐인거죠.

좀 더 구체적으로 질문을 주셨으면 합니다. 막연히 <더 바람직한 것>을 알려주세요. 라고 질문주시면 답변드리기 많이 곤란합니다.

DishMenuForm이 forms.Form이던데 특별한 이유가 없으시다면 forms.ModelForm을 쓰시면 편리합니다. 다수의 dish 필드에 대해서 같은 이름으로 값을 넘겨주셨네요. 잘 하셨구요. 장고 뷰 단에서 request.GET, POST, FILES 에서는 .get 메서드 외에 .getlist 메서드를 지원해줍니다. .getlist 를 통해 같은 이름으로 전달된 다수의 값을 리스트로 조회할 수 있습니다.

다수의 dish 값을 순회시에, 각각의 dish 값에 대해서 get_or_create를 써보실 수도 있겠네요. 상황에 따라 다른 방법이 존재할 수도 있습니다.

정답은 없습니다.

화이팅입니다. :-)

0

gbch526

답변 감사합니다. 막막했는데 앞으로 갈 길이 조금씩 보이는 느낌입니다.

0

이진석

살펴보시고 다양한 질문 남겨주세요.

화이팅입니다. :-)

안녕하세요.

0

46

1

[OneToOne Field Demo] get_user_model() 메서드를 활용해야 하는 이유?

0

268

1

useEffect 훅에서 else 유무에 따른 결과

0

209

1

useAxios 훅의 dependency array 설정

0

242

1

useEffect에서 변수 업데이트 관련 질문

0

380

1

rest_framework.generics.CreateAPIView의 model 속성 유무

0

264

1

bootstrap4

0

466

4

리뉴얼 강의가 오픈이 되면 기존 강의는 더이상 못보는걸까요

1

358

1

admin form에서 앞선 필드 선택 후 다른 필드 select widget 구성하는 방법

0

570

3

useState는 필수일까요?

0

259

1

python manage.py makemigrations instagram 시 created_at default 오류가 발생합니다.

0

592

4

Django allauth를 사용한 소셜 로그인 시 에러

0

650

1

프로젝트명 변경 뒤, 디버그툴바+디버그모드 사용 시 에러

0

550

2

useLocalStorage() 함수 사용여부

0

224

1

django에 LOGIN_URL = '/accounts/login/'의 의미?

0

445

1

리듀서의 의미 재확인

0

425

1

simple-jwt Refresh Token 사용 노하우

0

895

2

docker compose 를 통한 배포 관련 오류 문의

0

667

1

파이썬 속도 장고 관련 궁금한게 있습니다.

0

360

1

is_like_user

0

230

1

related_name 오류

0

270

1

re_path 오류

0

255

1

re_path url

0

246

1

No post matches the given query

0

656

2