Django : ManyToMany, Who is the most efficient? - django

I hesitate between two conceptions of my models.
In my website, there are football teams. These teams contains coachs, players, directors... etc.
Currently, I modeled this like that (1) :
class Team(models.Model):
name = models.CharField(max_length=25,primary_key=True)
class Chief(models.Model):
created_at = models.DateField(auto_now_add=True)
team = models.ForeignKey(Team, null=False,on_delete=models.CASCADE)
user = models.ForeignKey(User, null=False,on_delete=models.CASCADE)
class Player(models.Model):
created_at = models.DateField(auto_now_add=True)
team = models.ForeignKey(Team, null=False,on_delete=models.CASCADE)
user = models.ForeignKey(User, null=False,on_delete=models.CASCADE)
position = models.CharField(max_length=30) #3 positions posible
class Director(models.Model):
created_at = models.DateField(auto_now_add=True)
team = models.ForeignKey(Team, null=False,on_delete=models.CASCADE)
user = models.ForeignKey(User, null=False,on_delete=models.CASCADE)
The problem is when I want to get all members of a team (chiefs, directors and players), I have to execute 3 requests.
But the advantage is when I want just all directors, I just search in Director entity !
I hesitate to delete these 3 models (Director, Player and Chief) and make 3 relations ManyToMany in Team like that (2) :
class Team(models.Model):
name = models.CharField(max_length=25,primary_key=True)
chiefs = models.ManyToManyField(User)
directors = models.ManyToManyField(User)
players_position1 = models.ManyToManyField(User)
players_position2 = models.ManyToManyField(User)
players_position3 = models.ManyToManyField(User)
Which is the most efficient way between the (1) and the (2) ?

You can use model inheritance
models.py
class TeamMember(models.Model):
created_at = models.DateField(auto_now_add=True)
team = models.ForeignKey(Team, null=False,on_delete=models.CASCADE)
user = models.ForeignKey(User, null=False,on_delete=models.CASCADE)
class Chief(TeamMember):
pass
class Director(TeamMember):
pass
class Player(TeamMember):
position = models.CharField(max_length=30)
views.py
#Get all members
members = TeamMember.objects.all()
#Only players
players = Player.objects.all()

