Django form for model referenced by foreign keys - python

I am creating a quiz application in django. As of right now, I have two models, Question and Answer.
class Question(models.Model):
question_text = models.CharField(max_length=255)
video_ref = models.ForeignKey('Video')
class Answer(models.Model):
question_ref = models.ForeignKey('Question')
answer_text = models.CharField(max_length=255)
correct = models.BooleanField()
This setup allows me to have variable numbers of potential answers to every question with a possibility of multiple correct answers.
I want to create a form model for a Question such that every Answer that points to the Question is part of the form. How can this be done?

You can do as follow:
forms.py
class QuestionForm(forms.ModelForm):
answers = forms.ModelMultipleChoiceField(queryset=Question.answer_set.all(), widget=forms.CheckboxSelectMultiple)
class Meta:
model = Question
Using forms.ModelMultipleChoiceField and the widget forms.CheckboxSelectMultiple django will render the form with checkbox for you.

Related

How Can I Associate A Foreign Key Of A Django Class Model Field To A Parent's Class Field

I am creating a question and answer django model where i want to set the correct answer to an option on the same class
Essentially I Want To Do Something Like This
class Question(models.Model):
question = models.CharField(max_length=40)
options = models.ManyToManyField('Answer')
correct_answer = models.ForeignKey('self.options',on_delete=models.CASCADE)
Unfortunately I'm Getting Errors From Django.
Why don't you just point the foreign key to the same model? Like this:
class Question(models.Model):
question = models.CharField(max_length=40)
options = models.ManyToManyField('Answer')
correct_answer = models.ForeignKey('Answer',on_delete=models.CASCADE)

Is it possible to have two ManyToMany relationships to the same model on the same admin page?

I modelling a quiz and the associated questions as follows:
# models
class Question(models.Model):
title = models.TextField()
category = models.TextField()
class Quiz(models.Model):
questions = models.ManyToManyField(Question, through='OrderedQuestion')
class OrderedQuestion(models.Model):
# A through table to allow ordering of questions
question = models.ForeignKey(Question, ...)
quiz = models.ForeignKey(Quiz, ...)
order = models.PositiveIntegerField(default=0)
I have two types of questions that are handled by proxy models:
# proxy models to handle specific question categories
class BoatQuestion(Question):
objects = BoatQuestionManager() # handles setting category
class Meta:
proxy = True
and a similar one for CarQuestion.
I want to be able to edit BoatQuestions and CarQuestions independently from each other but on the same admin page. The admin setup is:
class BoatQuestionInline(admin.TabularInline):
model = BoatQuestion.quiz.through
class CarQuestionInline(admin.TabularInline):
model = CarQuestion.quiz.through
class QuizAdmin(admin.ModelAdmin):
model = Quiz
inlines = (BoatQuestionInline, CarQuestionInline)
but whenever I change the questions in the boat question section, the questions in the car section update to match it and vice versa.
Is there any way to show these on the same admin page but change them independently?
The problem lies in your inlines. You use the same model for both, which is fine. But as you want to show only certain Questions, you have to adjust the QuerySet for each inline and add an appropriate .filter(). (I am guessing here, how you distinguish the category of the questions.)
class BoatQuestionInline(admin.TabularInline):
model = BoatQuestion.quiz.through
def get_queryset(self, *args, **kwargs):
return OrderedQuestion.objects.filter(question__category='boat')
class CarQuestionInline(admin.TabularInline):
model = CarQuestion.quiz.through
def get_queryset(self, *args, **kwargs):
return OrderedQuestion.objects.filter(question__category='car')

Counting Boolean Values in field of Child Model in Django QuerySet API

I have the following model (below).
I would like a query that returns every record of parent Question(models.Model), where ALL the values for the is_relevant field within the child Choice(models.Model) are "True".
Having a difficult time creating the QuerySet. Any Assistance would be very helpful.
model.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
is_relevant = models.BooleanField()
You can use the reverse relationship of the Question model like so:
Question.objects.filter(choice__is_relevant=True)
The choice in choice__is_relevant is the lowercase name of the model Choice.
Reference: Relationship lookups

How do I restrict foreign keys choices to related objects only in django?

How to reduce the foreign key data to a subset related to current object? For example:
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
# Not correct, it display the choices of all questions on not only
# the choices of the current question
answer = models.ForeignKey('Choice', related_name='question_related_choices')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
The answer field should contain only the choices of the related question and not the choices of all question.
I tried to use limit_choice_to of django without success. I think this is the best way to solve the problem to select a single correct choice for each section.
I also thought about using a field in Choice model, and display it as a radio button.. but I don't know how to achieve this. Thanks for the support.
I found a similar problem but I'm not able to figure out that solution, even because it use threads and so on... How do I restrict foreign keys choices to related objects only in django
Edit 1:
I'm still struggling with this problem, but probably I found the right direction. I found this discussion: https://stackoverflow.com/a/4656296/2653437 and the last answer seems the right one:"This limiting of choices to current user is a kind of validation that needs to happen dynamically in the request cycle, not in the static Model definition." Using threadlocals middleware to store data probably is not the right approach to this problem, instead, limiting the choices in the form seems more simple and clear.
If I figured out well, as show here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.form django admin, allow to specify a custom modelform. By default django admin use the ModelForm, M --> F, but to limiting the choice we can inherit from and add/edit custom fields: M --> CMF -- F
forms.py
class AnswerForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(Question, self).__init__(*args, **kwargs)
self.fields['answer'].queryset = Choice.objects.filter(question__choice=self)
class Meta:
fields = '__all__'
model = Question
admin.py
class QuestionAdmin(admin.ModelAdmin):
form = AnswerForm
list_display = ('question_text', 'pub_date', 'was_published_recently')
fieldsets = [
(None, {'fields': ['question_text']}),
(None, {'fields': ['answer']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
But the problem is still to get the instance of question to filtering/query the choice. Currently I get the following error:
TypeError: super(type, obj): obj must be an instance or subtype of type
[15/Aug/2016 11:50:34] "GET /admin/polls/question/3/change/ HTTP/1.1" 500 1260
Any suggestion/advice or a correct answer will be highly appreciated
Edit 2:
From the traceback I saw there's the key 'instance' in kwargs. This is the key because with it you can limit the choices only to related question with:
self.fields['answer'].queryset = Choice.objects.filter(question=kwargs['instance'])

Setting up default ForeignKey in django models

I need to set up default Foreign Key for a model at the model declaration stage (in models.py). I use the following code:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return str(self.pub_date)
def create_question():
q=Question(question_text='default text', pub_date=datetime.now())
q.save()
return q.id
class Choice(models.Model):
question = models.ForeignKey(Question, default=lambda: create_question())
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
This works fine, the Choice instance and associated Question instance are created... But saving of Choice instance leads to creation of two additional (useless) Question instances. It seems like that default-lambda is called several times during Choice instance saving. I don't need these additional Question instances. How to avoid their creation?
NOTE: In python-shell everything works well:
c=Choice(votes=5, choice_text='dim')
c.save()
creates one instance of Choice and one associated instance of Question. Only using admin save button leads to extra Question instances creation!

Categories