Django getting field names from different models - django

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

Related

How to access the value of a foreign key in a table in django?

I've 2 tables in a database on phpmyadmin that are connected by a foreign key. The table "bulle" contains the foreign key of the table "site". In enghlish : one "site" can contain some "bulles" (or not) and a "bulle" is always linked to a "site".
class Bulles(models.Model):
id_bulle = models.AutoField(primary_key=True)
num_bulle = models.CharField(max_length=20)
type_bulle = models.CharField(max_length=20)
colories = models.CharField(max_length=20)
latitude = models.FloatField()
longitude = models.FloatField()
date_vidange = models.DateField(
db_column="date_vidange"
)
id_depot = models.ForeignKey(
"Depot", on_delete=models.CASCADE, db_column="id_depot"
)
id_site = models.ForeignKey(
"Site",related_name='bul', on_delete=models.CASCADE, db_column="Id_site"
)
class Meta:
db_table = "bulles"
class Site(models.Model):
id_site = models.AutoField(
db_column="Id_site", primary_key=True
)
nom = models.CharField(
db_column="Nom", max_length=100
)
vitesse_b = models.FloatField(db_column="Vitesse_b") # Field name made lowercase.
vitesse_c = models.FloatField(db_column="Vitesse_c") # Field name made lowercase.
ecart_type_b = models.FloatField(
db_column="Ecart_type_b"
)
ecart_type_c = models.FloatField(
db_column="Ecart_type_c"
)
type_site = models.CharField(
db_column="Type_site", max_length=20
)
longitude = models.FloatField(db_column="Longitude")
latitude = models.FloatField(db_column="Latitude")
Nombre_bulles = models.IntegerField(db_column="Nombre_bulles")
date_vidange = models.DateField(
db_column="Date_vidange")
class Meta:
db_table = "site"
I've created a request to delete a row in "bulle" selected by the id_bulle (primary key). I'd like to get the "id_site" from this selected bulle that I delete in this request. Then, I need to count every "bulles" of the table that have this id_site. After that I would like to change the value of the column "Nombre_bulles" by the number found just before.
def DeleteBulle (request, id_bulle):
try:
id_bulle
param = Bulles.objects.get(pk=id_bulle)
param.delete()
print("Bulle supprimée")
except:
print("Cette bulle n'existe pas")
return redirect('api_bulles_frontend')
return redirect('api_bulles_frontend')
I don't know how to access the value of the Id_site of the "bulle" I'm deleting selected by its id.
I'm sorry for my english, I hope someone here can help me.
Thanks !
I really don't know how I could do that, I can't find it on Internet.
param.id_site.somethingFromTheClass

Django queryset annotation returning grouped counts

I am using Django 3.2
models.py
class AwardCategory(models.Model)
name = models.CharField(max_length=16)
slug = models.SlugField(max_length=16, unique=True, db_index=True)
class Award(models.Model):
name = models.CharField(max_length=16)
category = models.ForeignField(AwardCategory, on_delete=models.CASCADE)
class CeremonyAward(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="awards", on_delete=models.CASCADE )
award = models.ForeignKey(Award, related_name="ceremonies", on_delete=models.CASCADE )
I want to write a query that returns for a specified user (or list of user_ids):
award_category:
name
number_of_awards_in_category
I know I have to use annotations, but I'm quite new to annotations.
This is what I have so far:
user_ids = (someuser.id,)
CeremonyAward.objects.filter(user_id__in=user_ids).\
annotate(Count('award__category__slug', distinct=True)).\
prefetch_related('award','award_category')
How do I create a query that groups by award__category and then counts the awards in each distinct category

Is possible add a subquery with anothers relationships in django orm annotate

I have a View to show my total stock by "point of sale".
My problem is a new table added and I have put a more field in my View (counting total of reserved products).
My actual scenario:
Tables
class SalePoint(models.Model):
location = models.CharField(max_length=200, verbose_name='Local')
[...]
class Box(models.Model):
sale_point = models.ForeignKey(
[...]
related_name='boxes',
[...]
)
product = models.ForeignKey(
[...]
related_name='boxes',
[...]
)
amount = models.PositiveSmallIntegerField()
capacity = models.PositiveSmallIntegerField()
class Product(models.Model):
name = models.CharField()
sku = models.CharField()
View
SalePointStockViewSet(viewsets.ModelViewSet):
def list(self, request):
queryset = (
SalePoint.objects.values(
'location',
'boxes__product__name'
).annotate(
total_amount=Sum('boxes__amount'),
total_capacity=Sum('boxes__capacity'),
)
.order_by('location', 'total_amount')
)
return Response(queryset)
As I had said, my view works fine. I need to include a new field "reserved" in my queryset.
Reserved is a sum of total ordered products with status "waiting" from this table:
class Order(models.Model):
WAITING = 'WAIT'
DELIVERED = 'DELI'
STATUS_CHOICES = [
(WAITING, 'Waiting'),
(DELIVERED, 'Delivered'),
]
sale_point = models.ForeignKey(
[...]
related_name='orders',
[...]
)
product_sku = models.CharField()
status = models.CharField(
[...]
choices=STATUS_CHOICES,
)
What am I thinking
I'm thinking if it's possible to add the "reserved" field and fill it with a "subquery". The problem is that I have to filter the product by "sku". I don't know if this would be the best way.

