测验系统模型字段选择

时间:2017-01-29 08:53:05

标签: python django django-models

我正在为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)

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

1 个答案:

答案 0 :(得分:1)

几个月前,我有类似于基于问题系统的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
  3. 如果您实施 静态答案 系统,据我所知:

      

    会话答疑用户 在我之前的回答中表示为 基本答案用户 ;

    [ 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..