django user defined fields and answer model - python

Similar to this: User defined fields model in django
I am creating a COVID Prescreening system for a school project. Event creators will be able to create forms, which consist of basic questions such as temperature, contact with covid in the last 14 days, etc. as well as provide custom questions for the attendee to answer which I cannot predict.
For example, the event creator could ask 2 questions:
How are you feeling today?
Have you been to a party in the last week?
And every attendee for that event would have to fill out these 2 questions in addition to the standard questions.
The model for this is:
class Event(models.Model):
''' model for an event '''
creator = models.ForeignKey("Account", on_delete=models.CASCADE)
title = models.CharField(max_length=200, help_text="Enter a title for this event")
start_time = models.DateTimeField()
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
custom_questions = models.ManyToManyField(CustomQuestion)
def __str__(self):
return f'{self.title} {self.uuid}'
Each custom question is essentially a key/value model:
class CustomQuestion(models.Model):
question = models.CharField(max_length=200)
response = models.CharField(max_length=200, blank=True)
The user will fill out the COVID Form, which will create an object as such:
class CovidScreenData(models.Model):
custom_responses = models.ManyToManyField(CustomQuestion)
temperature = models.DecimalField(max_digits=5, decimal_places=2, default=98.6)
contact_with_covid = models.BooleanField(default=False)
This data is embedded in the larger response, which ties everything together
class Response(models.Model):
''' model for a completed covid screen '''
account = models.ForeignKey('Account', on_delete=models.SET_NULL, null=True)
time = models.DateTimeField()
event = models.ForeignKey('Event', on_delete=models.CASCADE)
details = models.ForeignKey('CovidScreenData', on_delete=models.CASCADE)
def __str__(self):
return f'{self.account.user.username}\'s Response ({self.event.title})'
When the attendee is filling out the form, I want them to be given the custom_questions for the event they are filling out.
My idea is that when they are presented with the form, each question in custom_questions will be looped through and displayed. When the user submits, their response, as well as the original question, are saved in the custom_responses variable.
What is the correct organization to do this? I am asking this rather than how do I display the questions to the user and save their responses in the model.

If you want to save the response correspond to the question I think you can not use ManytoMany field on this part
class Event(models.Model):
...
custom_questions = models.ManyToManyField(CustomQuestion)
...
you should use ManytoOne for Event relationship with CustomQuestion (adding foreign key to Event on CustomQuestion). It's because you store the answer on the same row with the question so other event should not use the same row of CustomQuestion(containing question and answer).
also you can't store a ManytoMany in the CovidScreenData about the custom_response that actually contains CustomQuestion because the reason on my first explanation.
If you want to get and store the answer just go through the Response item, then get the Event item, and then get pairs of question-answer using foreign key on CustomQuestion join with the Event item.

Related

How to create a single API which takes data of all Employees

I am new to django. I have a model like this:
class Standup(models.Model):
team = models.ForeignKey("Team", on_delete=models.CASCADE)
standup_time = models.DateTimeField(auto_now_add=True)
class StandupUpdate(models.Model):
standup = models.ForeignKey("Standup", on_delete=models.CASCADE)
employee = models.ForeignKey("Employee", on_delete=models.CASCADE)
update_time = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=50)
work_done_yesterday = models.TextField()
work_to_do = models.TextField()
blockers = models.TextField()
If I write view for this model, every employee will have to hit API for his/her standup update. But I am supposed create a single API which takes updates of all the employees and saves it into database. In frontend, it will be something like this:
Employee will select on a team as one employee can be a part of
multiple teams.
Then the employee will give his/her stadup updates.
Then another employee will do the same thing and so on.
At the end,by clicking on submit button, whole data will be saved together.
Any guidance on how to do it?
Not sure why you need a separate model for Updates.
I would try to approach it like that:
make the Standup model reference both Team and Employee models;
last_update, status, work_to_do etc. as its fields;
make a custom serializer that accepts a list with Standup field values and takes the authorized user's ID from request object's data. last_update time can be now(), status calculated according to your business logic
This part of DRF documentation could probably be helpful.

