I want to model a tournament database to store data of online games
My question is: How to create a model in relationship database to store all this types of tournaments? (such as, league of legends tournament, dota 2 tournament)
For example, a tournament can have 8 teams or 5 teams.
This is the sketch I created in my mind. What things do you suggest (especially I need help with relationships of tables).
Also how to keep team 1 and team 2 in the match table (such as, scores, winner, loser)
i thought;
Game database
game_id,name
Player database
player_id,name,surname,country,Game(FK).. ( and some other fields)
Team database
team_id,name,country,game,Player(ManyToMany).. ( and some other fields)
Match database
match_id,name,match_game,match_map,team1,team2,winner,loser,date,duration,score1,score2.. ( and some other fields)
Tournament database
tournament_id,tournament_name,tournament_game,Match(ManyToMany).. ( and some other fields)
You can create something like this in [app_name]/models.py
from django.db import models
class Tournament(models.Model):
name = models.CharField(max_length=255)
class Team(models.Model):
name = models.CharField(max_length=255)
class Player(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
country = models.CharField(max_length=255)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
class Match(models.Model):
name = models.CharField(max_length=255)
match_game = models.CharField(max_length=255)
match_map = models.CharField(max_length=255)
match_teams = models.ManyToManyField(Team)
winner = models.ForeignKey(Team, on_delete=models.CASCADE)
loser = models.ForeignKey(Team, on_delete=models.CASCADE)
duration = models.DurationField()
winning_score = models.PositiveIntegerField()
losing_score = models.PositiveIntegerField()
tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
class Game(models.Model):
name = models.CharField(max_length=255)
match = models.ForeignKey(Match, on_delete=models.CASCADE)
Some things to note:
You do not need to create ID fields, Django does this for you automatically.
A Many-to-Many field can often be replaced with a One-to-One field on the other model, for instance instead of many matches having many games, each game is part of one match. This may or may not work in your particular use case.
I have changed some field names (such as score_1 being replaced with winning_score) because I feel they are more clear, assuming I have correctly understood their purpose.
There are some fields (Tournament.tournament_game, Player.country) for which I used CharField but would be better served with a ForeingKey field to a separate model.
This also assumes that you do not need different fields for different types of tournament (League of Legends, DOTA). If you do need this you could achieve it with different models that inherit from an abstract base class:
class Game(models.Model):
name = models.CharField(max_length=255)
match = models.ForeignKey(Match, on_delete=models.CASCADE)
class Meta:
abstract = True
class DOTA2Game(Game):
dota_field = models.CharField(max_length=255)
class LeagueOfLegendsGame(Game):
lol_field = models.CharField(max_length=255)
In this example DOTA2Game and LeagueOfLegendsGame both inherit from Game and therefore have both a name and a match field as well as their custom fields. Setting abstract = True in the meta class of Game prevents it existing as a separate table within the database.
Related
I am doing rating system on my current django project and I need to implement database for rating. Database would be simple, if I didn't have multiple rating criteries, now I have to ask:
How would you design a database with these objects:
User
RatedObject
Rating
there will ofcourse be multiple users and objects to be rated AND multiple rating criterias.
Now my current idea would be to go for few separate tables with each of the objects such as:
USER(pk=id, fk= rating.id)
RATED_OBJECT(pk=id, fk= rating.id, overall_attribute_1, overall_attribute_2, overall_rating)
RATING(pk=user.id, pk=rated_object.id, fk=rated_attribute1, fk=rated_attribute2)
RATED_ATRIBUTE(pk=id, fk=type, value)
TYPE(pk=id, name) - 2 types since we have 2 attributes to be rated
(now overal_rating will be average of all overall attributes and each overal attribute will be average of all attributes of one type from ratings, where the id of rated object will be same)
I have a bad feeling about doing this 'multiple-FK-to-one-PK' operation. Would it make more sence to make table for each rated attribute? Or maybe say **** it and have values in the RATING itself and screw RATED_ATTRIBUTE and TYPE table? What do you guys think?
EDIT: IF my guess was right- meaning I could connect RATING with RATED_ATTRIBUTE multiple times (multiple fk to 1 pk), I need to set constraints, so when rating happens, it all goes to fields of RATING correctly
(when rating attribute one, in RATING i need to ensure that in RATED_ATTRIBUTE the type is exactly the one like in RATING). Now, I cannot get my head arround, how to do that whidj Django's CheckConstraint, any ideas?
snippet:
class RatedAttribute(models.Model):
TYPE = (
('attribute1', 'attribute1'),
('attribute2', 'attribute2'),
)
id = models.IntegerField(primary_key= True, auto_created=True)
type = models.CharField(max_length=120, choices=TYPE, default=None)
value = models.IntegerField()
class Rating(models.Model):
user_id = models.ManyToManyField(User, through='RatingUser')
rated_object_id = models.ManyToManyField(RatedObject, through='Rating_Object')
attribute1 = models.ForeignKey(RatedAttribute, on_delete=models.CASCADE)
attribute2 = models.ForeignKey(RatedAttribute, on_delete=models.CASCADE)
class Meta:
constraints = [
CheckConstraint(
*NO IDEA HOW TO FILL THIS CONSTRAINT(s)*, name='something')
]
def __str__(self):
return self.place
code is with proper connecting Rating_Object
This is what i came up with after reading what you put in the comments.
If anything comment on this answer.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
rating_choices = [
(1, '1 Star'),
(2, '2 Stars'),
(3, '3 Stars'),
(4, '4 Stars'),
(5, '5 Stars'),
]
class Product(models.Model):
class Meta:
verbose_name = "Product"
verbose_name_plural = "Products"
name = models.CharField(max_length=50)
description = models.TextField()
def __str__(self):
return self.name
class Rating(models.Model):
class Meta:
verbose_name = "rating"
verbose_name_plural = "ratings"
user = models.ForeignKey(User, verbose_name=_(""), on_delete=models.CASCADE, related_name="rating")
product = models.ForeignKey(Product, verbose_name=_(""), on_delete=models.CASCADE, related_name="product_rating")
taste = models.IntegerField(choices=rating_choices)
smell = models.IntegerField(choices=rating_choices)
def __str__(self):
return "{self.user.username}'s rating for {self.product.name}"
There are two tables
Hookahs and tobacco for example
and for the basket model, you need to combine these two models, help
For example:
class Hookah(model.Model):
name = models.Charfield()
description = .....
price = .......
class Tabacco(model.Model):
name = models.Charfield()
description = .....
price = .......
and OrderItem model:
class OrderItem(model.Model):
and here I need to pass the top two models, as a product, how to do it?
i.e. combine Hookah and Tabacoo into one
please help me
If I understand correctly, you want a Basket model that stores a link to other types? You can do that by creating a parent model that each shopping item inherits from, or you can do it by using a GenericForeignKey which allows pointing to any model object. The shared parent model is probably better as you don't have to duplicate code for shopping items such as name, price, etc.
class ShoppingItem(model.Model)
name = models.Charfield()
description = .....
price = .......
class Hookah(ShoppingItem):
height = ....
class Tabacco(ShoppingItem):
flavour = ....
Then you can do something like one of the following:
class OrderItem(model.Model): # info on a single ordered item
item = models.ForeignKey(ShoppingItem, on_delete=models.DO_NOTHING)
class Basket(model.Model): # basket of many `ShoppingItem`
items = models.ManyToManyField(ShoppingItem)
I think in this case, you should probably look at building a single product model and have a type attribute separate the product types. That way you can FK to a single product model with your order item model.
Something like this:
models.py
class Type(models.Model):
...
name = models.CharField(max_length=50)
...
class Product(models.Model)
name = models.CharField(max_length=150)
description = models.TextField()
type = models.ForeignKey(Type, on_delete=models.DO_NOTHING)
class Order(models.Model):
...
product = models.ForeignKey(Product, on_delete=models.DO_NOTHING)
....
The case is I have a model User which is the teacher and student and I differ between them using a flag type, Now Teachers may have many students and vice versa so..
Which is better as a performance
Case 1:
class UserAccount(AbstractUser):
type = models.PositiveSmallIntegerField(choices=TYPES, default=1)
grp = models.ManyToMany("self",blank=True)
Case 2:
class UserAccount(AbstractUser):
type = models.PositiveSmallIntegerField(choices=TYPES, default=1)
class Group(models.Model):
teacher = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='students')
student = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='teachers')
For sure I can handle this based on the type in the form.. etc, but
Now I can't determine which is better as a performance and code modularity
I have a situation where i need to store a table of "Product"'s and a table of "Order"'s on these products.
One order consists of many ("Product", "Quantity") tuples where quantity is a float expressed in tonnes.
I considered the followng implementation, but i don't think having a table of arbitrary products and quantities would be a very good design decision.
class Product(models.Model):
name = models.CharField("Name", max_length=50)
description = models.TextField("Description", blank=True)
class ProductOrder(models.Model):
unit = "tonnes"
product = models.ManyToManyField('Product')
quantity = models.FloatField('Quantity')
class Order(models.Model):
products = models.ManyToManyField('ProductOrder')
date = models.DateField('Date')
Am I overlooking an obvious solution? How would you implement this relationship to lead to the most DRY code. (PS. I don't want to have separate lists of products and quantities and have to rely implicitly on their ordering.)
In django, you can use through to create such intermediate table and maintain order specific attributes in there.
You can implement it as
class Product(models.Model):
name = models.CharField("Name", max_length=50)
description = models.TextField("Description", blank=True)
class Order(models.Model):
products = models.ManyToManyField('Product', through="OrderDetail")
date = models.DateField('Date')
class OrderDetail(models.Model):
unit = "tonnes"
product = models.ForeignKey('Product')
order = models.ForeignKey('Order')
quantity = models.FloatField('Quantity')
The documentation explains how to use and work with such design.
Just stumbled upon some guy code
He have models like this
class Country(models.Model):
name = models.CharField(max_length=100)
class TourDate(models.Model):
artist = models.ForeignKey("Artist")
date = models.DateField()
country = models.ForeignKey("Country")
And is querying like this
ireland = Country.objects.get(name="Ireland")
artists = Artist.objects.all().extra(select = {
"tourdate_count" : """
SELECT COUNT(*)
FROM sandbox_tourdate
JOIN sandbox_country on sandbox_tourdate.country_id = sandbox_country.id
WHERE sandbox_tourdate.artist_id = sandbox_artist.id
AND sandbox_tourdate.country_id = %d """ % ireland.pk,
}).order_by("-tourdate_count",)
My question is why He have underscores like sandbox_tourdate but it isn't in model field
Is that created automatically like some sort of pseudo-field?
sandbox_tourdate isn't the name of the field, it's the name of the table. Django's naming convention is to use appname_modelname as the table name, although this can be overridden. In this case, I guess the app is called 'sandbox'.
I don't really know why that person has used a raw query though, that is quite easily expressed in Django's ORM syntax.