django PostgreSQL Partitioning reference error - django

We have two models. I'm implementing partitioning on the PaymentModel. It gives an error when I want to add to the BuyerModel table linked to this table;
insert or update on table "betik_app_payment_buyermodel" violates
foreign key constraint
"betik_app_payment_bu_payment_id_d7022880_fk_betik_app" DETAIL: Key
(payment_id)=(2) is not present in table
"betik_app_payment_paymentmodel".
models.py
#architect.install('partition', type='range', subtype='date', constraint='month', column='dt')
class PaymentModel(models.Model):
class Meta:
app_label = 'betik_app_payment'
indexes = [
models.Index(fields=['user_email'])
]
payment_status = models.PositiveIntegerField(default=1)
price = MoneyField(max_digits=20, decimal_places=2)
dt = models.DateTimeField()
user_email = models.EmailField(null=True, blank=True)
token = models.CharField(max_length=255, null=True, blank=True)
class BuyerModel(models.Model):
class Meta:
app_label = 'betik_app_payment'
indexes = [
models.Index(fields=['name', 'surname'])
]
payment = models.OneToOneField(to='betik_app_payment.PaymentModel', on_delete=models.CASCADE,related_name='buyer')
name = models.CharField(max_length=100)
surname = models.CharField(max_length=100)
email = models.EmailField(null=True, blank=True)
ip = models.GenericIPAddressField(null=True, blank=True)
main.py
from datetime import datetime
from djmoney.money import Money
buyer_name="Name"
buyer_surname="Surname"
buyer_email="developer#betik.com.tr"
buyer_ip="10.0.0.1"
price= Money("100.00","TRY")
payment_instance = PaymentModel.objects.create(
price=price,
dt=datetime.now(),
user_email=buyer_email
)
# raise error at here
buyer_instance = BuyerModel.objects.create(
payment=payment_instance,
name=buyer_name,
surname=buyer_surname,
email=buyer_email,
ip=buyer_ip
)
using library:
money
partition
I'm looking at the tables in the database with the pgadmin tool and the partition has been applied successfully.
data added in both tables. But BuyerModel table is empty
PaymentModel table has two triggers. These triggers are created automatically by the architect library. Maybe there is an error here?;
after_insert_betik_app_payment_paymentmodel_trigger.
-- FUNCTION: public.betik_app_payment_paymentmodel_delete_master()
-- DROP FUNCTION IF EXISTS public.betik_app_payment_paymentmodel_delete_master();
CREATE OR REPLACE FUNCTION public.betik_app_payment_paymentmodel_delete_master()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
DELETE FROM ONLY "betik_app_payment_paymentmodel" WHERE id = NEW.id;
RETURN NEW;
END;
$BODY$;
ALTER FUNCTION public.betik_app_payment_paymentmodel_delete_master()
OWNER TO postgres_user;
before_insert_betik_app_payment_paymentmodel_trigger.
-- FUNCTION: public.betik_app_payment_paymentmodel_insert_child()
-- DROP FUNCTION IF EXISTS public.betik_app_payment_paymentmodel_insert_child();
CREATE OR REPLACE FUNCTION public.betik_app_payment_paymentmodel_insert_child()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF SECURITY DEFINER
AS $BODY$
DECLARE
match "betik_app_payment_paymentmodel"."dt"%TYPE;
tablename VARCHAR;
checks TEXT;
BEGIN
IF NEW."dt" IS NULL THEN
tablename := 'betik_app_payment_paymentmodel_null';
checks := '"dt" IS NULL';
ELSE
match := DATE_TRUNC('month', NEW."dt");
tablename := 'betik_app_payment_paymentmodel_' || TO_CHAR(NEW."dt", '"y"YYYY"m"MM');
checks := '"dt" >= ''' || match || ''' AND "dt" < ''' || (match + INTERVAL '1 month') || '''';
END IF;
BEGIN
EXECUTE 'CREATE TABLE IF NOT EXISTS ' || tablename || ' (
CHECK (' || checks || '),
LIKE "betik_app_payment_paymentmodel" INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES
) INHERITS ("betik_app_payment_paymentmodel");';
EXCEPTION WHEN duplicate_table THEN
-- pass
END;
EXECUTE 'INSERT INTO ' || tablename || ' VALUES (($1).*);' USING NEW;
RETURN NEW;
END;
$BODY$;
ALTER FUNCTION public.betik_app_payment_paymentmodel_insert_child()
OWNER TO postgres_user;

Related

Django queryset from raw SQL

I want an equivalent of this sql query in Django
SELECT Gender, ServCode
FROM [openimisproductTestDb_16_08_22].[dbo].[tblInsuree]
JOIN [openimisproductTestDb_16_08_22].[dbo].[tblServices] ON [openimisproductTestDb_16_08_22].[dbo].[tblInsuree].AuditUserID = [openimisproductTestDb_16_08_22].[dbo].[tblServices].AuditUserID
WHERE Gender = 'F'
AND ServCode = 'F4'
What I have tried:
def assisted_birth_with_cs_query(user, **kwargs):
date_from = kwargs.get("date_from")
date_to = kwargs.get("date_to")
hflocation = kwargs.get("hflocation")
format = "%Y-%m-%d"
date_from_object = datetime.datetime.strptime(date_from, format)
date_from_str = date_from_object.strftime("%d/%m/%Y")
date_to_object = datetime.datetime.strptime(date_to, format)
date_to_str = date_to_object.strftime("%d/%m/%Y")
dictBase = {
"dateFrom": date_from_str,
"dateTo": date_to_str,
}
dictGeo = {}
if hflocation and hflocation!="0" :
hflocationObj = HealthFacility.objects.filter(
code=hflocation,
validity_to__isnull=True
).first()
dictBase["fosa"] = hflocationObj.name
claimItem = Insuree.objects.filter(
validity_from__gte = date_from,
validity_to__lte = date_to,
**dictGeo,
gender = 'F'
).count()
data = Service.objects.filter(code = 'F4').count() | Insuree.objects.filter(gender = 'F').count()
dictGeo['health_facility'] = hflocationObj.id
dictBase["post"]= str(data)
return dictBase
I tried like that but the one just adds when I want the women included in the insured table and the F4 code contained in the service table. both tables have the auditUserID column in common
It would be great if you could add the models to better see the relations between Insuree and Service. Assuming it's a 1-M, I'd go with this query:
Service.objects.filter(code='F4', insuree__gender='F').count()

Django filter ManyToMany with Q and Or

class State(models.Model):
name = models.CharField(max_length=55, unique=True)
class City(models.Model):
name = models.CharField(max_length=255)
states = models.ManyToManyField(State, related_name='cities')
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, related_name='children', blank=True)
I have a state and I want to find cities that either have null parent or whose parent states doesn't contain a state.
I tried state.cities.filter(Q(parent=None) | ~Q(parent__states=state)) but it doesn't work and I query is strange:
`SELECT "city"."id", "city"."name", "city"."parent_id", FROM "city" INNER JOIN "city_states" ON ("city"."id" = "city_states"."city_id") WHERE ("city_states"."state_id" = 7 AND ("city"."parent_id" IS NULL OR NOT ("city"."parent_id" IN (SELECT U2."city_id" FROM "city_states" U2 WHERE (U2."state_id" = 7 AND U2."id" = "city_states"."id")) AND "city"."parent_id" IS NOT NULL))) ORDER BY "city"."name" ASC`
In particular what does the code AND U2."id" = "city_states"."id" perform?
You can simply work with the .exclude(…) [Django-doc] here:
state.cities.exclude(
parent__states=state
)
This will still work if parent is None/NULL, since then the parent__states=state does not hold.
This will construct a query that looks like:
SELECT app_name_city.*
FROM app_name_city
WHERE NOT (
app_name_city.parent_id IN (
SELECT U2.city_id
FROM `app_name_city_states U2
WHERE U2.state_id = id_of_state
)
AND app_name_city.parent_id IS NOT NULL
)
The subquery thus makes a list of cities for the given state, and we thus require the city to have a parent that is not in any of these states.

Django ORM. Joining subquery on condition

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.

Django Select across three models with filter criteria

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.

relation "" does not exist in django for app name with mixed-case

I have faced a problem while working with django models. lets say my apps name is GasNet and my models name is Riser well the generated table name is GasNet.riser, I can successfully generate table and add objects to table and even delete all of the objects of a table. But when I try to delete an object I face this error
The above exception (relation "GasNet_riser" does not exist LINE 1: ..."."createDateTime", "GasNet_riser"."deleted" FROM "GasNet_ri... ^ ) was the direct cause of the following exception:
in debug window the sql query is as
sql
('SELECT "GasNet_riser"."id", "GasNet_riser"."city_code", '
'"GasNet_riser"."geom"::bytea, "GasNet_riser"."node_code", '
'"GasNet_riser"."pipe", "GasNet_riser"."parcel_code", '
'"GasNet_riser"."Number", "GasNet_riser"."hack", "GasNet_riser"."multi_code", '
'"GasNet_riser"."gis_code", "GasNet_riser"."angle", "GasNet_riser"."size", '
'"GasNet_riser"."direction", "GasNet_riser"."instalation_date", '
'"GasNet_riser"."description", "GasNet_riser"."type", '
'"GasNet_riser"."status", "GasNet_riser"."instalation_type", '
'"GasNet_riser"."material", "GasNet_riser"."zone_id", '
'"GasNet_riser"."prejenti_id", "GasNet_riser"."emergency_sub_zone_id", '
'"GasNet_riser"."updateDateTime", "GasNet_riser"."createDateTime", '
'"GasNet_riser"."deleted" FROM "GasNet_riser" WHERE "GasNet_riser"."id" = %s')
this is my model
class Riser(models.Model):
id=models.AutoField(primary_key=True)
city_code = models.CharField(max_length=10)
geom = models.PointField(srid=4326)
node_code = models.IntegerField(default=-1,blank=True) # شماره گره جهت اعمال مصرف آن برروی گره در طراحی
pipe = models.IntegerField(default=-1,blank=True)
parcel_code = models.IntegerField(default=-1,blank=True)
Number = models.CharField(max_length=20) #کد علمک
hack = models.IntegerField(default=-1,blank=True)
multi_code = models.CharField(max_length=10,blank=True)
gis_code = models.CharField(max_length=20,blank=True)
angle = models.FloatField(default=-1,blank=True)
size = models.IntegerField(default=-1,blank=True)
direction = models.TextField(max_length=500,blank=True)
instalation_date = models.DateField(null=True,blank=True) # تاریخ نصب
description = models.TextField(blank=True)
type = models.CharField(max_length=20,blank=True) # همان فیلد kind هست
# choises
status = models.CharField(max_length=5,default=ModelChoiseFields.NAN, choices=ModelChoiseFields.RISER_STATUS,blank=True)
instalation_type = models.CharField(max_length=5,default=ModelChoiseFields.NAN, choices=ModelChoiseFields.RISER_INSTALATION_TYPE,blank=True)
material = models.CharField(max_length=5,default=ModelChoiseFields.NAN, choices=ModelChoiseFields.RISER_MATERIAL,blank=True)
# relations
zone = models.ForeignKey(Zone,on_delete=models.CASCADE,null=True)
prejenti = models.ForeignKey(pt,models.CASCADE,null=True,blank=True)
emergency_sub_zone = models.ForeignKey(EmergencySubZone,models.CASCADE,null=True) # زیرناحیه امداد
# Auto fields
updateDateTime = models.DateTimeField('update date', auto_now_add=True, auto_now=False)
createDateTime = models.DateTimeField('create date',auto_now_add=False, auto_now=True)
deleted = models.BooleanField(default=False)
I tried makemigrations and migrate and I know that table is fine but I have no idea why this happens.
I try to delete object using this method.
selected=Riser.objects.get(id=id)
selected.delete()
I think the problem is with app name and upper case G and N but I do not know how to fix this problem.
I also tried to delete using filter and the same error happens. it says
relation "GasNet_riser" does not exist LINE 1: DELETE FROM "GasNet_riser" WHERE "GasNet_riser"."id" = 1115 ^
when I run the above query manually in my database it runse with no problem DELETE FROM "GasNet_riser" WHERE "GasNet_riser"."id" = 1115 returns Query returned successfully: one row affected, 62 msec execution time.