Django study notes: django orm extra

the use of complicated extra django orm sql statement in the
extra (select = None, where = None, params = None, tables = None, order_by = None, select_params = None)

In some cases, Django query syntax difficult to succinctly express complex WHERE clause. In this case, Django provides the extra () QuerySet modification mechanism, it can generate in the QuerySet SQL clause into the new clause.

Due to product differentiation, these custom queries difficult to protect compatible between different databases (SQL because of your handwritten code), and contrary to the DRY principle, so unless absolutely necessary, or try to avoid writing extra.

You may specify one or more parameters params extra, such as select, where or tables. All parameters are optional, but at least you want to use a.

   the SELECT
the SELECT parameter allows you to add additional information fields in the SELECT clause. It should be a dictionary, the storage of attribute names to SQL clauses of the map.

E.g:

Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})

 

The results for each Entry object has an additional is_recent property, which is a Boolean value that indicates whether pub_date later than January 1, 2006.

Django will directly join the corresponding fragment in the SELECT SQL, the SQL converted as follows:

SELECT blog_entry.*, (pub_date > '2006-01-01')
FROM blog_entry;

 

The following example is more complex; it will be added in each Blog object entry_count a property, it will run a sub-query to obtain the number of associated Entry objects:

Blog.objects.extra(
select={
'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'},
)

 

(Above this particular case, we have to understand the fact that blog_blog table already exists in the FROM clause.)

Translated to SQL as follows:

SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;

 

It should be noted that most of the database you need to add brackets at both ends clause in the select clause in Django so they do not need. Also to attract attention that in some databases, such as some MySQL versions, do not support sub-queries.

Sometimes, you might want to give extra (select = ...) in the SQL statement to pass parameters, then you can use select_params parameters. Because select_params is a queue and select attribute is a dictionary, so both should be matched correctly correspond. In this case, you should use the value django.utils.datastructures.SortedDict match select, rather than using a general Python queue.

E.g:

Blog.objects.extra(
select=SortedDict([('a', '%s'), ('b', '%s')]),
select_params=('one', 'two'))

 

When using extra () to avoid select string containing "%% s" substring, this is because in the% character Django, processing to find a string select% s and not escape. So if% had escaped, but can not get the correct result.

   where / tables
you can use the parameter display where the definition in SQL WHERE clause, sometimes run not explicitly linked. You can also use tables to the SQL FROM clause manually add other tables.

where and tables accept a list of strings as arguments. Are "AND" relationship between each other where all the parameters.

E.g:

Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])

 

Roughly translates into the following SQL:

SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);

 

When using the tables, if you specify table has appeared in the query, then be careful. When you add other data tables by table parameters, if the table has been included in the query, then Django will think you want to contain this table once. This leads to a question: repeated due to multiple tables will be given an alias, so in addition to the first, each table name will be repeated by the Django assign an alias respectively. So, if you use a parameter where, in which uses a repeating table, but do not know it's an alias, it will result in an error.

Under normal circumstances, you can only add a new table does not appear in the query. But if the special circumstances mentioned above occurs, you can use the following measures to solve. First, determine whether it is necessary to duplicate the table, you can remove duplicate table. If this does not work, they try extra () call in the beginning of the query structure, since the first appearance of the table name will not be renamed, it may solve the problem. If this does not work, then view the generated SQL statements to find out the alias of each database, and then rewrite where parameters so as long as you always use the same way to call query (queryset), alias table is not It will change. So you can directly use the alias table constructed where.

   order_by
If you have passed the extra () to add a new field or database, a new field at this time if you want to sort, can order_by parameter to extra () is passed a string sorting sequence. Field name string may be a native model (as with the method using conventional ORDER_BY ()), may also be table_name.column_name this form, or in the field you define extra () in the select.

E.g:

q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
q = q.extra(order_by = ['-is_recent'])

 

This code sort the records according is_recent, the field value is True top surface, False the row behind. (True when descending order is ahead of the False).

By the way, the above code also demonstrated, according to you can call as many times wish the extra () operation (every time you add a new sentence structure can).

Guess you like

Origin www.cnblogs.com/john-xiong/p/12099977.html