Creating a Django object with field values from a SELECT equivalent - django

I am trying to figure out how to reproduce the following using Django - anyone help?
INSERT INTO table1 (table2_id, a_field)
SELECT table2.id as table2_id, table3.a_field
FROM table2
INNER JOIN table3 ON
table3.table2_id == table2.id
WHERE table2.id = 123
If I've got this correct (not my original query ;-) ), this is doing the following:
Creating an entry in table1 where...
a field named table2_id will match the id of a row in table2 and
a field named a_field will match the same named field in a_field in a row of table3 and
the table2/table3 objects from which these values are read are identified by a shared table2.id/table3.table_id2 relationship and also the table2 id being 123.
I don't see how such "calculated" field values can be passed to a create() or get_or_create() style command. It this perhaps possible using Q() objects?

Django model is an ORM framework.
In ORM way, you need
get table2Entity
construct a new table1Entity with table2Entity and related table3Entity values
save the table1Entity
def batch_save_entity2():
entity2 = Table2Entity.objects.get('123')
entity1 = Table1Entity()
entity1.table2_id = entity2.id
entity1.a_field = entity2.entity3.a_field
entity1.save()
or just execute sql directly without ORM
from django.db import connection
def my_custom_sql(self):
with connection.cursor() as cursor:
cursor.execute('''
INSERT INTO table1 (table2_id, a_field)
SELECT table2.id as table2_id, table3.a_field
FROM table2
INNER JOIN table3 ON
table3.table2_id == table2.id
WHERE table2.id = 123''')

Related

Is there any way to convert this into django orm?

I needed to get all the rows in the table1 even if it is not existing in table2 and display it as zero. I got it using raw sql query but in django ORM i am getting the values existing only in table2. The only difference on my django orm is that iI am using inner join while in the raw sql query I am using left join. Is there any way to achieve this or should I use raw sql query? Thanks.
Django ORM:
total=ApplicantInfo.objects.select_related('source_type').values('source_type__source_type').annotate(total_count=Count('source_type'))
OUTPUT OF DJANGO ORM IN RAW SQL:
SELECT "applicant_sourcetype"."source_type", COUNT("applicant_applicantinfo"."source_type_id") AS "total_count" FROM "applicant_applicantinfo" INNER JOIN "applicant_sourcetype" ON ("applicant_applicantinfo"."source_type_id" = "applicant_sourcetype"."id") GROUP BY "applicant_sourcetype"."source_type"
RAW SQL:
SELECT source.source_type, count(info.source_type_id) as total_counts from applicant_sourcetype as source LEFT JOIN applicant_applicantinfo as info ON source.id = info.source_type_id GROUP BY source.id
You cannot query on ApplicantInfo if you want a left join with it. Query on SourceType instead:
qs = (SourceType.objects
.values('source_type')
.annotate(cnt=Count('applicantinfo'))
.values('source_type', 'cnt')
)
Since you haven't posted the models, you may need to adapt the field names to make it work.

How to create a table in sqlite3 with column names taken from a list?

I intend to create a table in sqlite3 with the column names in a list [item1,...]. I don't want to hard code the column names while creating the table because the number of columns and even names are dynamic. I want the correct syntax to get the column names directly from this list. Thank you. I'm using python.
You can do something like this:
import contextlib
import sqlite3
fields = ["field1", "field2", "field3"]
with contextlib.closing(sqlite3.connect(':memory:')) as conn:
cursor = conn.cursor()
columns = ", ".join("{field} TEXT".format(field=field) for field in fields)
cursor.execute("""
CREATE TABLE IF NOT EXISTS your_table(
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
{columns}
)
""".format(columns=columns))
conn.commit()
But, you should consider using an ORM, like SqlAlchemy. Here is a tutorial for that: https://www.pythoncentral.io/introductory-tutorial-python-sqlalchemy/
Edit
To go further, your insert statement could be built like this:
stmt = ("INSERT INTO mytable ({fields}) VALUES ({marks})"
.format(fields=", ".join(fields), marks=", ".join("?" * len(fields))))
For instance:
INSERT INTO mytable (field1, field2, field3) VALUES (?, ?, ?)

sqlite3 & python: get list of primary and foreign keys

