Django Multiple Choice questions with Answers linked to users

407 views
Skip to first unread message

Giles german

unread,
Feb 22, 2018, 11:32:31 AM2/22/18
to Django users

Dear all I am wondering if you can help me??

I have a list of questions with a list of multiple choice answers. 

I am trying to get details of a user who will then answer the questions and store their answers next to their name. The questions/answers may change moving forward. 

I have the following code is this correct can you help please?

  from django.db import models

class Investor(models.Model):
    Investor = models.CharField(max_length=100, default="")

    def __str__(self):
        return self.Investor

class Question(models.Model):
    Question_text = models.TextField(max_length=200,default="")

    def __str__(self):
        return self.Question_text

class Option(models.Model):
    Question = models.ForeignKey(Question, on_delete=models.CASCADE)
    Option = models.CharField(max_length=50, default="")

    def __str__(self):
        return self.Option

class Answer(models.Model):
    Investor = models.ForeignKey(Investor, on_delete=models.CASCADE, default="")
    Question = models.OneToOneField(
        Question,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    Answer = models.OneToOneField(
        Option,
        on_delete=models.CASCADE,
        primary_key=True,
    )

Mike Dewhirst

unread,
Feb 23, 2018, 12:31:15 AM2/23/18
to django...@googlegroups.com
On 23/02/2018 2:56 AM, 'Giles german' via Django users wrote:
>
> Dear all I am wondering if you can help me??

I haven't looked too closely at your code but there are a couple of
things I would do differently.

1. I don't use Caps for field names. Too easy to confuse myself with
identical class names. The convention is to use all lower case with
underscores for field names and related names.

2. Your Answer model has a foreign key to Investor. Having an attribute
default="" is odd. If you are trying to say that an Answer can exist
without an Investor then you really need null-True. But I don't think
you are, An Answer is presumably created in response to a Question by a
user. Presumably that is the Investor in which case you don't need
null=True either.

3. You are using primary_key=True in places which I don't understand.
That option is for when you supply your own primary key field in a
model. Needing to do so is very rare and almost always related to legacy
systems. Otherwise you are always much better leaving the PK to Django
and control uniqueness via the Meta class option unique_together = [list
of fields].

I can't easily reconcile your Question, Option, Answer arrangement.

I have recently written a small question and answer app for online
training and that is very simple. It has a custom user as a student
where you have Investor and you can see that in my Answer model below.

Another difference is my students can have many Answers so that means a
FK. If there needs to be one Answer per user, I'm not sure whether I
would use a OneToOneField or a ForeignKey with unique_together = [ fk,
fk] where fk in my case below is unique_together = ['question',
'student']. I do that because I think it is more explicit and I use
get_or_create to retrieve or create the Answer record for that
question+student. If for example the requirement was to retain sets of
answers for each student for historical purposes I would have a
different arrangement.

Somewhat stripped down it goes ...

class Course(models.Model):
name = models.CharField(
verbose_name='course name',
max_length = LARGE,
)
def __str__(self):
return self.name

class Instruction(models.Model):
course = models.ForeignKey(
Course,
on_delete=models.CASCADE,
related_name='course_instruction'
)
sequence = models.CharField(
verbose_name='Instruction sequence',
max_length=SMALL,
default='1',
blank=True,
)
num_sequence = models.FloatField(
# see self.save() and Meta order_by
default=0,
blank=True,
)
topic = models.CharField(
verbose_name='topic',
max_length = LARGE,
default='',
)
item = models.CharField(
verbose_name='item',
max_length = LARGE,
default='',
blank=True,
)
instruction = HTMLField(
verbose_name='instruction',
default='',
blank=True,
)
class Meta:
verbose_name = 'instruction'
verbose_name_plural = 'instruction'
ordering = ['num_sequence']
unique_together = ['course', 'topic', 'item']

def __str__(self):
coursename = '{0}'.format(self.course)
item = self.item or ' '
return ' '.join(
[coursename, '-', self.sequence, '-', self.topic, item ]
).strip()


class Question(models.Model):
instruction = models.ForeignKey(
Instruction,
on_delete=models.CASCADE,
related_name='instruction_question'
)
sequence = models.CharField(
verbose_name='Question number',
max_length=SMALL,
default='1',
blank=True,
)
num_sequence = models.FloatField(
# see self.save() and Meta order_by
default=0,
blank=True,
)
question_detail = HTMLField(
verbose_name='question',
default='',
blank=True,
)
answer = models.CharField(
max_length=MEDIUM,
verbose_name='Single answer',
default='',
blank=True,
)
score = models.IntegerField(
verbose_name='score',
default=1,
blank=True,
help_text='Relative value for a correct answer to this question (or '
'these questions).',
)

class Meta:
verbose_name = 'question'
verbose_name_plural = 'questions'
ordering = ['num_sequence']
unique_together = ['instruction', 'sequence']

def __str__(self):
""" Instruction record display name + 'Q' + sequence """
return '{0} Q{1}'.format(self.instruction, self.sequence)


class Answer(models.Model):
question = models.ForeignKey(
Question,
on_delete=models.CASCADE,
related_name='question_answer'
)
student = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='student_answer'
)
answer = models.CharField(
max_length=MEDIUM,
verbose_name='answer',
default='',
blank=True,
)
score = models.IntegerField(
verbose_name='score',
default=0,
blank=True,
help_text='Value copied from self.question.score if answer(s) match',
)

class Meta:
verbose_name = 'answer'
verbose_name_plural = 'answers'
unique_together = ['question', 'student']

def __str__(self):
return '{0}'.format(self.question).replace(' Q', ' A')

I don't know whether this will help in your scenario but I hope so.
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com
> <mailto:django-users...@googlegroups.com>.
> To post to this group, send email to django...@googlegroups.com
> <mailto:django...@googlegroups.com>.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/5878156e-4726-4bb2-b857-9baa31e53cdb%40googlegroups.com
> <https://groups.google.com/d/msgid/django-users/5878156e-4726-4bb2-b857-9baa31e53cdb%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages