Advanced ORM common query syntax

General Operation

The official website look professional documents, make professional programmers!

Must know will be 13

<1> all (): Search Results 
 
<2> filter (** kwargs) : it contains the object to match the filter of 
 
<3> get (** kwargs) : returns the given match the filter It objects, and only one result is returned, if the object matching the filter will throw more than one or no errors. 
 
<4> exclude (** kwargs) : it contains the given object does not match the filter criteria of 
 
<5> values (* field) : Returns a ValueQuerySet-- a special QuerySet, running is not obtained after a series of model examples of the object, but may be a dictionary iterative sequence 
 
<6> values_list (* field) : it values () are very similar, it returns a tuple sequence, values returns a dictionary sequence 
 
<7> order_by (* field): order query results 
 
<8> reverse (): reverse order query results, note reverse () only with defined generally on the order QuerySet that call (ordering specified in the Meta model class or call order_by () method). 
 
<9> distinct (): eliminate duplicate records (if you query across multiple tables, may be obtained from the returned results in the calculation of QuerySet reproducible results can now use distinct (), note that only supported by fields go in PostgreSQL. weight). 
 
<10> COUNT ():
 
<11> first (): returns the first record 
 
<12> last (): returns the last record 
 
<13> exists (): if QuerySet contains data, returns True, otherwise return False

Return QuerySet object methods

all()

filter()

exclude()

order_by()

reverse()

distinct()

Special QuerySet

values ​​() Returns an iterative sequence dictionaries

values_list () returns an ancestral sequence of iterations

Return specific object

get()

first()

last()

Returns a Boolean value methods are:

exists()

Returns the methods

count()

Single-table queries of magical double underline

(id__lt = 10, id__gt = 1 ) models.Tb1.objects.filter # acquires id value greater than 1 and less than 10 
 
models.Tb1.objects.filter (id__in = [11, 22 , 33]) # acquires id equal to 11, 22,33 data 
models.Tb1.objects.exclude (id__in = [. 11, 22 is, 33 is]) # Not in 
 
models.Tb1.objects.filter (name__contains = "ven") # Get name field contains "ven" of 
models .Tb1.objects.filter (name__icontains = "ven") # icontains case insensitive 
 
models.Tb1.objects.filter (id__range = [1, 3 ]) # id ranges from 1 to 3, equivalent to the SQL bettwen and 
 
there are similar: startsWith, istartswith, endsWith, iendswith 

DATE field also be: 
models.Class.objects.filter (first_day__year = 2017)

ForeignKey operation

Forward Lookup

Object lookup (cross table)

grammar:

Objects . Associated field . Field

 

Example:

book_obj = models.Book.objects.first () # the first book of the object 
print (book_obj.publisher) # get this book publishers association objects 
print (book_obj.publisher.name) # get the name of the object Press

Lookup field (cross table)

grammar:

Associated field __ field

 

Example:

print(models.Book.objects.values_list("publisher__name"))

Reverse operation

Find objects

grammar:

obj. _set table

Example:

publisher_obj = models.Publisher.objects.first () # object is to find the first publishing house 
books = publisher_obj.book_set.all () # find the first book published by all 
titles = books.values_list ( "title") # find all the books of the first title published by a publishing house

Fields Find

grammar:

Table Name field __

Example:

titles = models.Publisher.objects.values_list("book__title")

ManyToManyField

class RelatedManager

"Association Manager" is used in many or many-associated context's manager.

It exists in the following two cases:

  1. Reverse Lookup foreign key relationships
  2. To-many relationship

It is simply a later point when there may be multiple objects can use the following method.

method

create()

Create a new object, saving the object, and add it to the associated object set in, returns the newly created object.

>>> import datetime
>>> models.Author.objects.first().book_set.create(title="番茄物语", publish_date=datetime.date.today())

add()

Add the specified model object to the associated object set.

Add an object

>>> author_objs = models.Author.objects.filter(id__lt=3)
>>> models.Book.objects.first().authors.add(*author_objs)

Adding id

>>> models.Book.objects.first().authors.add(*[1, 2])

set()

Updates the associated object model objects.

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.set([2, 3])

remove()

Centralized model objects removed from the execution of the associated object

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.remove(3)

clear()

Removes all objects from the related object.

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.clear()

note:

For ForeignKey objects, clear () and remove () method is only present when the null = True.

for example:

ForeignKey field is not set to null = True,

class Book(models.Model):
    title = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Publisher)

No clear () and remove () method:

>>> models.Publisher.objects.first().book_set.clear()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'RelatedManager' object has no attribute 'clear'

When the field is set ForeignKey null = True,

class Book(models.Model):
    name = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Class, null=True)

At this point there are clear () and remove () method:

>>> models.Publisher.objects.first().book_set.clear()

 

