Ordering by a field in reverse side foreign key in Django - django

I have the following models
class Question(models.Model):
content=models.TextField()
...
class Answer(models.Model):
created_at = models.DatetimeField(auto_add=True)
author = models.ForeignKey(User, ... )
content = models.TextField()
question = models.ForeignKey(Question, ....)
...
class meta:
unique_together=('author','question')
in the database I have a set of questions and answers. answers are linked to their authors.
unique_together ensures the user can give an answer only once to a question.
usr_1 Is a user instance that has answers to some questions that I can retrieve by:
qst_qs=Question.objects.filter(answer__author=usr_1)
I want to sort questions in qst_qs according to the created_at field in usr_1's answer in each question.
Thanks in advance.

Please try this code:
qst_qs=Question.objects.filter(answer__author=usr_1).order_by('answer__created_at')

Related

how to make primay or unique three field in django models?

I have the four models in my Django models.py ( User, Exam, Questions, Answers )
the Answer model has four fields ( user, exam, question, answer)
after creating an exam and creating questions for that, the users come to take an exam
I want to store the user's answers in the Answer model, therefore, I specify which user is taking which exam and answering which question, at the end I save the user's answers in the last field ( the 'answer' field in Answer modle )
but I want this user only once can answer this question in this exam, so I want to make these fields ( user, exam, question ) primary in the Answer model that
my Answer model:
class Answer(models.Model):
exam = models.ForeignKey(Exam, on_delete=models.CASCADE, default=None)
user = models.ForeignKey(User, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.CharField(max_length=8)
I don't know how to do this action to primary three field
actually, there is no matter whether the two or one fields of these three fields are similar, I just want to prevent storing records that user, exam, and question fields are already stored
for example, I have this record in my database:
user:1, exam:52, question:38, answer: "option_a"
when I want to store the following record I expect to get an error:
user:1, exam:52, question:38, answer:"option_b"
but this record is ok:
user:1, exam:52, question:60, answer:"option_c"
Django want only one field as primary key.
The solution in your case is to use unique_together for your three fields:
class Answer(models.Model):
exam = models.ForeignKey(Exam, on_delete=models.CASCADE, default=None)
user = models.ForeignKey(User, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.CharField(max_length=8)
class Meta:
unique_together = ['user', 'exam', 'question']
Documentation about unique_together option: https://docs.djangoproject.com/fr/4.1/ref/models/options/#unique-together

How to apply condition in boolean field in django rest framework?

I am working on a blog type website.
where students will ask question and teacher will answer it.
I put two user role
Teacher and student
class User(AbstractBaseUser, PermissionsMixin):
USER_TYPE = (
('None', 'None'),
('Student', 'Student'),
('Teacher', 'Teacher'),
)
user_type = models.CharField(choices=USER_TYPE, default='Student', max_length=50)
This is the user model where the role is defined.
Post model for submitting the question and Comment model for answering it.
In the Post model I put on field is_answered and as default put it False
class add_question(models.Model):
created_by = models.ForeignKey(User, blank=False, on_delete=models.CASCADE)
is_answered = models.BooleanField(default=False)
And the answer model [which is comment one] is referred to as the foreign key of the question
class submit_answer(models.Model):
question_id = models.ForeignKey(
add_question, blank=False, on_delete=models.CASCADE)
created_by = models.ForeignKey(User, blank=False, on_delete=models.CASCADE)
Both question and answer model contains created_by field and ForeignKey of User and answer model contains another ForeignKey of question.
so I need when the teacher role will put a comment the is_answered Field in add_question model should turn as true.
as student also can comment on his/er question so I need on condition to apply.
I am using serializer as I need API of this
So, should I modify on my views.py or serializers.py and how should I do that!
It would be great help if someone guide me how to do it?
Thanks and let me know if any other information needed.
The best practice would be adding such codition in save() method of models.Model. You should name your Model classes differently, like Question and Answer, because after creating, if you want to edit or something, it would be weird if you have to search for submit_answer, right? And as #wjh18 said, use CamelCase in classes.
Also question_id is usually bad idea, better think of question, because it will lead directly to the whole object, not its id.
class Answer(models.Model):
question = models.ForeignKey(Question, blank=False, on_delete=models.CASCADE)
created_by = models.ForeignKey(User, blank=False, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
if self.created_by.user_type == 'Teacher' and not self.question.is_answered:
self.question.is_answered = True
self.question.save()
super().save(*args, **kwargs)

QuerySets are lazy in template

I am working on one question and answer website.I think i have mess with code.I am sending querysets all objects when only one needed.
Like sending all answer of one question when only one needed.
I print only one.
So at that time will it affect database's all record or only record which i will print in template?
View.py
questions = Question.objects.all()
context = {
'questions':questions
}
return render(request,'index.html',context=context)
template_tag.py
#register.simple_tag
def getmostvotedanswer(answers):
answer = answers.order_by('-vote')[0]
return answer.answer
index.html
<p>{% getmostvotedanswer question.answer_set.all %}</p>
In this i am sending all answers but only needed so will it affect database's performance?
Question Model
class Question(models.Model):
question = models.CharField(max_length=400)
uid = models.ForeignKey("User",on_delete=models.SET_DEFAULT,default=1,related_name='user_q_id_set')
vote = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
catitle = models.ForeignKey("Category", on_delete=models.CASCADE)
editUser = models.ManyToManyField("User",related_name='user_q_edit_set',null=True,blank=True)
Answer Model
class Answer(models.Model):
answer = models.TextField()
qid = models.ManyToManyField("Question")
uid = models.ForeignKey("User",on_delete=models.CASCADE,related_name='user_a_id_set')
vote = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
editUser = models.ManyToManyField("User",related_name='user_a_edit_set',null=True,blank=True)
In your templates, you are iterating through questions, passing all the answers to your custom template tag and find the one with the most vote.
If that's what you want, you can simply put ordering into your answers model like this:
class Answer(models.Model):
vote = models.IntegerField(default=0)
# ...
class Meta:
ordering = ['-vote']
This way, when you call question.answer_set, it will automatically sort the answers by the vote field.
So you can say question.answer_set.first to get the top voted answer.

Select users with common answers to questions

I have four models and a CustomUser table.
class Profile(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
class Question(models.Model):
question = models.CharField(max_length=140)
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
answer = models.CharField(max_length=70)
class Response(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='responses')
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.ForeignKey(Answer, on_delete=models.CASCADE)
Each question has multiple answers but each user can only pick one answer to each question.
Each user can answer multiple questions.
How do I select a list of users with a nested list of their common answers to a reference user with just the ORM?
I can think of a hacky solution of retrieving the list of common answers and then a python loop to increment the count for each user but I would like to confine it to the ORM as I need to append this to a parent serializer (UserSerializer -> ResponseSerializer).
We can use a Prefetch object here, like:
from django.db.models import Prefetch
user_answers = Answer.objects.filter(response__user=reference_user)
CustomUser.objects.prefetch_related(
Prefetch(
'response_set',
queryset=Response.objects.filter(answer__in=user_answers),
to_attr='common_answers'
)
)
Now the CustomUsers that arise from this queryset, will have an extra attribute common_answers with Response objects that will contain Responses with an Answer that they share with reference_user.
If you are only looking for users that have at least one common answer with reference_user, you can filter out the others with:
CustomUser.objects.filter(
response__answer__response__user=reference_user
).prefetch_related(
Prefetch(
'response_set',
queryset=Response.objects.filter(answer__in=user_answers),
to_attr='common_answers'
)
).distinct()

Working with multiple forms on a single page in Django

I'm new to Django and I'm having a hard time wrapping my head around how to deal with "nested" forms in a template and how to process those forms accordingly. I'm creating a polling application similar to the tutorial, but more complex. I have multiple models (Poll, Question, Choice, Vote). A poll contains many questions, a question contains many choices.
I want to allow a user to view all the questions in a poll at once and vote on each question by selecting a choice from each question's choice set. After the user selects a choice for each question, they submit all their votes at once and process them to create the vote objects.
I'm really scratching my head at how to do this. Any help would be greatly appreciated.
Here are how my models are set up:
models.py
class Poll(models.Model):
name = models.CharField(max_length=255, default="Unnamed Poll")
key = models.CharField(max_length=16, blank=True, editable=False, unique=True, db_index=True, null=True)
instructor = models.ForeignKey(User)
course = models.ForeignKey(Course)
active = models.BooleanField(default=False)
anonymous = models.BooleanField(default=True, help_text="Allow votes to be anonymous?")
class Question(models.Model):
question_text = models.CharField(max_length=255, verbose_name='Poll Question')
poll = models.ForeignKey(Poll)
class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=255, verbose_name='Response Choice')
class Vote(models.Model):
question = models.ForeignKey(Question)
choice = models.ForeignKey(Choice)
student = models.ForeignKey(User)
You should use django.forms.Formsets in your case.Read about formsets here
Please comment to ask for further clarifications.
cheers :-)