I Have a models like this :
class Person(models.Model):
person_id=models.AutoField(primary_key=True)
person_name=models.CharField(max_length=100)
person_family=models.CharField(max_length=100)
person_father=models.ForeignKey('Person', related_name='child_from_father',null=True)
person_mother=models.ForeignKey('Person', related_name='child_from_mother',null=True)
def __str__(self):
return self.person_family
class Car(models.Model):
car_id=models.AutoField(primary_key=True)
car_name=models.CharField(max_length=100)
car_owner=models.ForeignKey(Person)
def __str__(self):
return self.car_name
there is some query that i want the orm form :
1: select person_name from Person
2: select *
from Person,Car
where car_owner=person_id
3: select *
from Person,Car
group_by(person_name)
4: select *
from Person,Car
where name like %x%
group_by(person_name)
having car_id >= 2
and at last do u know any good refrence for orm
thx for help
I'm assuming the group by is for ordering. If you really want group_by look at aggregates and annotate in django. My guess of what you are looking for is:
1: Get the person record - select person_name from Person
person = Person.objects.get(<WHERE clause>).values('person_name')
2: select *
from Person,Car
where car_owner=person_id
Get the cars belonging to the person
cars = Car.objects.filter(car_owner = person)
3: select *
from Person,Car
group_by(person_name)
Get list of cars sorted by owner
car_list = Car.objects.all().order_by('car_owner__person_name')
4: select *
from Person,Car
where name like %x%
group_by(person_name)
having car_id >= 2
List of cars with search criteria
car_list = Car.objects.filter(id__gte = 2, car_name__contains = "<search>").order_by('car_owner__person_name',)
Cars and their Owners
car_list = Car.objects.all().values('car_name','car_owner__person_name')
Related
I have three models, Accrual and Member, and the common field of these two models is register_no, but this field is not a foreign key
class Accrual(models.Model):
register_no = models.PositiveIntegerField(verbose_name=_('Register No'))
amount=models.DecimalField(decimal_places=2, max_digits=17, verbose_name=_('Total Amount'))
class Member(models.Model):
register_no = models.PositiveIntegerField(unique=True, verbose_name=_('Register No'))
class Driver(models.Model):
register_no = models.PositiveIntegerField(unique=True, verbose_name=_('Register No'))
I want to list the debt each member/driver has. It can be done with #property;
class Member(models.Model):
register_no = models.PositiveIntegerField(unique=True, verbose_name=_('Register No'))
#property
def debt(self):
ret_val = Accrual.objects.filter(register_no=self.register_no).aggregate(
debt=Sum('amount'))
debt = ret_val.get('debt', 0)
return debt if debt else 0
but I can't use order_by this way. I want to sort each member by debt. How can I solve this problem?
You can use a subquery to add all the related accruals based on the register_no:
from django.db.models import OuterRef, Subquery, Sum
accruals = Accrual.objects.filter(
register_no=OuterRef('register_no')
).values('register_no').annotate(debt=Sum('amount'))
Member.objects.annotate(
debt=Subquery(accruals.values('debt'))
).order_by('debt')
which produces this sql:
SELECT "id", "register_no", (
SELECT SUM(U0."amount") AS "debt"
FROM "accrual" U0
WHERE U0."register_no" = ("register_no")
GROUP BY U0."register_no"
) AS "debt"
FROM "member"
ORDER BY "debt" ASC
I have a table TickerStatement, which contains financial statements about companies
class Statements(models.TextChoices):
"""
Supported statements
"""
capital_lease_obligations = 'capital_lease_obligations'
net_income = 'net_income'
price = 'price'
total_assets = 'total_assets'
short_term_debt = 'short_term_debt'
total_long_term_debt = 'total_long_term_debt'
total_revenue = 'total_revenue'
total_shareholder_equity = 'total_shareholder_equity'
class TickerStatement(TimeStampMixin):
"""
Model that represents ticker financial statements
"""
name = models.CharField(choices=Statements.choices, max_length=50)
fiscal_date_ending = models.DateField()
value = models.DecimalField(max_digits=MAX_DIGITS, decimal_places=DECIMAL_PLACES)
ticker = models.ForeignKey(Ticker, on_delete=models.CASCADE, null=False,
related_name='ticker_statements')
And now I'm trying to calculate a multiplier. The formula looks like:
(short_term_debt + total_long_term_debt) / total_shareholder_equity
I wrote a raw SQL query
SELECT "fin_tickerstatement"."fiscal_date_ending",
t2.equity AS "equity",
value AS "debt",
short_term_debt AS "short_term_debt",
(value + short_term_debt) / t2.equity AS "result"
FROM "fin_tickerstatement"
JOIN
(SELECT "fin_tickerstatement"."fiscal_date_ending",
fin_tickerstatement.value AS "equity"
FROM "fin_tickerstatement"
WHERE ("fin_tickerstatement"."ticker_id" = 12
AND "fin_tickerstatement"."fiscal_date_ending" >= date'2015-09-03'
AND "fin_tickerstatement"."name" = 'total_shareholder_equity')
GROUP BY "fin_tickerstatement"."fiscal_date_ending",
fin_tickerstatement.value
ORDER BY "fin_tickerstatement"."fiscal_date_ending" DESC) t2
ON fin_tickerstatement.fiscal_date_ending = t2.fiscal_date_ending
JOIN
(SELECT "fin_tickerstatement"."fiscal_date_ending",
fin_tickerstatement.value AS "short_term_debt"
FROM "fin_tickerstatement"
WHERE ("fin_tickerstatement"."ticker_id" = 12
AND "fin_tickerstatement"."fiscal_date_ending" >= date'2015-09-03'
AND "fin_tickerstatement"."name" = 'short_term_debt')
GROUP BY "fin_tickerstatement"."fiscal_date_ending",
fin_tickerstatement.value
ORDER BY "fin_tickerstatement"."fiscal_date_ending" DESC) t3
ON fin_tickerstatement.fiscal_date_ending = t3.fiscal_date_ending
WHERE ("fin_tickerstatement"."ticker_id" = 12
AND "fin_tickerstatement"."fiscal_date_ending" >= date'2015-09-03'
AND "fin_tickerstatement"."name" = 'total_long_term_debt')
GROUP BY "fin_tickerstatement"."fiscal_date_ending",
equity,
debt,
short_term_debt
ORDER BY "fin_tickerstatement"."fiscal_date_ending" DESC;
and have no idea how to translate it into Django ORM. Maybe you have some ideas or know some Django plugins that can help me.
The only way to solve this problem is to install django-query-builder.
I have three models:
class Vehicle(models.Model):
Vehicle_ID = models.AutoField('ID', primary_key= True)
Vehicle_VIN = models.CharField('FIN', max_length=30)
Vehicle_DELETED = models.BooleanField('Gelöscht',default=False)
class Recall(models.Model):
Recall_ID = models.AutoField('ID', primary_key= True)
Recall_CODE = models.CharField('Rückruf-Code',max_length=500, unique= True)
class Vehicle_Recall(models.Model):
Vehicle_Recall_ID = models.AutoField('ID', primary_key=True)
Vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE)
Recall = models.ForeignKey(Recall, on_delete=models.CASCADE)
I want to make a Select Statement like this:
SELECT * FROM Vehicle INNER JOIN(Recall INNER JOIN Vehicle_Recall ON Recall.ID = Vehicle_Recall.Recall) ON Vehicle.ID = Vehicle_Recall.Vehicle WHERE Recall.ID=1 AND Vehicle.DELETED)=FALSE;
Is there a way to make such query in django?
You canuse the Django's ORM as follows (it is an example):
vehicles = Vehicle.objects.filter(Vehicle_DELETED=False).filter(
Q(vehicle_recall__Recall__Recall_ID=1)
)
which generates the following SQL query:
SQL SELECT "vehicle"."Vehicle_ID", "vehicle"."Vehicle_VIN", "vehicle"."Vehicle_DELETED" FROM "vehicle" INNER JOIN "vehicle_recall" ON ("vehicle"."Vehicle_ID" = "vehicle_recall"."Vehicle_id") WHERE ("vehicle"."Vehicle_DELETED" = False AND "vehicle_recall"."Recall_id" = 1)
You can use the raw query as follows:
vehicles = Vehicle.objects.raw(f"""
SELECT * FROM Vehicle
INNER JOIN(Recall INNER JOIN Vehicle_Recall ON Recall.ID = Vehicle_Recall.Recall)
ON Vehicle.ID = Vehicle_Recall.Vehicle
WHERE Recall.ID=1 AND Vehicle.DELETED=FALSE;
""")
and remember to adjust name of tables.
I propose the first solution, but the appropriate code depends on needs. I prepared only some example to present its simplicity.
Here are my models:
class Zoo(TimeStampedModel):
id = models.AutoField(primary_key=True)
class Animal(models.Model):
id = models.AutoField(primary_key=True)
zoo = models.ForeignKey(Zoo, on_delete=models.PROTECT, related_name='diffbot_results')
I would like to run a query like this:
Zoo.objects.filter("WHERE zoo.id IN (select zoo_id from animal_table having count(*) > 10 group by zoo_id)")
One way is to use a raw queryset:
>>> from testapp.models import Zoo, Animal
>>> z1, z2 = Zoo(), Zoo()
>>> z1.save(), z2.save()
(None, None)
>>> z1_animals = [Animal(zoo=z1) for ii in range(5)]
>>> z2_animals = [Animal(zoo=z2) for ii in range(15)]
>>> x = [a.save() for a in z1_animals+z2_animals]
>>> qs = Zoo.objects.raw("select * from testapp_zoo zoo WHERE zoo.id IN (select zoo_id from testapp_animal group by zoo_id having count(1) > 10)")
>>> list(qs)
[<Zoo: Zoo object (2)>]
In theory, per these docs, it should be possible to pass in a queryset to a regular .filter(id__in=<queryset>), but the queryset must only select one column, and I can't find a way of adding the HAVING clause without also causing the queryset to select a num_animals column, preventing it from being used with an __in filter expression.
I have the following model structure below:
class Master(models.Model):
name = models.CharField(max_length=50)
mounting_height = models.DecimalField(max_digits=10,decimal_places=2)
class MLog(models.Model):
date = models.DateField(db_index=True)
time = models.TimeField(db_index=True)
sensor_reading = models.IntegerField()
m_master = models.ForeignKey(Master)
The goal is to produce a queryset that returns all the fields from MLog plus a calculated field (item_height) based on the related data in Master
using Django's raw sql:
querySet = MLog.objects.raw('''
SELECT a.id,
date,
time,
sensor_reading,
mounting_height,
(sensor_reading - mounting_height) as item_height
FROM db_mlog a JOIN db_master b
ON a.m_master_id = b.id
''')
How do I code this using Django's ORM?
I can think of two ways to go about this without relying on raw(). The first is pretty much the same as what #tylerl suggested. Something like this:
class Master(models.Model):
name = models.CharField(max_length=50)
mounting_height = models.DecimalField(max_digits=10,decimal_places=2)
class MLog(models.Model):
date = models.DateField(db_index=True)
time = models.TimeField(db_index=True)
sensor_reading = models.IntegerField()
m_master = models.ForeignKey(Master)
def _get_item_height(self):
return self.sensor_reading - self.m_master.mounting_height
item_height = property(_get_item_height)
In this case I am defining a custom (derived) property for MLog called item_height. This property is calculated as the difference of the sensor_reading of an instance and the mounting_height of its related master instance. More on property here.
You can then do something like this:
In [4]: q = MLog.objects.all()
In [5]: q[0]
Out[5]: <MLog: 2010-09-11 8>
In [6]: q[0].item_height
Out[6]: Decimal('-2.00')
The second way to do this is to use the extra() method and have the database do the calculation for you.
In [14]: q = MLog.objects.select_related().extra(select =
{'item_height': 'sensor_reading - mounting_height'})
In [16]: q[0]
Out[16]: <MLog: 2010-09-11 8>
In [17]: q[0].item_height
Out[17]: Decimal('-2.00')
You'll note the use of select_related(). Without this the Master table will not be joined with the query and you will get an error.
I always do the calculations in the app rather than in the DB.
class Thing(models.Model):
foo = models.IntegerField()
bar = models.IntegerField()
#Property
def diff():
def fget(self):
return self.foo - self.bar
def fset(self,value):
self.bar = self.foo - value
Then you can manipulate it just as you would any other field, and it does whatever you defined with the underlying data. For example:
obj = Thing.objects.all()[0]
print(obj.diff) # prints .foo - .bar
obj.diff = 4 # sets .bar to .foo - 4
Property, by the way, is just a standard property decorator, in this case coded as follows (I don't remember where it came from):
def Property(function):
keys = 'fget', 'fset', 'fdel'
func_locals = {'doc':function.__doc__}
def probeFunc(frame, event, arg):
if event == 'return':
locals = frame.f_locals
func_locals.update(dict((k,locals.get(k)) for k in keys))
sys.settrace(None)
return probeFunc
sys.settrace(probeFunc)
function()
return property(**func_locals)