note:

  1. For all types of related fields, add (), create (), remove () and clear (), set () will immediately update the database. In other words, at any end of the association, it does not need to call the save () method.

Aggregate query and query packet

polymerization

aggregate () is QuerySet  a termination clause, which means that it returns a dictionary that contains a number of key-value pairs.

The aggregate value is the name of the key identifier value is computed aggregate values. Name of the key is automatically generated out according to the name field and aggregate functions.

Used built-in functions:

from django.db.models import Avg, Sum, Max, Min, Count

Example:

>>> from django.db.models import Avg, Sum, Max, Min, Count
>>> models.Book.objects.all().aggregate(Avg("price")) {'price__avg': 13.233333}

If you want to specify a name for the aggregate values, it can provide to the aggregation clause.

>>> models.Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 13.233333}

If you want to generate more than one aggregate, you may provide Aggregate () clause add another parameter. So, if you want to know all the books of the maximum and minimum prices, it can be a query:

>>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
{'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}

Packet

We are here to brush up on grouping SQL statements.

Suppose now that there is a company employee table:

 

 We use native SQL statements, in accordance with the requirements of the packet average wage:

select dept,AVG(salary) from employee group by dept;

ORM query:

from django.db.models import Avg
Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg")

Even table query packet:

 

SQL query:

select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;

ORM query:

from django.db.models import Avg
models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")

More examples:

示例1:统计每一本书的作者个数

>>> book_list = models.Book.objects.all().annotate(author_num=Count("author"))
>>> for obj in book_list:
...     print(obj.author_num)
...
2
1
1

示例2:统计出每个出版社买的最便宜的书的价格

>>> publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price"))
>>> for obj in publisher_list:
...     print(obj.min_price)
...     
9.90
19.90

方法二:

>>> models.Book.objects.values("publisher__name").annotate(min_price=Min("price"))
<QuerySet [{'publisher__name': '沙河出版社', 'min_price': Decimal('9.90')}, {'publisher__name': '人民出版社', 'min_price': Decimal('19.90')}]>

示例3:统计不止一个作者的图书

>>> models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1)
<QuerySet [<Book: 番茄物语>]>

示例4:根据一本图书作者数量的多少对查询集 QuerySet进行排序

>>> models.Book.objects.annotate(author_num=Count("author")).order_by("author_num")
<QuerySet [<Book: 香蕉物语>, <Book: 橘子物语>, <Book: 番茄物语>]>

示例5:查询各个作者出的书的总价格

>>> models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")
<QuerySet [{'name': '小精灵', 'sum_price': Decimal('9.90')}, {'name': '小仙女', 'sum_price': Decimal('29.80')}, {'name': '小魔女', 'sum_price': Decimal('9.90')}]>

F查询和Q查询

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例1:

查询评论数大于收藏数的书籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

models.Book.objects.all().update(price=F("price")+30)

引申:

如果要修改char字段咋办?

如:把所有书名后面加上(第一版)

>>> from django.db.models.functions import Concat
>>> from django.db.models import Value
>>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

示例1:

查询作者名是小仙女或小魔女的

models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

示例:查询作者名字是小仙女并且不是2018年出版的书的书名。

>>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
<QuerySet [('番茄物语',)]>

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。

例如:查询出版年份是2017或2018,书名中带物语的所有书。

>>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")
<QuerySet [<Book: 番茄物语>, <Book: 香蕉物语>, <Book: 橘子物语>]>

锁和事务

select_for_update(nowait=False, skip_locked=False)

返回一个锁住行直到事务结束的查询集,如果数据库支持,它将生成一个 SELECT ... FOR UPDATE 语句。

举个例子:

entries = Entry.objects.select_for_update().filter(author=request.user)

所有匹配的行将被锁定,直到事务结束。这意味着可以通过锁防止数据被其它事务修改。

一般情况下如果其他事务锁定了相关行,那么本查询将被阻塞,直到锁被释放。 如果这不想要使查询阻塞的话,使用select_for_update(nowait=True)。 如果其它事务持有冲突的锁, 那么查询将引发 DatabaseError 异常。你也可以使用select_for_update(skip_locked=True)忽略锁定的行。 nowait和skip_locked是互斥的,同时设置会导致ValueError。

目前,postgresql,oracle和mysql数据库后端支持select_for_update()。 但是,MySQL不支持nowait和skip_locked参数。

使用不支持这些选项的数据库后端(如MySQL)将nowait=True或skip_locked=True转换为select_for_update()将导致抛出DatabaseError异常,这可以防止代码意外终止。

事务

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()

    import datetime
    from app01 import models

    try:
        from django.db import transaction
        with transaction.atomic():
            new_publisher = models.Publisher.objects.create(name="火星出版社")
            models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10)  # 指定一个不存在的出版社id
    except Exception as e:
        print(str(e))

 

Guess you like

Origin www.cnblogs.com/shangping/p/11479271.html