Django search for child models via foreign key - django

I have a models.py file that more or less looks like this:
class Match(models.Model):
match_id = models.BigIntegerField()
class Team(models.Model):
team_id = models.CharField(max_length=4)
match = models.ForeignKey(
Match,
related_name='teams',
on_delete=models.CASCADE,
)
win = models.BooleanField()
class Player(models.Model):
player_id = models.IntegerField()
team = models.ForeignKey(
Team,
related_name='players'
on_delete=models.CASCADE,
)
For each match, I want to find the two teams that played, and for each team, I want to find the players that were on the team. This is what I tried so far:
match_id = 123456789
match_info = Match_model.objects.get(match_id=match_id)
red_info = Team_model.objects.get(match=match_info, team_id='Red')
blue_info = Team_model.objects.get(match=match_info, team_id='Blue')
red_players = Player_model.objects.filter(team=red_info)
blue_players = Player_model.objects.filter(team=blue_info)
but Django is giving me the error:
Team matching query does not exist.
How would I go about fixing this error? Any pointers on how to correct my queries would be greatly appreciated!

try:
red_info = Team_model.objects.get(match=match_info, team_id='Red')
blue_info = Team_model.objects.get(match=match_info, team_id='Blue')
except Team_model.DoesNotExist:
pass
else:
red_players = Player_model.objects.filter(team=red_info)
blue_players = Player_model.objects.filter(team=blue_info)

Related

Complex django annotation

I have the following models:-
class Group(models.Model):
name = models.CharField(max_length=200)
class Game(models.Model):
group = models.ForeignKey(Group, related_name='games')
date = models.DateField()
players = models.ManyToManyField(
Player, through='GameMembership', related_name='games'
)
class GameMembership(models.Model):
game = models.ForeignKey(Game, related_name='memberships')
player = models.ForeignKey(Player, related_name='memberships')
selected = models.BooleanField(default=False)
injured = models.BooleanField(default=False)
class Player(models.Model):
group = models.ForeignKey('groups.Group', related_name='players')
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='players')
I want to annotate all of the players in the group with a score which is calculated as follows:-
For the last 10 games for which a player wasn't injured, score 5 if they were selected.
I can do this using Sum/Case/When if I ignore the "wasn't injured" clause, by using a manager method on Player which looks something like this:-
def with_availability_scores(self, group):
for_games = group.games.reverse()[:10]
return self.annotate(
availability_score=Sum(Case(
When(
memberships__selected=True, memberships__game__in=for_games,
then=5)
default=0, output_field=IntegerField()))
)
But the addition of the "injured" clause means that I can't use that for_games variable like that to begin with.
I suspect it can be done using Subquery and OuterRef but I can't quite figure out the exact syntax I need.
Any ideas?

How to represent join queries in Django?

How do we present sql query like this one in django?
select * from question LEFT JOIN (select * from question_solved where username = 'ashu'
) AS result on question.q_id = result.q_id
I tried to perform query separately,
q = question_solved.objects.filter(username='ashu')
y = Question.objects.filter(q__q_id = Question.q_id)
But it is giving me error
django.core.exceptions.FieldError: Cannot resolve keyword 'q' into field. Choices are: q_answer, q_content, q_id, q_submission, q_tags, q_title, q_type
my model file
from django.db import models
# Create your models here.
class Question(models.Model):
q_id = models.CharField(primary_key=True, max_length=20)
#q_difficulty = models.IntegerField()
q_title = models.CharField(max_length = 200)
q_content = models.CharField(max_length = 1000)
q_type = models.IntegerField()
q_answer = models.FloatField()
q_submission = models.IntegerField()
q_tags = models.CharField(max_length=10)
class Student(models.Model):
username = models.CharField(primary_key=True, max_length=30)
password = models.CharField(max_length=200)
class question_solved(models.Model):
q_id = models.CharField(primary_key=True, max_length=20)
username = models.CharField(max_length=30)
Query will produce result like this.
Thanks in advance.
You should use ForeignKey to relate models .
From what I understood you want to get all the questions solved by username ashu.
In your current state of models you can do this like:
First get a list of q_id values that are in the table for username ashu. you can do that using values_list():
quest=question_solved.objects.filter(username='ashu').values_list('q_id',flat=True)
Then from the Question table filter the objects with q_id in the list obtained from previous query.
solved_questions=Question.objects.filter(q_id__in=quest)
You can get all the question with all()
all_questions = Question.objects.all()
and if you want you can have 2 separate queryset one which is a list of question solved by 'ashuand other which is not solved byashu`.
unsolved_questions=Question.objects.exclude(q_id__in=quest).

Django: select data from 2 models

