How can i use loop to create list of fields - python

Recently, I start project using django 3 I face the problem with model
I want to create the modelform and the field is a list:
Like answer1, answer2, ..., answer10,...
class Quiz(models.Model):
question = models.CharField(max_length=30)
def __str__(self):
return self.question
quiz = Quiz.objects.all()
class Answer(models.Model):
answer1 = models.CharField(max_length=20)
answer2 = models.CharField(max_length=20)
answer3 = models.CharField(max_length=20)
...
answer10 = models.CharField(max_length=20)
...
How I use loop or something to declare this answer field?
Can I set my table column name of
answer1 = quiz[0].question

Not sure what database you are using, but you could use ArrayField if you are using PostreSQL instead of creating many similar columns.
https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/

Related

Django ORM queries

I've these tables:
class ContestQuestions(models.Model):
contest = models.ForeignKey(Contest, on_delete=models.CASCADE,
related_name='contest_question_contest')
quetions = models.ForeignKey(Question, on_delete=models.CASCADE,
related_name='contest_question_questions')
class UserResponse(models.Model):
user = models.ForeignKey(User, on_deleted=models.CASCADE, related_name='user_response')
response = models.ForeignKey(Answer, on_delete=models.CASCADE,
related_name='user_answer')
Other related tables I've:
class Contest(models.Model):
name = charfield
date = charfield
is_active = bool
class Question(models.Model):
title = charfield
created_at = datetimefield
class Answer(models.Model):
question = FK(Question)
answer = charfield #4 options of 1 question
is_true = bool
I need to get some stat about every quiz. So from every quiz, I want to know the top 5 most correctky answered questions and most incorrectly answered questions and total number of people who attempted that question.
How can I write a query for it?
I would add a method to your Contest model so that you can access this data like so:
class Contest(models.Model):
...
def top_answered_questions(self, correct=True):
return Questions.objects.filter(
contest_question_questions__contest=self
).annotate(
correct_answers=Count('answer', filter=Q(answer__is_true=correct))
).order_by(correct_answers)
You can then call contest.top_answered_questions()[:5] and change the correct parameter to get correctly and incorrectly answered questions.

What's the best way to implement django models for multiple choice against multiple strings