I am very new to sql and intermediate at python. Using sqlite3, how can I get a print() list of of primary and foreign keys (per table) in my database?
Using Python2.7, SQLite3, PyCharm.
sqlite3.version = 2.6.0
sqlite3.sqlite_version = 3.8.11
Also note: when I set up the database, I enabled FKs as such:
conn = sqlite3.connect(db_file)
conn.execute('pragma foreign_keys=ON')
I tried the following:
conn=sqlite3.connect(db_path)
print(conn.execute("PRAGMA table_info"))
print(conn.execute("PRAGMA foreign_key_list"))
Which returned:
<sqlite3.Cursor object at 0x0000000002FCBDC0>
<sqlite3.Cursor object at 0x0000000002FCBDC0>
I also tried the following, which prints nothing (but I think this may be because it's a dummy database with tables and fields but no records):
conn=sqlite3.connect(db_path)
rows = conn.execute('PRAGMA table_info')
for r in rows:
print r
rows2 = conn.execute('PRAGMA foreign_key_list')
for r2 in rows2:
print r2
Unknown or malformed PRAGMA statements are ignored.
The problem with your PRAGMAs is that the table name is missing. You have to get a list of all tables, and then execute those PRAGMAs for each one:
rows = db.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
tables = [row[0] for row in rows]
def sql_identifier(s):
return '"' + s.replace('"', '""') + '"'
for table in tables:
print("table: " + table)
rows = db.execute("PRAGMA table_info({})".format(sql_identifier(table)))
print(rows.fetchall())
rows = db.execute("PRAGMA foreign_key_list({})".format(sql_identifier(table)))
print(rows.fetchall())
SELECT
name
FROM
sqlite_master
WHERE
type ='table' AND
name NOT LIKE 'sqlite_%';
this sql will show all table in database, for eache table run sql PRAGMA table_info(your_table_name);, you can get the primary key of the table.
Those pictures show what sql result like in my database:
first sql result
second sql result

Django 1.11 OuterRef generating invalid Postgres

I have a model named Brand with a field named "name", so this works fine:
brands = (Brand
.objects
.annotate(as_string=models.functions.Concat('name',models.Value("''"))))
I have a model named Item with a foreign key to Brand. The following does NOT work:
annotated_brands = brands.filter(pk=models.OuterRef('brand'))
(Item
.objects
.annotate(brand_string=models.Subquery(annotated_brands.values('as_string'))))
Specifically, I get a ProgrammingError:
missing FROM-clause entry for table "policeinventory_item"
LINE 1: ... FROM "PoliceInventory_brand" U0 WHERE U0."id" = (PoliceInve...
This is born out when I inspect the SQL query. Here is the broken query:
'SELECT "PoliceInventory_item"."id", "PoliceInventory_item"."_created", "PoliceInventory_item"."_created_by_id", "PoliceInventory_item"."_last_updated", "PoliceInventory_item"."_last_updated_by_id", "PoliceInventory_item"."brand_id", "PoliceInventory_item"."type", (SELECT CONCAT(U0."name", \'\') AS "as_string" FROM "PoliceInventory_brand" U0 WHERE U0."id" = (PoliceInventory_item."brand_id") ORDER BY U0."_created" DESC) AS "brand_string" FROM "PoliceInventory_item" ORDER BY "PoliceInventory_item"."_created" DESC'
Note how the nested id comparison is performed with PoliceInventory, NOT "PoliceInventory" as it is referred to everywhere else. The following query works as expected:
'SELECT "PoliceInventory_item"."id", "PoliceInventory_item"."_created", "PoliceInventory_item"."_created_by_id", "PoliceInventory_item"."_last_updated", "PoliceInventory_item"."_last_updated_by_id", "PoliceInventory_item"."brand_id", "PoliceInventory_item"."type", (SELECT CONCAT(U0."name", \'\') AS "as_string" FROM "PoliceInventory_brand" U0 WHERE U0."id" = ("PoliceInventory_item"."brand_id") ORDER BY U0."_created" DESC) AS "brand_string" FROM "PoliceInventory_item" ORDER BY "PoliceInventory_item"."_created" DESC'
The problem seems pretty clearly to be OuterRef incorrectly failing to use the same table reference as the outer query, resulting in a mismatch. Does anyone know how I can persuade OuterRef to behave correctly?

Can JPA join to a codes table when part of join clause requires a hard coded value?

I would like the resulting entity to contain all the columns from table1, plus the description from codes1.
If I were to do this in SQL I would write it as follows:
select table1.*, codes1.description
from table1
inner joing codes1 where codes1.code = table1.status_code
and codes1.group = 'status'
I have done this with a native query, but would like to do this using straight JPA if possible.
Codes Table:
Group Code Description
status a status code a
status b status code b
other a other code a
If we imagine 2 objects: Table1 and Code1.
Your class Table1 contains of course Code1.
In "straight JPA" or jpql you select an object so the query will be:
select t from Table1 t where t.code1.group = 'status'
The join is automaticaly done by the mapping (#OneToOne, #ManyToOne...).