tasddc1226 / survey-management

설문지들을 관리할 수 있는 설문지 관리 웹서비스 입니다.
0 stars 0 forks source link

#1 answer_type이 CheckboxSelectMultiple인 경우 DB에 적재하는 방법? #1

Open tasddc1226 opened 2 years ago

tasddc1226 commented 2 years ago
## models.py

class Survey(models.Model):
    """설문지는 관리자에 의해 생성"""

    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    is_active = models.BooleanField(default=False)
    created_at = models.DateTimeField(default=timezone.now)

    class Meta:
        db_table = "survey"

class Question(models.Model):
    """
    하나의 설문지에 여러 질문이 존재
    질문의 유형(type)은  Radio(1개), Checkbox(1개 이상), Select(1개) 중 하나
    """

    RADIOBUTTON = 1
    MULTIPLE = 2
    SELECT = 3
    TYPES_CHOICES = [
        (RADIOBUTTON, "RadioButton"),
        (MULTIPLE, "CheckBox"),
        (SELECT, "Select"),
    ]
    survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
    question_text = models.CharField(max_length=100)
    answer_type = models.IntegerField(
        choices=TYPES_CHOICES, default=RADIOBUTTON, max_length=32
    )

    class Meta:
        db_table = "question"

class Choice(models.Model):
    """
    하나의 질문에는 여러 보기가 존재
    """

    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=100)

    class Meta:
        db_table = "choice"

class Submission(models.Model):
    """특정 설문지 질문들에 대한 답변 집합"""

    survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
    created_at = models.DateTimeField(default=timezone.now)
    is_complete = models.BooleanField(default=False)

    class Meta:
        db_table = "submission"

class Answer(models.Model):
    """특정 질문에 대한 답변"""

    submission = models.ForeignKey(Submission, on_delete=models.CASCADE)
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE)

    class Meta:
        db_table = "answer"
## forms.py의 AnswerForm class
if type == 1:
    choice_field = forms.ChoiceField(
        choices=lists, widget=forms.RadioSelect, required=True
    )
elif type == 2:
    choice_field = forms.ChoiceField(
        choices=lists,
        widget=forms.CheckboxSelectMultiple,
        required=True,
    )
elif type == 3:
    choice_field = forms.ChoiceField(
        choices=lists, widget=forms.Select, required=True
    )
mysql> select * from answer;
+----+-----------+---------------+
| id | choice_id | submission_id |
+----+-----------+---------------+
|  2 |        93 |             7 |
|  3 |        97 |             7 |
|  4 |        71 |             8 |
|  5 |        73 |             8 |
|  6 |        80 |             8 |
+----+-----------+---------------+
5 rows in set (0.00 sec)

Screen Shot 2022-06-08 at 17 19 34

tasddc1226 commented 2 years ago

이슈 해결 방법

if request.method == "POST":
        total_questions = int(request.POST.get("form-TOTAL_FORMS"))
        for i in range(0, total_questions):
            answers = request.POST.getlist(f"form-{i}-choice")
            if len(answers) > 1:
                with transaction.atomic():
                    for choice_id in answers:
                        Answer.objects.create(
                            choice_id=choice_id, submission_id=sub_pk
                        )
            else:
                with transaction.atomic():
                    Answer.objects.create(
                        choice_id=answers[0], submission_id=sub_pk
                    )
        sub.is_complete = True
        sub.save()

        return redirect("survey-thanks", pk=survey_pk)

form을 활용한 is_vaild 함수를 사용하지 않고 직관적이진 않지만 POST로 넘어온 모든 항목들에 대하여 응답 값이 복수개 즉, 1개 이상이라면 Checkbox에 대한 복수 응답이라고 판단하여 list의 요소를 순회하면서 값을 저장하도록 하였다.