Good day!
I have 2 models and I am trying to get sql equivalent of : select * from both models where order=xx. Appreciate little assistance :)
class Orders(models.Model):
order_id = models.AutoField(primary_key=True)
created = models.DateTimeField(auto_now_add=True)
class ResourcePool(models.Model):
email = models.EmailField()
item_a = models.CharField()
item_b = models.CharField()
item_c = models.CharField()
order_id = models.ForeignKey(Orders)
Tried the following, but it does not inlude fields from 'Orders' model
ResourcePool.objects.filter(order_id__pk=26).values()
ResourcePool.objects.filter(order_id__pk=26).select_related().values()
ResourcePool.objects.filter(order_id__pk=26).values('orders__created','email','item_a',item_b','item_c')
try this
try this
order = Orders.objects.get(pk=26)
resource=ResourcePool.objects.filter(order_id=order.id).select_related()
And to obtain the data of "Orders"
id_order_pk26 = resource.order_id.order_id
created_pk26 = resource.order_id.created

How would I do this query in Django?

So let's say I have three models: User, CarBrand, CarModel, CarCharacteristics. The CarCharacteristics model describes how a user rates the characteristics of a car. So there can be many CarCharacteristics objects for a user, and a user can have many CarCharacteristics.
This is what my models look like:
class User(models.Model):
id = models.AutoField(primary_key=True)
class CarBrand(models.Model):
idcar_brand = models.AutoField(primary_key=True)
class CarModel(models.Model):
idcar_model = models.AutoField(primary_key=True)
car_brand = models.ForeignKey(CarBrand, null=True, on_delete=models.SET_NULL)
class CarCharacteristics(models.Model):
idcar_characteristics = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.PROTECT)
car_model = models.ForeignKey(CarModel, on_delete=models.PROTECT)
What I would like to do is to get all CarBrand objects where a User has a CarCharacteristics. This is what am I doing right now:
car_chars = CarCharacteristics.objects.filter(user=user_id)
car_brands_ids = []
for car_char in car_chars:
brand_id = car_char.car_model.car_brand.idcar_brand
if brand_id not in car_brands_ids:
car_brands_ids.append(brand_id)
brands = CarBrand.objects.filter(idcar_brand__in=brand_ids)
Is there a simpler way of doing this? And how do I get all the CarModels where there exists a CarCharacteristics?
Try this:
CarBrand.objects.exclude(carmodel__carcharacteristics__user=None).distinct()
I think I figured it out. I think this works:
user_id = request.user.pk
brands = CarBrand.objects.exclude(~Q(carmodel__carcharacteristics__user=user_id))
EDIT
Is what I have above also equivalent to this:
user_id = request.user.pk
car_models = CarModel.objects.filter(carcharacteristics__user=user_id)
brands = CarBrand.objects.filter(carmodel__in=car_models).distinct()
CarBrand.objects.filter(carmodel__carcharacteristics__user=request.user).distinct()

Django getting field names from different models

Guys,
Is there an easy way to return different fields names from different models by chaining joins?
My model:
Class Item(models.Model):
item_code = models.CharField(max_length=10)
name = models.CharField(max_length=255)
...
Class Stock(models.Model):
item_code = models.ForeignKey( Item )
userid = models.ForeignKey( User )
qty = models.IntegerField()
...
I want to select " Item.Item_code, Item.name, Stock.qty where Stock.userid=2 and Item.item_code = Stock.Item_Code"
How do i do this in Django?
Gath
I want to select " Item.Item_code, Item.name, Stock.qty where Stock.userid=2 and Item.item_code = Stock.Item_Code"
You can pick these specific fields only using one SQL, provided you start from the Stock model. For instance
q = Stock.objects.select_related('userid', 'item_code').filter(
userid__id = 2).values('item_code__item_code', 'item_code__name', 'qty')
This will help if you want to limit the data and then number of queries. If you are not concerned with this then do:
q = Stock.objects.filter(userid__id = 2)
for stock in q:
print stock.item_code.item_code
print stock.item_code.name
print stock.qty
This will return a queryset with only those fields you have chose using values. You can then iterate through it.
PS: Re: your models.
Class Stock(models.Model):
item_code = models.ForeignKey( Item )
userid = models.ForeignKey( User )
qty = models.IntegerField()
...
It is a good idea to use the model name in lower case for FK relationships. For e.g. you ought to write:
Class Stock(models.Model):
item = models.ForeignKey( Item ) # Changed
user = models.ForeignKey( User ) # Changed
qty = models.IntegerField()
...
You can also use this:
Stock.objects.filter(user=2).values('item__item_code', 'item__name')
First of all change fileds names
Read this very carefuly http://docs.djangoproject.com/en/dev/ref/models/querysets/
Class Item(models.Model):
item_code = models.CharField(max_length=10)
name = models.CharField(max_length=255)
...
Class Stock(models.Model):
item = models.ForeignKey( Item )
user = models.ForeignKey( User )
qty = models.IntegerField()
...
#view
stocks = Stock.objects.filter(user=2)
for stock in stocks:
print stock.item.item_code, stock.item.name
#one query version