Listing all movies of a specific cinema - Foreign Key Django

I am new to Django and I have a question regarding the models and foreignkeys.
I have two models: Cinema and Movie.
One Cinema can have multiple movies, so I placed the foreign key of cinema in the Movie model.
class Cinema(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=255)
class Movie(models.Model):
title = models.CharField(max_length=255)
description = models.CharField(max_length=255)
posting_cinema = models.ForeignKey('cinemas.Cinema', on_delete=models.CASCADE, null=True)
Now I want to list all the movies of a specific Cinema.
How can I do it?
The idea is the following:
The user clicks on a cinema, it opens a page with the cinema details and a button "see movies". If the user clicks this button, a new page opens and I want to have listed there the movies of that specific cinema.
I tried to figured out some solutions but sadly I am stuck. I was thinking about Movie.objects.filter(#something) but I am not sure
For a given Cinema you can use:
some_cinema.movie_set.all()
Or you can give the ForeignKey a more sensical name to query in reverse:
class Movie(models.Model):
title = models.CharField(max_length=255)
description = models.CharField(max_length=255)
posting_cinema = models.ForeignKey(
'cinemas.Cinema',
on_delete=models.CASCADE,
null=True,
# here we give the reverse relation a name
related_name='movies'
)
then you can query this with:
some_cinema.movies.all()
An alternative is to filter based on the ForeignKey, for example:
Movie.objects.filter(posting_cinema=some_cinema)
or if you have the primary key of the cinema:
Movie.objects.filter(posting_cinema__pk=some_cinema_pk)
(this can for example save a fetch of the Cinema object, if you never really need the Cinema itself).

How to get data from ManyToManyField - Django

I have a problem with retrieving data from this ManyToManyField (users) of a model Event:
class Event(models.Model):
name = models.CharField(max_length=26)
description = models.CharField(max_length=200)
date = models.DateField()
user = models.ForeignKey(User)
users = models.ManyToManyField(User, related_name="users", blank=True)
image = models.ImageField(
upload_to='images/',
default='images/default.png'
)
users = models.ManyToManyField creates an additional table "events_event_users", It stores user_id and event_id fields. So I want to output all event information from Event model, where user_id from that additional table is equal to request.user. Please help, how should I do this?
You can do request.user.users.all()
Note, this is unnecessarily confusing because of the related_name you've set, which defines the backwards relation from User to Event. Leave that out, and the code is more comprehensible:
request.user.event_set.all()
(If you must set one, at least call it events, not users.)

Tricky logic to calculate unique recent visitors in a Django app

I have a live web-based chat app made in Django. Users can form groups where other users can congregate, leave messages (called replies) and photos. The url every user visits to access a group is:
url(r'^group/(?P<pk>\d+)/reply/$', auth(GroupView.as_view()), name="group_reply"),
where pk is group.pk.
My question is: how can I get a list (or set) of all distinct users who accessed a certain group's URL in the last 5 mins? Essentially, I'm trying to calculate the number of unique recent visitors for each group. I can't seem to wrap my head around how to do this, though I guess sessions information could help? (I'm using django user_sessions in this project, which
"makes session objects a first class citizen like other ORM objects"
).
In case required, the model behind a group is:
class Group(models.Model):
topic = models.TextField(validators=[MaxLengthValidator(200)], null=True)
rules = models.TextField(validators=[MaxLengthValidator(500)], null=True)
owner = models.ForeignKey(User)
private = models.CharField(max_length=50, default=0)
category = models.CharField(choices=TYPE, default=1, max_length=25)
created_at = models.DateTimeField(auto_now_add=True)
And the model behind posting a reply in each group is:
class Reply(models.Model):
text = models.TextField(validators=[MaxLengthValidator(500)])
which_group = models.ForeignKey(Group)
writer = models.ForeignKey(User)
submitted_on = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to=upload_pic_to_location, null=True, blank=True )
And User is a vanilla django.contrib.auth user.
You don't have anything that is collecting the data you need. If you want to record visits to a page, you will need to build a model to do that; a simple one with FKs to User (for the visitor) and Group (for the group being visited), plus a timestamp, should be enough. Then your GroupView can make an entry in that table every time a user visits.

