Django, relational querysets - django

How do I express this SQL query in a Django Queryset?
SELECT * FROM Table1, Table2 WHERE Table1.id_table2 = Table2.id_table2;
Be aware that the structure of table1 implyes a id_table2 foreign key...
Why? Because I want to replace the id_table2 in the Table1 table1.object.all() listing with values asociated to the register involved in the relation. Like this
Whithout relationship
| id_table1 | id_table2 | foo_field1 | bar_field1 |
---------------------------------------------------
| 1 | 1 | foo1 | foo2 |
---------------------------------------------------
With Relationship
| id_table1 | foo_field2*| foo_field1 | bar_field1 |
----------------------------------------------------
| 1 | foo2 | foo1 | foo2 |
----------------------------------------------------
Keep in mind that foo_field2 means not only this related field, but all related fields of that register.

You cannot perform that query with the Django ORM. The best you can do is use select_related() to also pull the fields for the other table at the same time:
Table1.objects.select_related('table2')

Related

How to use prefetch_related to retrieve multiple rows similar to SQL result

I’ve a question about the usage of prefetch_related. Based on my understanding I need to use prefetch_related for reverse foreign key relationships
As an example I have a User(id, name) model and SchoolHistory(id, start_date, school_name, user_id[FK user.id]) model. A user can have multiple school history records.
If I’m querying the database using the following SQL query:
SELECT
user.id,
name,
start_date,
school_name
FROM user
INNER JOIN school_history ON school_history.user_id = user.id
the expected result would be:
| User ID | Name | Start Date | School |
| 1 | Human | 1/1/2022 | Michigan |
| 1 | Human | 1/1/2021 | Wisconsin |
| 2 | Alien | | |
This is the current result that I’m getting instead with ORM and a serializer:
| User ID | Name | school_history
| 1 | Human | [{start_date:1/1/2022 , school:Michigan}, {start_date:1/1/2021 , school:Wisconsin}] |
| 2 | Alien | [] |
This is the ORM query that I’m using:
User.objects.prefetch_related(
Prefetch(
‘school_history’
query_set=SchoolHistory.objects.order_by(‘start_date’)
)
)
Is there a way for the ORM query to have a similar result as SQL? I want multiple rows if there are multiple schools associated with that user

query to give workflow statistics like source count,target count,start time and end time of each sessions

I have one workflow which contain five sessions. I am looking for a query by using informatica repository tables/views which give me output like below. I am not able to get a query which give me desired result.
workflow-names session-names source-count target-count session-start time session-end time.
If you have access to Repository metadata tables, then you can use below query
Metadata Tables used in query:
OPB_SESS_TASK_LOG
OPB_TASK_INST_RUN
OPB_WFLOW_RUN
Here the Repository user is INFA_REP, and workflow name is wf_emp_load.
SELECT w.WORKFLOW_NAME,
t.INSTANCE_NAME,
s.SRC_SUCCESS_ROWS,
s.TARG_SUCCESS_ROWS,
t.START_TIME,
t.END_TIME
FROM INFA_REP.OPB_SESS_TASK_LOG s
INNER JOIN INFA_REP.OPB_TASK_INST_RUN t
ON s.INSTANCE_ID=t.INSTANCE_ID
AND s.WORKFLOW_RUN_ID=t.WORKFLOW_RUN_ID
INNER JOIN INFA_REP.OPB_WFLOW_RUN w
ON w.WORKFLOW_RUN_ID=t.WORKFLOW_RUN_ID
WHERE w.WORKFLOW_RUN_ID =
(SELECT MAX(WORKFLOW_RUN_ID)
FROM INFA_REP.OPB_WFLOW_RUN
WHERE WORKFLOW_NAME='wf_emp_load')
ORDER BY t.START_TIME
Output
+---------------+---------------+------------------+-------------------+--------------------+--------------------+
| WORKFLOW_NAME | INSTANCE_NAME | SRC_SUCCESS_ROWS | TARG_SUCCESS_ROWS | START_TIME | END_TIME |
+---------------+---------------+------------------+-------------------+--------------------+--------------------+
| wf_emp_load | s_emp_load | 14 | 14 | 10-JUN-18 18:31:24 | 10-JUN-18 18:31:26 |
| wf_emp_load | s_emp_revert | 14 | 14 | 10-JUN-18 18:31:27 | 10-JUN-18 18:31:28 |
+---------------+---------------+------------------+-------------------+--------------------+--------------------+