I'm working on a project using Django(2.2) and Python(3.7) in which I have to implement models for a specific scenrio:
I have a Vote in which we have five questions like:
DELIVERING VALUE
EASY TO RELEASE
FUN
HEALTH OF CODEBASE
TEAMWORK
and each of these questions has options in the form of dropdown as:
-- Select --
--helpful--
--not helpful--
--disaster--
and all of these votes will belong to a group and later I need to perform some aggregations to get the total no of votes for of these options (like helpful) against each question (like DELIVERING VALUE).
Here's how currently I have implemented this scenario in Django models:
From models.py:
class UserGroup(models.Model):
email = models.EmailField(primary_key=True)
group = models.CharField(max_length=250, default='notingroup')
def __str__(self):
return self.group
VOTE_CHOICES = (
('helpful', "helpful"),
('meh', 'meh'),
('disaster', 'disaster')
)
class VotingValues(models.Model):
value1 = models.CharField(max_length=40)
value2 = models.CharField(max_length=40)
value3 = models.CharField(max_length=40)
value4 = models.CharField(max_length=40)
value5 = models.CharField(max_length=40)
score1 = models.CharField(choices=VOTE_CHOICES, max_length=20)
score2 = models.CharField(choices=VOTE_CHOICES, max_length=20)
score3 = models.CharField(choices=VOTE_CHOICES, max_length=20)
score4 = models.CharField(choices=VOTE_CHOICES, max_length=20)
score5 = models.CharField(choices=VOTE_CHOICES, max_length=20)
user = models.EmailField(max_length=255)
group = models.CharField(max_length=250, default='notingroup')
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user + ' \'s ' + 'vote in ' + self.group
is there a better approach to implement this scenario?
I really don't like puting the questions inside same model as answers. maybe it's better idea to put questions in another model (something like Question)
class Question(models.Model):
q1 = models.CharField(max_length=40)
q2 = ...
class VotingValues(models.Model):
question = models.ForeignKey(Question)
a1 = ...
I think this is cleaner compared to your solution, but you can think more about it. if it's just a one time thing above answer is good enough but if you might need to create more surveys with more or less questions it's clear that for each survey you need to change current models or create new ones
to solve this issue, first thing comes to my mind is putting questions and answers inside a json field or array field
class Question(models.Model):
q = JSONField()
class VotingValues(models.Model):
question = models.ForeignKey(Question)
a = JSONField()
(note that I don't know how aggregated queries work with json field so you might need to look it up)
other thing comes to my mind is instead of using json field add a new model to store individual questions:
class Question(models.Model):
question = models.CharField
group = foreign key to question group
class QuestionGroup(models.Model):
name = models.CharField
class Vote(models.Model):
question = foreign key to question
score = ...
for current survey: you create 1 question_group and add 5 questions for that group. when user votes for that question_group you add 5 rows in vote table (one row for each question in question group)

Is there a way to filter data when passing it in ModelForm and how can we edit them?

I'm creating a site to register students. So basically it is divided into 3 parts
1. A student register model which take the name, fathername, etc of student.
2. A student fee model which use foreignkey to get register student.
3. ModelForm for showing student fee model to enter data.
Now the problem if I want to fill a student fee of class 1 it shows all the student of other classes, but I want the student filter according to their classes and their name show and in front of them editable fee and pending fee form.
By some reach I got to know about ModelForm instance I wrote code for automatically add register students to student fee.
def student_fee(request):
# add a selection field to a variable for filtering student_class below this.
students = StudentRegister.objects.filter(student_class="1")
....
for x in students:
if not StudentFee.objects.filter(student=x):
StudentFee.objects.create(student=x, fee=0, pending_fee=0)
But for instance I have to know primary key of every student I can loop through them but it only get the last element.
models.py
class StudentRegister(models.Model):
student_image = models.ImageField(upload_to="register_student", blank=True)
student_class = models.CharField(max_length=2, choices=STUDENT_CLASS, default="1")
mobile_number = models.CharField(max_length=50)
student_name = models.CharField(max_length=50)
father_name = models.CharField(max_length=50)
mother_name = models.CharField(max_length=50)
address = models.CharField(max_length=200)
student_fee = models.CharField(max_length=10, default="0")
Date_Of_Birth = models.DateField(auto_now=False)
admission_fee = models.CharField(max_length=10)
Admission_date = models.DateField(auto_now=False)
adhaar_no = models.CharField(max_length=100)
def __str__(self):
return "%s class: %s" % (self.student_name, self.student_class)
class StudentFee(models.Model):
student = models.ForeignKey(StudentRegister, on_delete=models.CASCADE)
fee = models.CharField(max_length=20)
pending_fee = models.CharField(max_length=20)
def __str__(self):
return "%s " % (self.student)
forms.py
class StudentFeeForm(forms.ModelForm):
class Meta:
model = StudentFee
fields = '__all__'
views.py(its messy sorry)
def student_fee(request):
# add a selection field to a variable for filtering student_class below this.
students = StudentRegister.objects.filter(student_class="1")
real = StudentFee.objects.all()
# student_form = StudentFeeForm(request.POST or None)
student_form = StudentFeeForm(request.POST)#, instance=students)
# print(dir(students))
q = (students.get(pk=1))
global list_student_pk
list_student_pk = []
for x in students:
list_student_pk.append(x.pk)
student_get_instance = StudentFeeForm(instance=q)
# print(student_get_instance)
# This thing done don't touch----------------------------------
for x in students:
if not StudentFee.objects.filter(student=x):
StudentFee.objects.create(student=x, fee=0, pending_fee=0)
if request.method == "POST":
if student_form.is_valid():
pass # this thing will done after the form problem solved.
# till here ==========================================================
return render(request, "student_fee_home.html", {"students": students, "real":real, "student_form":student_form, "list_student_pk":list_student_pk, "student_get_instance":student_get_instance})
I want that modelforms filter according to class.
Then the student fee model which already having register student(student name, fee, pending fee) can edit. So that it shows the student name and right in front of him a editable fee form and a pending fee form.
It is working right now like this showing all student of all classes, but I want that students name will show instead of selection field. In my knowledge only option to display names of student display names direct from models then use a form to take input of fee and pending fee then create it in models.
djang0-filter will help you for filtering
pip install django-filter
Model.py
class Dispatcher(models.Model):
_safedelete_policy = SOFT_DELETE
Individual = 'Individual'
Company = 'Company'
TYPES = [
(Individual, 'Individual'),
(Company, 'Company')
]
type = models.CharField(max_length=255,
choices=TYPES,
default=Individual)
Views.py
class DispatcherViewSet(viewsets.ModelViewSet):
queryset = Dispatcher.objects.all()
serializer_class = DispatcherSerializer
filter_backends = (DjangoFilterBackend,)
filterset_fields = ['type']

Django Rest Framework- Writable nested serializers error

I'm trying to create a quiz app, i'm a beginner in dajango and rest, and I'm trying to create a serializer for creating new question with choices, i also not understand well how writable nested serializers working, if some one can give a working example
models.py:
class Question(models.Model):
quiz = models.ForeignKey(Quiz, related_name="question")
question = models.CharField(max_length=200)
def __unicode__(self):
return self.question
class Choice(models.Model):
question = models.ForeignKey(Question, related_name="choice")
choice = models.CharField(max_length=200)
correct_answer = models.BooleanField(default=False)
def __unicode__(self):
return self.choice
serializers.py:
class createChoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Choice
fields = ('choice','correct_answer',)
class createQuestionSerializer(serializers.ModelSerializer):
choices = createChoiceSerializer()
class Meta:
model = Question
def create(self, validated_data):
choices_data = validated_data.pop('choices')
question = Choice.objects.create(**validated_data)
for choice in choices_data:
try:
choice = Choice.objects.get(name=choice["name"])
except Choice.DoesNotExist:
choice = Choice.objects.create(**choice)
question.choices.add(choice)
return question
when i write the question and choice i got an error:
ValueError at /questions/create
Cannot assign "u"what's your name"": "Choice.question" must be a "Question" instance.
question = Choice.objects.create(**validated_data)
question is a Choice instance and question.choices.add(choice) basically adds Choice to Choice instance.
You may try Question.objects.create(**validated_data). I'm not sure if this works but at least solves the error you encounter now.

Get all teachers that have at least 1 subject on table - Django Query Set

I Would like to get all the Teachers that have at least 1 subject. Currently I'm using...
user = users.objects.all().order_by('-karma')[:100]
Because people who does not have any subjects related is a Student.
Here is my models.py
class subjects(models.Model):
id_user = models.IntegerField(db_column='ID_user') # Field name made lowercase.
s = models.CharField(max_length=90)
def __unicode__(self):
return self.s
class Meta:
db_table = 'subjects'
class users(models.Model):
email = models.EmailField(max_length=160)
nick = models.CharField(unique=True, max_length=60)
karma = models.IntegerField(max_length=11)
pass_field = models.CharField(db_column='pass', max_length=160)
One option is to do this in two steps:
get id_user list from subjects model with the help of values_list():
user_ids = subjects.objects.values_list('id_user', flat=True).distinct()
get all users by the list of id_users using __in:
print users.objects.filter(pk__in=user_ids)
Also, since models are not related, you can make a raw query that would do the same in one go.

Categories