【问题标题】:Quiz sytem model Field selection测验系统模型 字段选择
【发布时间】:2017-01-29 08:53:04
【问题描述】:

我正在为 Django 中的测验系统创建一个模型。每个问题有一个问题和 5 个选项。

    class Question(models.Model):
      quiz_question=models.CharField(max_length=1000)
      option1=models.CharField(max_length=500)
      option2=models.CharField(max_length=500)  
      option3=models.CharField(max_length=500)
      option4=models.CharField(max_length=500)
      option5=models.CharField(max_length=500)

这里只有一个答案是正确的答案。这里代表答案的最佳方式是什么?是通过添加另一个字段还是可以通过编辑现有字段之一来完成?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    几个月前,我有一个基于 Question system 的类似 django 项目。 在您的情况下,我认为您需要创建一个新的Answer 模型,将ForeignKey 转换为Question 模型。

    这是我的models.py

    from django.db import models
    from django.contrib.auth.models import User
    from django.core.urlresolvers import reverse
    from django.db.models import (Q, Count, Sum)
    from django.utils.translation import ugettext, ugettext_lazy as _
    from django.utils.encoding import python_2_unicode_compatible
    
    
    class TimeStampedModel(models.Model):
        created = models.DateTimeField(auto_now_add=True)
        modified = models.DateTimeField(auto_now=True)
    
        class Meta:
            abstract = True
    
    
    class QuestionQuerySet(models.QuerySet):
    
        def published(self):
            return self.filter(publish=True)
    
    
    @python_2_unicode_compatible
    class Question(TimeStampedModel):
        title = models.CharField(max_length=200)
        TYPE_CHOICES = (
            ('short', _('Sort')),
            ('medium', _('Medium')),
            ('complete', _('Complete'))
        )
        type = models.CharField(
            max_length=200,
            choices=TYPE_CHOICES,
            default='short'
        )
        weight = models.PositiveIntegerField()
        publish = models.BooleanField(default=True)
        objects = QuestionQuerySet.as_manager()
    
        def __str__(self):
            return self.title
    
        @property
        def total_score(self):
            answer = Answer.objects.filter(
                question__pk=self.pk
            ).annotate(Sum('score'))
            return answer  # .count()
    
        def get_answers(self):
            return Answer.objects.filter(
                question__pk=self.pk
            )
        get_answers.allow_tags = True
    
        class Meta:
            verbose_name = _('Detail Question')
            verbose_name_plural = _('Questions')
            ordering = ['-created']
    
    
    @python_2_unicode_compatible
    class Answer(models.Model):
        question = models.ForeignKey(
            Question, related_name='question_answer'
        )
        answer = models.CharField(max_length=200)
        score = models.PositiveIntegerField()
    
    
    def key_generator():
        import uuid
        key = uuid.uuid4().hex
        if BaseAnswerUser.objects.filter(key=key).exists():
            return "{0}-{1}".format(key, uuid.uuid4().hex)
        return key
    
    
    @python_2_unicode_compatible
    class BaseAnswerUser(TimeStampedModel):
        """
        To save the answers that already answered by user.
        in this case, is such as session method.
        """
        user = models.ForeignKey(
            User, related_name='user_answer'
        )
        key = models.CharField(
            max_length=200,
            unique=True,
            default=key_generator
        )
    
        def get_absolute_url(self):
            return reverse('result', kwargs={'key': self.key})
    
        def get_answers(self):
            return AnswerUser.objects.filter(
                base_answer__key=self.key
            )
    
        def __str__(self):
            return _('Result analyze for %(user)s') % {
                'user': self.user.username,
            }
    
        class Meta:
            verbose_name = _('Base Answer User')
            verbose_name_plural = _('Base Answer Users')
            ordering = ['-created']
    
    
    @python_2_unicode_compatible
    class AnswerUser(TimeStampedModel):
        question = models.ForeignKey(
            Question, related_name='question_answer_user'
        )
        base_answer = models.ForeignKey(
            BaseAnswerUser, related_name='base_answer_user'
        )
        score = models.PositiveIntegerField(
            null=True, blank=True
        )
        text_answer = models.TextField(
            null=True, blank=True
        )
    
        @property
        def weight(self):
            return self.question.weight
    
        def __str__(self):
            return _('Result for %(question)s') % {
                'question': self.question
            }
    
        class Meta:
            verbose_name = _('Detail User Answer')
            verbose_name_plural = _('User Answers')
            ordering = ['-created']
    

    为了处理仪表板 django admin 中的答案,我使用了admin.TabularInline。更多信息,您可以通过gist 结帐

    另请参阅如何处理Django multiple input field values with same name

    希望对您有所帮助..


    更新

    我之前的回答是针对动态回答系统,举例:

    1. 问题 A (有 4 个选项答案)

      • a)。选项答案A
      • b)。选项答案 B
      • c)。选项答案C
      • d)。选项答案D
    2. 问题 B (有 3 个选项答案)

      • a)。选项答案A
      • b)。选项答案 B
      • c)。选项答案C

    如果您实施 Static Answers 系统,据我所知:

    会话回答用户表示为我之前回答的基本回答用户

    [ Question ] -------------------+
     - title       (chr)            |
     - description (chr)            |
     - weight      (int)            |
        |                           |
        |                           |
        |                           |
       \./                         \./
     [ Answer ]               [ Answer User ]
     - fk_question (int)      - fk_question       (int)
     - option_a    (chr)      - fk_session_answer (int)
     - scroe_a     (int)      - score             (int) # save the final score
     - option_b    (chr)           /'\
     - score_b     (int)            |
                                    |
                                    |
                                    |
                          [ Session Answer User ]
                              - fk_user      (int)
                              - session_key  (char:unique)
                              - created      (date)
                                    |
                                    |
                                   \./
                              [ User Model ]
                                - username    (chr)
                                - date_joined (date)
    

    查询集怎么样?

    我想查找特定用户和特定会话的总分的示例。

    >>>
    >>> session = get_object_or_404(SessionAnswerUser, user=request.user, session_key='key-key-key')
    >>> answered_questions = AnswerUser.objects.filter(session_answer=session)
    >>>
    >>> # Find total scores. eg: {'score__sum': 15}
    >>> answered_questions.aggregate(Sum('score'))['score__sum']
    15
    >>>
    

    如何以及何时使用session_key

    用户回答完所有问题后(创建模式),然后重定向到结果页面。一个例子:

    @login_required
    def save_answers(request):
        """
        This view isn't using django forms, 
        but only handling at the templates and this view.
        Because until now I don't know how to handle it.
        """
        if request.method == 'POST':
            # retrieve all id/pk's from the `questions` (model:Question)
            questions = request.POST.getlist('question')
    
            # retrieve all id/pk's from the `answers`. (model:Answer)
            answers = [request.POST['answer-{}'.format(q)] for q in questions]
    
            # saving the session with `key_generator()`, see my previous answer.
            session = SessionAnswerUser.objects.create(user=request.user)
            session.save()
    
            # Makesure the length of `questions` is same with length of `answers`
            # 1 answer for 1 question
            if len(questions) == len(answers):
                for n in range(len(questions)):
                    dict_answer = {
                        'question': Question.objects.get(pk=questions[n]),
                        'session': session, # from latest session above
                        'score': answers[n]
                    }
                    answered_questions = AnswerUser.objects.create(**dict_answer)
                    answered_questions.save()
    
                # redirecting to the result page.
                return redirect('/result/page', key=session.session_key)
    
            else:
                # length of `questions` is not same with length of `answers`
                # do stuff...
    
    
    @login_required
    def result_page(request, key):
        session = get_object_or_404(SessionAnswerUser, session_key=key)
        answered_questions = AnswerUser.objects.filter(session=session)
    
        # I hope you already know how to use the django queryset.
        # eg:
        # >>> session.user
        # <User: john smith>
        # >>> 
        # >>> answered_questions
        # <QuerySet: [<AnswerUser: foobar lorem>, <AnswerUser: xxxx>]>
        # >>> 
        # >>> answered_questions.first()
        # <AnswerUser: foobar lorem>
        # >>> answered_questions.first().score
        # 3
    
        ...
        # your context goes here..
    

    【讨论】:

    • 为什么我不需要在这里创建另一个表。我认为这是一种浪费
    • 以前,你需要保存他们的答案吗?
    • 是的,我想保存答案。但是无论如何,是否有显示该选项与问题之间的关系
    • 我也不是数据库模型方面的专家
    • 您的选项字段是静态的还是动态的?
    猜你喜欢
    • 1970-01-01
    • 2018-07-05
    • 2014-08-17
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多