How to add "description" for a column in Postgres DB using the corresponding Django model?

For e.g., in this table, I'd like to be able add the "description" text at the Django ORM layer and have it reflected at the database level.
test=# \d+ django_model
Table "public.django_model"
Column | Type | Modifiers | Description
--------+---------+-----------+-------------
i | integer | |
j | integer | |
Indexes:
"mi" btree (i) - Tablespace: "testspace"
"mj" btree (j)
Has OIDs: no
I suppose you can't do it. Here's the https://code.djangoproject.com/ticket/13867 request. Closed 6 ya as "Won't do".
You still can use postgres COMMENT extension, eg:
t=# create table t (i int, t text);
CREATE TABLE
Time: 12.068 ms
t=# comment on column t.i is 'some description';
COMMENT
Time: 2.994 ms
t=# \d+ t
Table "postgres.t"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+----------+--------------+------------------
i | integer | | | | plain | | some description
t | text | | | | extended | |

Django: Limit QuerySet to user input (checkboxes)

My question is similar to Django Advanced Filtering but I need another approach:
Abstract:
Tables: manufacturer, supplies
Manufacturers have multiple supplies (1 or 0 in "supply" table)
I have a HTML form with multiple (20+ checkboxes) which should limit the queryset with AND queries (so standard). The HTML checkbox names equal MySQL field names. My table looks like this:
mysql> explain supply;
+----------------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| manufacturer_id | int(11) | NO | MUL | NULL | |
| supply1 | tinyint(1) | NO | | NULL | |
| supply2 | tinyint(1) | NO | | NULL | |
| supply3 | tinyint(1) | NO | | NULL | |
| [...] | tinyint(1) | NO | | NULL | |
| supply20 | tinyint(1) | NO | | NULL | |
Now in pseudo SQL, I'd like to:
User selected checkboxes supply2 and supply14: SELECT * FROM supply WHERE supply2 = 1 AND supply14 = 1;
User selected checkboxes supply1, supply9 and supply18: SELECT * FROM supply WHERE supply1 = 1 AND supply9 = 1 AND supply18 = 1;
I'm pretty sure I need some QuerySet with kwargs, but I'm unable to construct the view for my needs (still learning Django).
I wonder if the data model here couldn't use some tweaking? You might want to have a supply table with twenty rows and an intermediate table connecting them (that is a ManytoMany(Supply) or something like that). Then you could just have a multi select field, rather than 20 check boxes (unless you really need them for some other reason).
If you need to add another supply, it's simply adding another row, rather than a schema migration.
supplies = Supply.objects.filter( supply1 = 1 )
And if you want to filter again:
supplies = supplies.filter(supply2 = 1)
The filter() method returns a QuerySet, so you can chain as many filter() calls as you like.

Django 1.4/1.5 control GROUP BY combined with HAVING

Say I have the following data:
| id | user_id | time |
| 1 | 1 | 10.0 |
| 2 | 1 | 12.0 |
| 3 | 2 | 11.0 |
| 4 | 2 | 13.0 |
What I want is to query this table such that I get the MIN(time) per user_id:
| id | user_id | time |
| 1 | 1 | 10.0 |
| 3 | 2 | 11.0 |
So my SQL would like this:
SELECT id, user_id, time FROM table GROUP BY user_id HAVING MIN(time)
However, when trying to use .annotate(Min('time')), Django will GROUP BY on arbitrary (wrong) fields. For example see the following code and the resulting (simplified) SQL:
>>> Table.objects.annotate(Min('time')).query
SELECT id, user_id, time, MIN(time) FROM table GROUP BY id, user_id, time
>>> Table.objects.values('id', 'time').annotate(Min('time')).query
SELECT id, time, MIN(time) FROM table GROUP BY id, time
The resulting SQL is far from my desired output. I'm currently working around this by using raw SQL, however this defeats the purpose of using an ORM in the first place. Also, the resulting code is difficult to reuse as normal .filter() cannot be applied.
There are similar questions about this type of querying, however they are rather old and do not incorporate changes to Django since 1.3.
It's not pretty code but. Using django's 'extra' queryset method and where as an argument you can achieve getting back the desired result set. i.e.
Table.objects.extra(where=['id IN (SELECT id FROM table_name'
' GROUP BY user_id HAVING MIN(time))'])