django voting app - relationship between different models - django

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.

Related

django models hierarchy question: related attributes of a ManyToManyField

As a fresh coder, I seriously have problems to build my models relations.
Please check these two cases, How can I set current_reading_pages on my Scenario2?
from django.db import models
# Scenario1: Users can record their reading progress of a book.
class Book(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
current_reading_book = models.ForeignKey('Book', on_delete=models.CASCADE)
current_reading_page = models.IntegerField()
Result1: No problems about database, but Users can records their progress of only one book.
Other scenario, which I want to build:
from django.db import models
# Scenario2: Users can record their reading progress of multiple books.
class Book(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
current_reading_books = models.ManyToManyField('Book')
# current_reading_pages = ???
I want to save all progress of current books, for example,
User A is reading 3 books, book1 till page 100, book2 till page 10, book3 till page 0.
And I found 'through' parameter in django ManyToManyField,
My codes become like below but it does not work as I expected.
from django.db import models
# Scenario3: Using through parameter in ManyToManyField
class Book(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
current_reading_books = models.ManyToManyField('Book', through='ReadingBook')
class ReadingBook(models.Model):
book = models.ForeignKey('Book', on_delete=models.CASCADE)
current_reading_page = models.IntegerField()
ERRORS:
test_model.ReadingBook: (fields.E336) The model is used as an intermediate model by 'test_model.User.current_reading_books', but it does not have a foreign key to 'User' or 'Book'.
I think, that first scenario is easy to realize.
just add user attribute into the custom class UserBook
for example
class UserBooks(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
current_page = models.IntegerField(default=1)
if user wanna check his progress, in views.py you can just filter by books = UserBooks.objects.filter(user=request.user)

Creating a variable field in model Django

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.

Django Admin - Add button to create duplicate fields

I am trying to add (+) button on the admin page to duplicate a field. So say I have a field for Father/Mother, and in case someone has a step father or a step mother I could hit the plus button on Father/Mother and duplicate the field and update step Father/Mother info.
I want to be able to do this with other fields as well and not just these two.
I am a newbie. So can you please help me with detailed instructions for how to do this please?
I have been trying to source this info for some time now...but :(
Thanks,
Codie
I have a very simple model structure and no forms as of now. In the future I may have some forms.
class _musi(models.Model):
name = models.CharField(max_length=200)
born = models.DateField()
died = models.DateField()
age = models.IntegerField()
reason_of_death = models.CharField(max_length=200)
birthplace = models.CharField(max_length=200)
father = models.CharField(max_length=200)
mother = models.CharField(max_length=200)
You need to use Django Inlines also to work with inline may be you need to make some changes with your models as you did not show your models so i am not sure about this.
You can refer to Inlines
Django Admin Inlines
Edit :
Please add all fields as Foreignkey with your current model _musi .
You should read how to use Foreign Key relationships
For now if you want with fields father and mother then do like below.
class Father(models.Model):
name = models.CharField(max_length=200)
class Mother(models.Model):
name = models.CharField(max_length=200)
class _musi(models.Model):
name = models.CharField(max_length=200)
born = models.DateField()
died = models.DateField()
age = models.IntegerField()
reason_of_death = models.CharField(max_length=200)
birthplace = models.CharField(max_length=200)
father = models.ForeignKey(Father)
mother = models.ForeignKey(Mother)
Please implement same with your other fields which need this functionality.

django models - query with manytomanyfield

I have problem with 1 query connected with ManyToManyField. We have 2 related models: User and Event. Model Event has 2 relations with User, it must have 1 organizer and any number or participants - organizer cannot be participant (I skipped the code which is responsible for validation of that). Now, as an example, what I want is all participants from events I organized. Problem is that below query only gets request.user himself, skipping all participants alltogether. Is there a way to achieve what I need without any custom query? thanks
#models.py
class User(models.Model):
name = models.CharField(max_length=100)
class Event(models.Model):
name = models.CharField(max_length=100)
organiser = models.ForeignKey(User)
participants = models.ManyToManyField(User, related_name='participants', blank=True, null=True)
#views.py
def assess_partners(request):
users = User.objects.filter(event__organizer=request.user)
return render(request, 'some template.html', {'users': users})
Things will be clearer if you use better related_names, e.g.:
class Event(models.Model):
name = models.CharField(max_length=100)
organiser = models.ForeignKey(User, related_name='events_as_organiser')
participants = models.ManyToManyField(User, related_name='events_as_participant', blank=True)
what I want is all participants from events I organized
User.objects.filter(events_as_participant__organiser=request.user).distinct()

Modeling django model statistics

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')]