I want to ask the user how many questions they want to ask; based on their response, I want to populate a model with those many fields. The way I am currently thinking about doing that is as follows:
from __future__ import unicode_literals
from django.db import models
class Interview(models.Model):
title = models.TextField()
description = models.TextField()
number_questions = models.IntegerField()
question_one = models.ForeignKey('Question', related_name='question_one')
question_two = models.ForeignKey('Question', related_name='question_two')
question_three = models.ForeignKey('Question', related_name='question_three')
question_four = models.ForeignKey('Question', related_name='question_four')
question_five = models.ForeignKey('Question', related_name='question_five')
class Question(models.Model):
question_description = models.TextField()
prep_time = models.IntegerField()
response_time = models.IntegerField()
I realize that this solution is inefficient because a) the user is limited to a preset number of questions and b) if the user specifies less than 5 questions, there are unnecessary question entries created. What is a better way to go about storing multiple questions?
Do the foreign key relation the other way round. That's how you model a many-to-one relation:
class Interview(models.Model):
title = models.TextField()
description = models.TextField()
#property
def number_questions(self):
return self.questions.count()
class Question(models.Model):
interview = models.ForeignKey(Interview, related_name='questions')
question_description = models.TextField()
prep_time = models.IntegerField()
response_time = models.IntegerField()
Now you can access an interview's question via:
interview.questions.all()
An Interview can now have any number of Questions.
Btw, the related_name of all the ForeignKeys in your original Interview model should have been 'interview' to make any semantic sense.
Related
I am studying Django and SQL and I have proposed to create a social network in which I can add all the reactions of a publication and add it to a new field where they are all added.
from django.db import models
# Create your models here.
class Post(models.Model):
# User
user = models.OneToOneField(User, on_delete=models.CASCADE)
post = models.TextField(max_length=500000)
# Data
comments = models.IntegerField()
reactions = models.IntegerField()
## Reaction Data
like = models.IntegerField()
love = models.IntegerField()
wow = models.IntegerField()
sad = models.IntegerField()
angry = models.IntegerField()
That is the model of publications, there is a field called reactions, and that will be the sum of all the reactions that publication has acquired. How can I create that sum?
Such architecture will be a little wrong.
from project_name import settings
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=50)
text = models.TextField()
likes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='post_likes')
love = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='post_loves')
# ... another reactions
created_date = models.DateTimeField(default=timezone.now)
settings.AUTH_USER_MODEL is your User
After that you will then be able to not only know the number of reactions, but also to identify users
To count users:
post = Post.objects.create(author=..., ...) # create post
queryset = post.likes # will return users id, who liked post
queryset.count() # will return number of users
I know how I can count things with annotate (in my view) but I would like to do the same in model (so it would be more reusable).
For example (lets take an example from django documentation) I have this model:
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
class Publisher(models.Model):
name = models.CharField(max_length=300)
class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
pubdate = models.DateField()
class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
and I can use in view this:
from django.db.models import Count
pubs = Publisher.objects.annotate(num_books=Count('book'))
But how I do that in model?
I know this question is pretty basic (probably) but I'm pretty much beginner in django.
Thanks for answers!
You can use custom managers:
Django docs: Managers
class BookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(num_books=Count('book'))
class Publisher(models.Model):
name = models.CharField(max_length=300)
books = BookManager()
Now you can call it like this:
pubs = Publisher.books.all()
And you will have num_books with your objects.
You can use classmethod for this.
class Publisher(models.Model):
...
#classmethod
def get_book_count(cls):
return cls.objects.annotate(num_books=Count('book'))
You can call this method as
pubs = Publisher.get_book_count()
Edit - Also check out the answer by #Navid2zp which might be a better solution for you.
I am building a Quiz app where a user (Content Creator or Author) can create quizzes (choice based questions and their solutions) from a specific domain. These quiz can be attempted by other users (Consumers - not yet implemented).
To allow quiz consumers to be able to search questions based on specific domains of their interest (and to add granularity to the quiz content), I am implementing a tagging system attached to the questions.
Here are my models:
class question(models.Model):
ques_id = models.AutoField(primary_key=True)
ques_text = models.TextField(max_length=1024, blank=False)
ques_author = models.ForeignKey('author')
ques_created = models.DateField(auto_now_add=True)
ques_dscore = models.IntegerField()
ques_bloom = models.CharField(max_length=3)
ques_subject = models.CharField(max_length=3)
ques_type = models.CharField(max_length=1)
ques_flags = models.CharField(max_length=16)
ques_quiz = models.ManyToManyField('quiz')
def __unicode__(self):
return self.ques_text
class choice(models.Model):
choice_id = models.AutoField(primary_key=True)
choice_text = models.CharField(max_length=256, blank=False)
choice_ques = models.ForeignKey('question')
choice_ans = models.BooleanField(default=False)
choice_tags = models.CharField(max_length=32)
def __unicode__(self):
return self.choice_text
class answer(models.Model):
answer_id = models.AutoField(primary_key=True)
answer_text = models.TextField(max_length=1024)
answer_ques = models.ForeignKey('question')
answer_choice = models.ForeignKey('choice')
answer_tags = models.CharField(max_length=128)
class author(models.Model):
user = models.OneToOneField(User)
domain = models.CharField(max_length=16)
def __unicode__(self):
return self.user.username
# a table for storing all the tags
class tags(models.Model):
tags_id = models.AutoField(primary_key=True)
tags_text = models.CharField(max_length=16)
def __unicode__(self):
return self.tags_text
# table that connects tags with question attached to the tag
# from all the research on the web, it can be infered that
# 3NF tagging (Toxi Solution) is the best way to go
# good for inserts but slow on selects
class tagcon(models.Model):
tagcon_id = models.AutoField(primary_key=True)
tagcon_tags = models.ForeignKey('tags')
tagcon_ques = models.ForeignKey('question')
I have currently applied the 3NF tagging Toxi solution. The issue is that a denormalized system would help in faster selects and a 3NF would be faster inserts but slow searches.
I am confused if I should use ManyToMany field type for tags. Could someone enlighten if it would be better to use a ManyToMany field inbuilt in Django or implement the 3NF system as done?
This is already exactly the same as a ManyToManyField. The only difference is that adding the field would give you an explicit accessor from question to tag.
(Note, your models are very odd. There is absolutely no benefit in prefixing every field name with an abbreviated version of the model name; you can only ever access the field via the model anyway, so you would always be doing question.ques_text, which is redundant. And you shouldn't be defining your own PK fields unless you have a very good reason.)
In my opinion I suggest you try these 2 projects
django-tagging.
django-taggit.
I have a simple voting app which has 2 models Poll and Choice as most voting apps do.
Poll model has the following fields:
question - charField
pub_date - date and time
end_date - date and time
Also, each Poll has 2 choices.
Choice model has the following fields:
Poll - ForeignKey
choice - ImageField
vote - Integer
I have another model Person. A Poll occurs between 2 people from the Person model.
Person Model:
Name - Charfield
age - charfield
image - imagefield
...
I want to accomplish the following in the admin;
Create Poll (this is a simple one)
Create Choice - take image from Person Model rather than uploading new.
if a choice is added against a poll, the choice and the votes on that choice automatically show up as read only fields on Poll.
Person model shows how many Polls has the Person taken part in and how many of them has he won and lost.
Points 2,3 and 4 are the ones I am struggling with. please keep your responses simple, I am a newbie.
class Poll(models.Model):
question = models.CharField(max_length=250)
pub_date = models.DateTimeField()
end_date = models.DateTimeField()
class Choice(models.Model):
Poll = models.ForeignKey(Poll)
choice = models.ImageField(upload_to="choice")
vote = models.IntegerField()
class Person(models.Model):
name = models.CharField(max_length=200)
age = models.IntegerField(blank=True, null=True)
image = models.ImageField(upload_to='img')
let me know if the question is not clear.
It is not totally clear to me what you want to achieve. Implying you want to answer the question in reference to two images I would use the following models:
class Poll(models.Model):
question = models.CharField(max_length=250)
person1 = models.ForeignKey(Person,related_name ="+") #"+" to block reverse reference
person2 = models.ForeignKey(Person,related_name ="+")
pub_date = models.DateTimeField()
end_date = models.DateTimeField()
class Choice(models.Model):
Poll = models.ForeignKey(Poll)
choice = models.ForeignKey(Person)
vote = models.IntegerField()
class Person(models.Model):
name = models.CharField(max_length=200)
age = models.IntegerField(blank=True, null=True)
image = models.ImageField(upload_to='img')
def votes_sum(self):
return len( self.choice_set.all()) #this returns all votes
In the admin you can then add the Choice model as Inline to the Poll.
class ChoiceInline(admin.TabularInline):
model = Choice
extra=1
class ProjectAdmin(admin.ModelAdmin):
inlines = [ChoiceInline]
class VotesAdmin(admin.ModelAdmin):
list_display = ['name', 'votes_sum']
readonly_fields = ('votes_sum',)
I did not test this code but you should get an idea how you can do this.
I'm working on a questionnaire model for django that should be maintainable by someone with no programming experience, so I've spent a lot of time crafting my models to compensate for minor details.. Now I want to unlock the potential of SQL database queries to be able to generate statistics about the responses and feedback given.
One of my question types is a 5 star rating, so I would like to be able to gather statistics about the question like:
How many responses for question q were 5 star (, 4star, 3star, etc.)?
What was the average rating response?
Ideally I would like to record these statistic questions in a model, and create a view that shows all the statistics asked and keep the entire thing programmatic.
Should this be a carefully crafted model or set of models like feedback, or is there already some framework or module that handles these situations for me?
My questionnaire/models.py:
class QuestionType(models.Model):
name = models.CharField(max_length=256, blank=True, default="")
class Question(models.Model):
text = models.TextField()
type = models.ForeignKey(QuestionType)
class Response(models.Model):
question = models.ForeignKey(Question)
answer = models.TextField()
class Feedback(models.Model):
user = models.ForeignKey(User)
responses = models.ManyToManyField(Response)
response_time = models.DateTimeField(auto_now_add=True)
This would cover your requirements:
class QuestionType(models.Model):
name = models.CharField(max_length=256, blank=True, default="")
class Question(models.Model):
text = models.TextField()
type = models.ForeignKey(QuestionType)
def how_many_ratings_where_x_stars(self, stars):
return self.rating_set.filter(stars=stars).count()
def average_rating(self, stars):
return self.rating_set.aggregate(models.Avg('stars'))['stars__avg']
class Response(models.Model):
question = models.ForeignKey(Question)
answer = models.TextField()
user = models.ForeignKey(User)
timestamp = models.DateTimeField(auto_now_add=True)
class Rating(models.Model):
question = models.ForeignKey(Question)
stars = models.PositiveIntegerField(min_value=1, max_value=5)
user = models.ForeignKey(User)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = [('question', 'user')]