Django测验应用程序,REST,如何设计模型?

问题描述 投票:0回答:2

我正在构建django测验应用程序,并且所有数据(问题/答案)应可通过REST服务获得。我将为此使用好吃的东西。

我在脑子里想到了完美的结果JSON,它看起来像(带有答案的单个问题):

{
    "level": 1,
    "question": "Example question",
    "choices":[
        {
            "content":"Example answer 1",
            "valid": true
        },
        {
            "content":"Example answer 2",
            "valid": false
        },
        {
            "content":"Example answer 3",
            "valid": false
        },
        {
            "content":"Example answer 4",
            "valid": false
        }
    ]
},

单个问题将始终仅包含4个答案,其中一个或多个有效。

我不确定如何为这种模式设计Django模型。

我是否应该使用问题外键创建“答案”模型?在这种情况下,也许其他解决方案会更好?如果是这样,我如何使用django admin / web表单轻松添加新问题?

有什么想法或建议吗?

django django-models django-forms tastypie
2个回答
3
投票

我过去使用的模型结构如下:

class Questionnaire(models.Model):
    version = models.CharField()

class Question(models.Model):
    questionnaire = models.ForeignKey(Questionnaire)
    text = models.CharField()

class QuestionAnswer(models.Model):
    question = models.ForeignKey(Question)
    text = models.CharField()
    is_valid = models.BooleanField()

class UserAnswer(models.Model):
    answer = models.ForeignKey(QuestionAnswer)

此解决方案将允许您设计多个问卷/测验,每个问卷/测验将具有可变数量的问题。然后,每个问题将具有可变数量的答案,您可以选择有效的数量。

这种设计的最大问题是,它实际上不利于部分问卷/测验的完成。如果那是个大问题,则可以如下调整UserAnswer类:

class UserQuestionnaire(models.Model):
    questionnaire = models.ForeignKey(Questionnaire)
    completed = models.BooleanField()

class UserAnswer(models.Model):
    answer = models.ForeignKey(QuestionAnswer)
    user_questionnaire = models.ForeignKey(UserQuestionnaire)

这会稍微破坏规范化,但可以让您设置接受者是否完成的设置标志。

希望这可以帮助您入门!


0
投票

我看过有关Medium的很好的教程。https://medium.com/@nsjcorps/create-a-quiz-application-with-django-rest-framework-react-redux-part-one-f0fcae5103fd,但通常应该看起来像这样。

from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
class Quiz(models.Model):
 name = models.CharField(max_length=1000)
 questions_count = models.IntegerField(default=0)
 description = models.CharField(max_length=70)
 created = models.DateTimeField(auto_now_add=True,null=True,blank=True)
 slug = models.SlugField()
 roll_out = models.BooleanField(default=False)
class Meta:
 ordering = [‘created’,]
 verbose_name_plural =”Quizzes”
def __str__(self):
 return self.name
class Question(models.Model):
 quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
 label = models.CharField(max_length=1000)
 order = models.IntegerField(default=0)
def __str__(self):
 return self.label
class Answer(models.Model):
 question = models.ForeignKey(Question, on_delete=models.CASCADE)
 text = models.CharField(max_length=1000)
 is_correct = models.BooleanField(default=False)
def __str__(self):
 return self.text
class QuizTakers(models.Model):
 user = models.ForeignKey(User, on_delete=models.CASCADE)
 quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
 correct_answers = models.IntegerField(default=0)
 completed = models.BooleanField(default=False)
 timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
 return self.user.username
class Response(models.Model):
 quiztaker = models.ForeignKey(QuizTakers, on_delete=models.CASCADE)
 question = models.ForeignKey(Question, on_delete=models.CASCADE)
 answer = models.ForeignKey(Answer,on_delete=models.CASCADE,null=True,blank=True)
def __str__(self):
 return self.question.label
@receiver(post_save, sender=Quiz)
def set_default_quiz(sender, instance, created,**kwargs):
 quiz = Quiz.objects.filter(id = instance.id)
 quiz.update(questions_count=instance.question_set.filter(quiz=instance.pk).count())
@receiver(post_save, sender=Question)
def set_default(sender, instance, created,**kwargs):
 quiz = Quiz.objects.filter(id = instance.quiz.id)
 quiz.update(questions_count=instance.quiz.question_set.filter(quiz=instance.quiz.pk).count())
@receiver(pre_save, sender=Quiz)
def slugify_title(sender, instance, *args, **kwargs):
 instance.slug = slugify(instance.name)```
© www.soinside.com 2019 - 2024. All rights reserved.