I'm starting my first Django web app [after completing the Django official tutorial and Django Girls tutorial].. I'm having some trouble wrapping my head around setting up models. I have something now that works, but I feel that it is quite inefficient and I rather learn the correct way before going forward..
Starting out - When learning a new programming language, a lot of people (on the internet) advise to pick a topic/hobby you enjoy and make a project out of it. I enjoy sports a lot and wanted to recreate a virtual scoreboard, similar to ESPN or any other sports web site.
My models.py currently looks like this -
class Game(models.Model):
# start_time = models.DateTimeField()
today = models.DateField(default=date.today)
game_id = models.AutoField(primary_key=True)
game_outcome = models.CharField(max_length=8)
game_quarter = models.CharField(max_length=1)
game_clock = models.PositiveSmallIntegerField()
away_team_id = models.CharField(max_length=3)
away_team_class = models.CharField(max_length=3)
away_team_city = models.CharField(max_length=13)
away_team_name = models.CharField(max_length=12)
away_team_score = models.PositiveSmallIntegerField()
home_team_id = models.CharField(max_length=3)
home_team_class = models.CharField(max_length=3)
home_team_city = models.CharField(max_length=13)
home_team_name = models.CharField(max_length=12)
home_team_score = models.PositiveSmallIntegerField()
but I feel like this is way too many variables and not the correct way to go about it. I have also tried something like this...
class Day(models.Model):
today = models.DateField(default=date.today)
class Game(models.Model):
game_id = models.AutoField(primary_key=True)
game_outcome = models.CharField(max_length=8)
game_quarter = models.CharField(max_length=1)
game_clock = models.PositiveSmallIntegerField()
away_team_id = models.CharField(max_length=3)
away_team_score = models.PositiveSmallIntegerField()
home_team_id = models.CharField(max_length=3)
home_team_score = models.PositiveSmallIntegerField()
class Team(models.Model):
team_id = models.ForeignKey('Team')
team_class = models.CharField(max_length=3)
team_city = models.CharField(max_length=13)
team_name = models.CharField(max_length=12)
Every Day has 0 to xx amount of games. Than every game has: outcome (null or 'FINAL'), current quarter ('1' or null), current clock ('00:00' or null), away team ('CHA'), away score ('99'), home team('TOR') and home score('102'). Then I would take the team id's and compare that to the class Team. Every Team has a class (for css: 'tor'), a city ('Toronto'), and full name ('Raptors').
Still it's not sticking in my head. I can get the all the information in a python shell and output to my html/css, but I feel it's inefficient. Also, every Day has it's own html page (similar to website.com/nba/scores/20150112/) and is filled with all the games from that day.
Sorry if this is too beginner to ask; I have spent a lot of time looking for answers and finally decided to post on stackoverlow (my first question ever).
Any information or advice would be greatly appreciated.
First of all you need to understand the more ForeignKeys you use the more load you put on the database. But it also depends a lot on the views.py code as well. Second of all you don't need to use team_id as a field name if you use a ForeignKey. Just mention the class name and it will automatically create an _id for the field.
Look at the following code:
class Game(models.Model):
start_time = models.DateTimeField()
today = models.DateField(default=date.today)
game_id = models.AutoField(primary_key=True) # You don't need this line, an id field is created for EVERY model class even if you don't specify it.
game_outcome = models.CharField(max_length=8)
game_quarter = models.CharField(max_length=1)
game_clock = models.PositiveSmallIntegerField()
away_team = models.ForeignKey('Team')
home_team = models.ForeignKey('Team')
class Team(models.Model):
team_class = models.CharField(max_length=3)
city = models.CharField(max_length=13)
name = models.CharField(max_length=12)
score = models.PositiveSmallIntegerField()
You can see that I have created another class by the name of Team and put four fields on that which was repeated in your original Game class. Then I have connected the Team class to the Game class with ForeignKey. If you install SQLiteBrowser and check out the database file then you will see that the away_team field is actually the away_team_id field in the database because Django takes care of that. You don't need to create id fields, just use relations like ForeignKey, ManyToManyField, etc. Off the top of my head this is the only thing that I can suggest.
Judging by the scope of this project you will not put too much pressure on the database with too many relations, so don't worry about that now. That' it. If you have any question more specific you can ask. Cheers! :)
P.S. I am not sure about your project details so use whichever relation you see fit, be it one-to-one, many-to-one or many-to-many, etc. Read the docs for more details. :)
I think the general idea of your model approach is good enough. Nevertheless, I'd encourage you to go through Django's ORM relationships documentation. It's ok if you want to use strings as your primary key, but let Django's ORM know that by using the proper model field. If you use primary and foreign keys (relationships), your dbms will create indexes over the necessary fields, resulting in more efficient queries. Let me know if this help! Good luck with your project!
UPDATE:
It would be something like this:
class Day(models.Model):
today = models.DateField(default=date.today)
class Game(models.Model):
game_outcome = models.CharField(max_length=8)
game_quarter = models.CharField(max_length=1)
game_clock = models.PositiveSmallIntegerField()
day = models.ForeignKey(Day, on_delete=models.CASCADE)
away_team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='away_team')
away_team_score = models.PositiveSmallIntegerField()
home_team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='home_team')
home_team_score = models.PositiveSmallIntegerField()
class Team(models.Model):
team_class = models.CharField(max_length=3)
team_city = models.CharField(max_length=13)
team_name = models.CharField(max_length=12)
Notice that I omitted all id fields, since django will use one automatically created, which behaves the same as AutoField. Also notice that since Game has two references to the same class (Team), it is necessary to provide the extra parameter related_name. Mor info about it in django docs about related_name.
This way, you can do things like
game = Game.objects.find(1)
away_team_name = game.away_team.team_name
You can access the associated Team class in the away_team variable. No need to call away_team_id at all.
Related
As a part of a task, I created an "apartment listings" website.
I managed to get that done, but now I need to make a "reservation system" for it.
The basic idea is that a logged in user can select an apartment from the listed apartments, pick a "start_date" and an "end_date" (if the apartment already isn't booked ) and book the apartment.
Im a total Django newbie, and need some pointers in order to start somewhere with this task.
I have an Apartment model which contains all of the Apartments info that I use to print everything out with the template.
I'm using the provided django user models to register / log-in.
What kind of model do I need for the reservation, and how could I connect everything ?
I tried making a reservation model, but I got no idea where to go next.
I'm not asking for you to solve this for me, I'm asking for someone to explain (if possibile in detal) to me how could I go on about achieving this on my own.
this is my apartment model:
class Apartment(models.Model):
title = models.CharField(max_length=200)
address = models.CharField(max_length=200)
city = models.CharField(max_length=100)
state = models.CharField(max_length=100)
zipcode = models.CharField(max_length=20)
description = models.TextField(blank=True)
price = models.IntegerField()
bedrooms = models.IntegerField()
bathrooms = models.DecimalField(max_digits=2, decimal_places=1)
garage = models.IntegerField(default=0)
size = models.IntegerField()
photo_main = models.ImageField(upload_to='photos/%Y/%m/%d/')
photo_1 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
photo_2 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
photo_3 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
photo_4 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
in_rent = models.BooleanField(default=False)
list_date = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.title
Thank you so much !
Your assumption for making a Reservation object would be correct.
You'll want to link those reservations to the Apartment in question. Django supports these kind of relationships through their ForeignKey and ManyToManyField.
These fields support linking of one-to-one, one-to-many, and many-to-many relationships.
In your case, one Apartment can have many Reservations, which means you need to have a field in your Reservation pointing to a single Apartment, which can be done using a ForeignKey
Your model should look something like this:
Reservation(models.Model)
apartment = models.ForeignKey(to=Apartment, related_name='reservations',
on_delete=models.Cascade)
start_date = models.DateField()
end_date = models.DateField()
To retrieve all reservations for an appartment, you can simply use apartment.reservations since we've defined a related_name in the ForeignKey field.
You can even filter for specific dates by doing Reservations.objects.filter(apartment=apartment, start_date__gte=<your_start_date>, end_date__gte<your_end_date>)
I'm working on a django website that can allow me to display some information about players and matches for a game.
There will be multiple matches and multiple players. The problem I'm having is that I'm not sure if this is what I should be doing:
class Player(models.Model):
player_id = models.IntegerField(default=0)
matches = models.ManyToMany(Match)
class Matches(models.Model):
match_id = models.IntegerField(default=0)
players = models.ManyToMany(Player)
or I should be doing:
class Player(models.Model):
player_id = models.IntegerField(default=0)
class Matches(models.Model):
match_id = models.IntegerField(default=0)
players = models.ManyToMany(Player)
A player can be in multiple matches, and a match can contain multiple players, which is why I'm a bit confused.
You should define the relation in only one of the models, so the second example is the correct one.
In the first one (you have a typo there that should be Matches by the way) you are creating two separate M2M relations between the two models that you don't want to have in your case.
On an unrelated note, you don't need to to have player_id and match_id columns as Django will automatically create id columns for your models.
The following code will solve your model structure for your project.
class TimeStamped(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Player(TimeStamped):
name = models.CharField(max_length=50)
extra_info = models.TextField()
matches = models.ManyToManyField('Match')
def __unicode__(self):
return self.name
class Match(TimeStamped):
title = models.CharField(max_length=50)
extra_info = models.TextField()
class Meta:
verbose_name_plural = 'Matches'
def __unicode__(self):
return self.title
The TimeStamped model is a good idea for every project you build. If you are using Python 3 then replace __unicode__ with __str__. Don't use plural in model names. Use verbose_name_plural, that is the convention in my opinion. It seems like you might have a problem with query players from a Match instance. Read the documentation for a detailed info on that. If you can't find that post here. Since this post is not about the querysets so I skipped that part.
Absolutely right for this scenario, ManyToMany relation is required to setup in DB.
id is the default field in Django model if you are not providing any other primary key. And ID is incremental. As per my opinion, Following models are enough to satisfy your scenario.
class Player(models.Model):
name = models.CharField(max_length=255)
class Match(modles.Model):
player = models.ManyToMany(Player, related_name="matches")
According to above model sample, you can accessing matches of one player and players who played a single match.
match = Match.objects.get(id=1)
print match.player.all() # It will print all players for match of id 1
player = Player.objects.get(id=1)
print player.matches
You definetelly have to use ManyToManyField, you can add it only to one model:
class Player(models.Model):
player_id = models.IntegerField(default=0)
matches = models.ManyToMany(Match)
class Matches(models.Model):
match_id = models.IntegerField(default=0)
After declaring models, Player objects have access to their related Matches objects in next way:
player.matches.all()
Matches objects have access to their related Player objects in next way:
match.player_set.all()
See article Many-to-many relationships, Django documentation, there are plenty of use full information of how to dial with ManyToMany relations in Django.
I'm struggling with django querysets and GROUP BY queries, I know there are plenty of similar questions, but I really don't get it:/
I would like to be able to create a request similar to this one (SQLite):
SELECT MAX(fb_game_score.value), fb_game_fbuser.first_name, fb_game_fbuser.last_name
FROM fb_game_score
JOIN fb_game_game ON (fb_game_score.game_id = fb_game_game.id)
JOIN fb_game_fbuser ON (fb_game_game.user_id = fb_game_fbuser.id)
GROUP BY fb_game_fbuser.fb_user_id;
The query is quite simple, it lists the users scores by showing only the best score for each players.
For clarification here's the model classes:
class FBUser(AbstractUser):
fb_user_id = models.CharField(max_length=100, null=True)
oauth_token = models.CharField(max_length=1024, null=True)
expires = models.IntegerField(null=True)
highest_score = models.IntegerField(null=True)
class Game(models.Model):
identifier = models.CharField(max_length=100, db_index=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='games')
class Score(models.Model):
game = models.ForeignKey(Game, related_name='scores')
value = models.IntegerField()
date = models.DateTimeField(auto_now=True)
timestamp = models.FloatField(default=0)
inter = models.BooleanField(default=False)
There's no high-level group_by in the queryset. It's used in calls to aggregate and annotate but it is not available to you.
There's a low-level API which is not documented at all. You can get an internal query description:
queryset = ... #whatever query you'd want to group by
query = queryset.query
and then you can alter the group_by member -which is a list- by adding a field which you'd want to group by:
query.group_by.append('a_field')
But:
you have to seriously know what you're doing.
there's no guarantee of stability of this API.
The current alternative for this is falling back to a raw (django.db.connection.* methods) SQL query.
Edit: I just saw this 3rd-party application which could help you with reports. I don't know if you can use in-code reports, or you have to limit yourself to in-view reports (i.e.: don't know if you can process reports in code or just have them as final results).
I have following models setup in my Django application
class School(models.Model):
name = models.TextField()
class Courses(models.Model):
name = models.TextField()
schools = ManyToManyField(School)
Now, I want to find out all schools which offer a particular course. For example, find all schools which offer biology and chemistry. What query can I use?
thanks
See lookup that span relationships in the manual:
class Courses(models.Model):
name = models.TextField()
schools = ManyToManyField(School, related_name='courses_set')
School.objects.filter(courses_set__name__in=('biology', 'chemistry'))
Hey, I have models like this:
class Galleries(models.Model):
creation_date = models.DateTimeField()
name = models.CharField(max_length=255, unique=True)
gallery_type = models.ForeignKey(Categories)
class Categories(models.Model):
handle = models.CharField(max_length=255, unique=True)
class Values(models.Model):
category = models.ForeignKey(Categories)
language = models.CharField(max_length=7)
category_name = models.CharField(max_length=50)
And now, I just want to reach the values of categories by starting from Galleries. For example: galleries = Galleries.objects.get(id=1). And now I want to reach somehow the values by using this "galleries" object... To get values with specific language would be much more better... I miss skills in Django ORM, so if you can, please point me to some docs or give some code example. Thanks!
galleries = Galleries.objects.get(id=1)
values = galleries.gallery_type.values_set.filter(language='language')
Interestingly, you used the exact wording that the docs use to refer to the related field lookups. I always found the definition strange to the gut, maybe because they put it in quotes.
FOLLOWING RELATIONSHIPS "BACKWARD"
http://docs.djangoproject.com/en/1.2/topics/db/queries/#following-relationships-backward
You may want to use the select_related method of objects so you reduce the number of queries you are making. select_related
gallery = Galleries.objects.select_related().get(id=1)
You can set a related name for the Values model in the category fk:
class Values(models.Model):
category = models.ForeignKey(Categories, related_name="categories")
language = models.CharField(max_length=7)
category_name = models.CharField(max_length=50)
now you can get your list of values for a specific language by doing
values = gallery.gallery_type.categories.filter(language="language")