Python Django how to retrieve specific objects

I've got this Post model at the moment:
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
def __unicode__(self):
return self.title
If I've got different parts of a website (or a forum rather) that contain different posts, e.g. Discussion about basketball, and Discussion about football, if I wanted to return just posts concerning basketball or just posts concerning football, is the easiest way to just make a specific basketball_post model/football_post model or is there a more efficient way? Should I perhaps be storing the values differently?
Thanks
Django has a really good tutorial. It is about making a Poll app. In the first chapter the thing you want is discussed. It is about a Question that can have multiple Choices.:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
The foreignKey creates a relation between two models. The same can be done for a blog:
class Category(models.Model):
title = models.CharField(max_length=200)
class Post(models.Model):
category = models.ForeignKey(Category) # This is the important part.
title = models.CharField(max_length=200)
body = models.TextField()
date = models.DateTimeField()
def __unicode__(self):
return self.title
The ForeignKey relation lets you do really nice things:
basketball_posts = Post.objects.filter(category_title='Basketball')
But before we all tell you how it is done, I really recommend to do the tutorial. It introduces you to all important Django concepts: https://docs.djangoproject.com/en/1.7/intro/tutorial01/
Update
If you have a fixed set of categories that are not likely to change, than you can hardcode them and use field choices:
class Post(models.Model):
FOOTBALL = 'F' # Variable name and db_value
CRICKET = 'C'
INTRODUCTION = 'I'
CATEGORY_CHOICES = (
(FOOTBALL, 'Soccer'), # Variable name and display value
(CRICKET, 'Cricket'),
(INTRODUCTION, 'Hello my name is'),
)
category = models.CharField(max_length=1,
choices=CATEGORY_CHOICES,
default=INTRODUCTION)
...
https://docs.djangoproject.com/en/dev/ref/models/fields/#choices
One of the advantages of this 'choice machinery' over a CharField without pre defined choices is that you are sure what values end up in your database. This lets you query them, without worrying if your data is sane:
Post.objects.filter(category=Post.CRICKET)
Use the extra table if you need the freedom to create new categories in the future. Use field choices if you don't want (or need) that freedom.
I would suggest to just add a field which makes the post relevant to that certain topic:
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
type = models.CharField(max_length=20) #<--- new field: e.g 'basketball','hockey'..
def __unicode__(self):
return self.title
example query:
#basketball posts
qs = Post.objects.filter(type__icontains="basketball")
then you dont need to have multiple models which also would be redundant.
Assuming all of the posts are in the same format, you could add another field to your model like "type". Different discussion forums could send a different values for that field when the post is added.
type = models.CharField(max_length=140, choices=['Football', 'Basketball', 'Baseball'])
Storing this would make it easy to filter which posts are which.
Post.objects.filter(type = 'Football')
Assuming that one post can be about only one sport, the better approach would be to have a foreign key relation between a model that stores data about a post with another model that stores the data about sports.
Something like this
class Sport(models.Model):
name = models.CharField(max_length = 200)
description = models.TextField()
def __unicode__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
sport = models.ForeignKey(Sport)
def __unicode__(self):
return self.title
This gives you the advantage of isolating the 'Sport' and the 'Post' models.You can add as many sports as you want, without any posts referring to it.
One more advantage is that you can add relevant information to the relevant models.
Eg:Suppose you want to add the information about "how many players are there in a team for sport x?". You can easily achieve this by adding a field "number_of_players" in the 'Sport' model without affecting the 'Post' model.
If you had to do this in one model, 'Post', then it would create lot of issues in terms of data consistency and other undesirable things.
Also, the query will look something like this:
posts = Post.objects.filter(sport__name = "Basketball")
PS:If your requirement is that a post can be tagged to multiple sports, then you can use ManyToMany field instead of a simple foreign key.
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
You could assign your posts tags or category, and filter on those.
If you use the model approach what happens when you add more sports? You'll need manually add the sports in your code, using a tags or category approach allows you to handle it in the db, and would then allow you to filter on the tags/categories in your system

Categories