class Team(models.Model):
name = models.CharField(max_length=25,primary_key=True)
class MemberQuerySet(models.QuerySet):
def chiefs(self):
return self.filter(position='a')
def directors(self):
return self.filter(position='b')
def players(self):
return self.filter(position__in=['c', 'd', 'e'])
class Member(models.Model):
created_at = models.DateField(auto_now_add=True)
team = models.ForeignKey(Team, models.CASCADE, related_name="members")
user = models.ForeignKey(User, models.CASCADE)
position = models.CharField(max_length=1, choices=(
('a', 'chief'),
('b', 'director'),
('c', 'player position 1'),
('d', 'player position 2'),
('e', 'player position 3'))
objects = MemberQuerySet.as_manager()
Now you can get all members of a team or just the players with just one hit on the database
members = Team.objects.get(pk='someteam').members
players = Team.objects.get(pk='someteam').members.players()

Related

I want to list all elements from abstract class Product and its categories (Smartphones, Tv ) etc

class ProductSerizer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(queryset=Category.objects)
title_of_product = serializers.CharField(required=True)
slug = serializers.SlugField(required=True)
image_of_product = serializers.ImageField(required=True)
description_of_product = serializers.CharField(required=True)
price_of_product = serializers.DecimalField(max_digits=12, decimal_places=2, required=True)
class Product(models.Model):
class Meta:
abstract = True
category = models.ForeignKey(Category, verbose_name="category", on_delete=models.CASCADE)
title_of_product = models.CharField(max_length=225,verbose_name="Title",null=True)
slug = models.SlugField(unique=True)
image_of_product = models.ImageField(verbose_name="Image", null=True)
description_of_product = models.TextField(verbose_name = "Descripwtion", null = True)
price_of_product = models.DecimalField(max_digits=10,decimal_places=2, verbose_name="Price", null=True)
and I want to list all elements from categories, but I cannot serialize this class. How should I do ?
Take a look at this thread, which talks about abtract models and how to serialize them

hi want to show the names from other classes to the Basic class

but when i run it i shows errors that it cant find the muscel_id i Muscel class, how can i show only the names. i ma trying to build a workout plan using django
class Days(models.Model):
day_name = models.CharField(max_length=60)
class Muscel(models.Model):
Muscel_name = models.CharField(max_length=60)
class Exercise(models.Model):
exercise_name = models.CharField(max_length=70)
class Basic(models.Model):
dagen_basic = models.ForeignKey(Days, related_name='days_basic', on_delete=models.CASCADE)
muskel = models.ForeignKey(Muscel.Muscel_name, related_name='muskel_basic',
on_delete=models.CASCADE)
exercise_name = models.ForeignKey(Exercise.exercise_name, related_name='exercise_name_basic',
on_delete=models.CASCADE)
reps = models.CharField(max_length=20)
sets = models.IntegerField()
try this:
class Muscel(models.Model):
muscel_name = models.CharField(max_length=60)
def __str__(self):
return self.muscel_name
add str on your Muscel model,
class Basic(models.Model):
......
muskel = models.ForeignKey(Muscel, related_name='muskel_basic',
on_delete=models.CASCADE)
exercise_name = models.ForeignKey(Exercise, related_name='exercise_name_basic',
on_delete=models.CASCADE)
......
remove .Muscel_name on ForeignKey

Django - Filter objects from another model

Sorry if it's a bad name for a title, but I'm not sure how to explain this. I would like to make a form for entry into the Captains model, however there needs to be a queryset filter so you can only select players from a user's FantasyTeam.
I have the models as follows:
class Player(models.Model):
player_id = models.IntegerField(primary_key=True)
team = models.ForeignKey(Team)
player_name = models.CharField(max_length=140)
position = models.CharField(max_length=10)
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
known_name = models.CharField(max_length=70,blank=True)
birth_date = models.DateField('birth date')
weight = models.IntegerField()
height = models.IntegerField()
jersey_num = models.IntegerField()
real_position = models.CharField(max_length=25)
join_date = models.DateField('join date')
country = models.CharField(max_length=30)
value = models.DecimalField(max_digits=3,decimal_places=1)
is_active = models.BooleanField(default=False)
def __str__(self):
return '%s (%s)' % (self.player_name,self.value)
class FantasyTeam(models.Model):
FANTASY_TEAM_ID = models.AutoField(primary_key=True)
team_name = models.CharField(max_length=25)
player1 = models.ForeignKey(Player, related_name='csplayer1')
player2 = models.ForeignKey(Player, related_name='csplayer2')
player3 = models.ForeignKey(Player, related_name='csplayer3')
player4 = models.ForeignKey(Player, related_name='csplayer4')
player5 = models.ForeignKey(Player, related_name='csplayer5')
player6 = models.ForeignKey(Player, related_name='csplayer6')
player7 = models.ForeignKey(Player, related_name='csplayer7')
player8 = models.ForeignKey(Player, related_name='csplayer8')
player9 = models.ForeignKey(Player, related_name='csplayer9')
player10 = models.ForeignKey(Player, related_name='csplayer10')
player11 = models.ForeignKey(Player, related_name='csplayer11')
player_sub_gk = models.ForeignKey(Player, related_name='cssubgk')
player_sub_1 = models.ForeignKey(Player, related_name='cssub1')
player_sub_2 = models.ForeignKey(Player, related_name='cssub2')
player_sub_3 = models.ForeignKey(Player, related_name='cssub3')
def __str__(self):
return '%s' % (self.team_name)
class Captains(models.Model):
fantasy_team = models.OneToOneField(ClassicSeasonFantasyTeam,primary_key=True)
captain = models.ForeignKey(Player, related_name='cscaptain')
vice_captain = models.ForeignKey(Player, related_name='csvicecaptain')
#Associates a user with a FantasyTeam
class ClassicSeasonUserTeam(models.Model):
CS_USER_TEAMS_ID = models.AutoField(primary_key=True)
fantasy_team = models.ForeignKey(ClassicSeasonFantasyTeam)
user = models.ForeignKey(User)
total_score = models.IntegerField(default=0)
season = models.ForeignKey(Season)
def __str__(self):
return '%s' % (self.user.username)
How can I achieve the queryset filter?
forms.py
class CaptainsForm(ModelForm):
class Meta:
model = ClassicSeasonCaptains
def __init__(self,*args,**kwargs):
super(ClassicSeasonCaptains,self).__init__(*args,**kwargs)
#filter to players that are only in the user's fantasy team
self.fields['captain'].queryset = ClassicSeasonFantasyTeam.objects.filter()????
self.fields['vice_captain'].queryset = ?????
If I understand correctly you want to limit the choices for a field in the form. The answer to that question is already given and is really good, see: https://stackoverflow.com/a/3420588/2583290
As for the Queryset filter itself, you want Players, so start with Player.objects.filter(). For the actual filter query you'll need to clean your code a bit first. It's would be overly complex because of how Players are linked to your FantasyTeam.
Consider having A class TeamPlayer with a role ("normal", "sub", "captain"). Read up in the django docs
PS: Avoid using plural class names. Use Captain instead of Captains.
PPS: Captain(s) should probably inherit from Player or a Person class rather than have a ForeignKey

django: getting foreign key information

I created a model with couple of classes and with foreign key and I was able to save it on the database.
I have the following models:
class Player_Bios(models.Model):
my_id = models.SlugField(unique=True)
player_id = models.IntegerField(max_length=50, unique=True)
name = models.CharField(max_length=50)
last = models.CharField(max_length=50)
middle = models.CharField(max_length=50, blank=True)
class BatStat (models.Model):
player_id = models.ForeignKey('Player_Bios')
team_id = models.ForeignKey('Team')
bat_stat_id = models.CharField(max_length=50, unique=True)
sport_code = models.CharField(max_length=50, blank=True)
ab = models.IntegerField(max_length=50, null=True)
class Team (models.Model):
team_id = models.IntegerField(max_length=50, unique=True)
team_short = models.CharField(max_length=50, blank=True)
team_full = models.CharField(max_length=50, blank=True)
When I save it to the database I can see that the team_id on the Team table is the same as the team_id on the BatStat table, but the player_id on the BatStat is different that the player_id on the Player_Bios table. This is how I save the data to the database:
p_id = Player_Bios.objects.get(player_id=st['player_id'])
t_id = Team.objects.get(team_id=st['team_id']) #I get the team_id from the Team Class
bat_id = str(st['season'])+ str(st['team_seq'])
bat_id = str(p_id.player_id) + bat_id
c = BatStat(player_id = p_id,team_id=t_id, bat_stat_id=bat_id, sport_code =st["sport_code"],ab=st['ab'])
c.save()
st['player_id'] is a dictionary. I did a print and it show the right player_id number
In BatStat you are storing the key to Player_Bios, which is not player_id
class Player_Bios(models.Model):
...
player_id = models.IntegerField(max_length=50, unique=True)
class BatStat (models.Model):
...
player_id = models.ForeignKey('Player_Bios')
I'm not sure why your team_id is the same, however, it seems like you already have the ids. You could avoid looking up the Player_Bios and Team by setting the id directly.
Django: Set foreign key using integer?
class Player_Bios(models.Model):
...
player_id = models.IntegerField(primary_key=True, max_length=50)
class Team (models.Model):
...
team_id = models.IntegerField(primary_key=True, max_length=50)
class BatStat (models.Model):
...
player = models.ForeignKey('Player_Bios') # notice i renamed this to not have '_id'
team = models.ForeignKey('Team') # notice i renamed this to not have '_id'
c = BatStat(bat_stat_id=bat_id,
sport_code =st["sport_code"],
ab=st['ab'])
c.player_id = st['player_id'], # notice that this has '_id'
c.team_id = st['team_id'], # notice this has '_id'
c.save()

Display data from another model in admin panel

How to display in OrderAdmin: Basket owner, products, quantity of products?
I try Inline:
admin.py:
class BasketInline(admin.TabularInline):
model = Basket
class OrderAdmin(admin.ModelAdmin):
inlines = [
BasketInline,
]
admin.site.register(Order, OrderAdmin)
but it does not work.
class Basket(models.Model):
owner = models.ForeignKey(User, related_name='user_basket', verbose_name='Owner')
name = models.CharField("Basket_Name", max_length=30)
products = models.ManyToManyField('Product', through='BasketProduct', blank=True, null=True)
class BasketProduct(models.Model):
product = models.ForeignKey('Product')
basket = models.ForeignKey('Basket')
quantity = models.IntegerField()
class Product(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField()
unit_price = models.DecimalField(max_digits=5, decimal_places=2)
desc = models.TextField()
category = models.ManyToManyField(Category)
class ShippingOptions(models.Model):
name = models.CharField(max_length=50)
price = models.DecimalField(max_digits=5, decimal_places=2)
time = models.CharField(max_length=150)
class Order(models.Model):
bask = models.OneToOneField(Basket)
shipp = models.OneToOneField(ShippingOptions)
Maybe I need a different way. Please any help. Thanks
You need foreignKey on Order in you Basket model:
class Basket(models.Model):
owner = models.ForeignKey(User, related_name='user_basket', verbose_name='Owner')
name = models.CharField("Basket_Name", max_length=30)
products = models.ManyToManyField('Product', through='BasketProduct', blank=True, null=True)
owner = models.ForeignKey(Owner, blank=True, verbose_name='Owner')
or you have error in first model row:
owner = models.ForeignKey(Owner, related_name='user_basket', verbose_name='Owner')