Django generic foreign key reverse filter

I have a model called "Comments" which uses a generic foreign key:
class CommentManager(models.Manager):
def for_model(self, model):
"""
QuerySet for all comments for a particular model (either an instance or
a class).
"""
ct = ContentType.objects.get_for_model(model)
qs = self.get_query_set().filter(content_type=ct)
if isinstance(model, models.Model):
qs = qs.filter(object_pk=force_text(model._get_pk_val()))
return qs
class Comment(models.Model):
"""
A user comment about some object.
"""
status = models.CharField(max_length=12, blank=True, null=True)
sub_status = models.CharField(max_length=500, blank=True, null=True)
comment = models.TextField()
content_type = models.ForeignKey(
ContentType,
verbose_name=_('content type'),
related_name="content_type_set_for_%(class)s")
object_pk = models.TextField(_('object ID'))
content_object = generic.GenericForeignKey(ct_field="content_type",
fk_field="object_pk")
One of the things you can put comments on are Tickets:
class Ticket(CommonModel):
type = models.ForeignKey(TicketType)
priority = models.PositiveSmallIntegerField()
status = models.ForeignKey(TicketStatus)
access_serial_number = models.PositiveSmallIntegerField(null=True)
parent = models.ForeignKey('self', null=True, related_name='child')
submitted = models.DateTimeField()
I do a lot of filtering of Tickets - in the past all I did with Comments on Tickets is that when I displayed a Ticket, I used Comments.objects.for_model(ticket) to find all the Comments for it. But now what I want to do is find Tickets that have a specific text in the comment. There is no comment_set or equivalent with GenericForeignKey.
This is what I've come up with, but it's pretty horrible:
comment_ticket_ids = [int(c.object_pk) for c in Comment.objects.for_model(Ticket).filter(comment__icontains='error')]
tickets = Ticket.filter(status=open_status, id__in=comment_ticket_ids)
There must be a better way.
Perhaps you could add something using .extra() to help. Instead of
comment_ticket_ids = [int(c.object_pk) for c in Comment.objects.for_model(Ticket).filter(comment__icontains='error')]
tickets = Ticket.filter(status=open_status, id__in=comment_ticket_ids)
You could attach the field id_wanted:
extra_select = {
'id_wanted': 'CASE WHEN (SELECT COUNT(*) FROM tickets WHERE comments something) > 0 THEN TRUE ELSE FALSE END'
}
Then filter for tickets with the extra select:
tickets = Tickets.objects.filter(ticket__status=open_status, id_wanted__isnull=False).extra(extra_select)
It's not fully clear to me why you can't have a FKey relationship between these two models.

Calculating score by counting and subtracting foreign key instances in Django

I have a class Summary:
class Summary(models.Model):
title = models.CharField(max_length=128)
category = models.ForeignKey(Category)
subcategory = models.ForeignKey(Subcategory)
content = RichTextField(null=True, blank=True)
users_rated_positive = models.ManyToManyField(
User, blank=True, related_name='summaries_rated_positive')
users_rated_negative = models.ManyToManyField(
User, blank=True, related_name='summaries_rated_negative')
author = models.ForeignKey(User, related_name='summaries_authored')
and a class UserProfile:
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True, related_name='profile')
karma = models.IntegerField(default=0)
rank = models.IntegerField(null=True,blank=True)
I want the karma to be calculated as the positive ratings on all the users summaries minus the negative ratings on all the users summaries
I figured I could add a property like this instead of a field:
#property
def karma(self):
summaries_list = self.user.summaries_authored.all()
positive_karma = sum(
[summary.users_rated_positive.count() for summary in summaries_list])
negative_karma = sum(
[summary.users_rated_negative.count() for summary in summaries_list])
return positive_karma - negative_karma
Is this the right way to do this? I feel like I should be using aggregate, or annotate but to be honest I'm new to Django and not entirely sure how they work for complex situations.
from django.db.models import Count
positive_karma = Summary.objects.filter(author=self.user).aggregate(pos_count=Count('users_rated_positive'))['pos_count']
negative_karma = Summary.objects.filter(author=self.user).aggregate(neg_count=Count('users_rated_negative'))['neg_count']
aggregate returns a dict so the actual value must be retrieved by the key
You would use annotate if you wanted to get the count of pos/neg ratings for every user.