Django ORM multi-table CRUD

Django ORM multi-table CRUD

Create a relationship field

ORM create multi-table relationships through the use of field. Commonly used multi-table relationships are:

  • ForeignKey foreign key, field-many relationship
  • OneToOneField one relationship field
  • ManyToManyField-many relationship field

Direct look at models.pythe code:

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    # 一对一
    ad=models.OneToOneField(to="AuthorDetail", to_field="id", on_delete=models.CASCADE)
    
    # to_field="id"  可以不写,默认找主键
    # to="AuthorDetail",  to=可以不用写
    # on_delete=models.CASCADE  默认是级联删除,想做级联更新,直接去数据库修改表结构
    # on_delete=models.SET_NULL  也可以设置成删除置空

class AuthorDetail(models.Model):
    birthday=models.DateField()
    telephone=models.CharField(max_length=16)
    addr=models.CharField(max_length=64)


class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)

class Book(models.Model):
    title = models.CharField(max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5, decimal_places=2)
    # 外键和多对多
    publishs=models.ForeignKey(to="Publish", to_field="id", on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author')

The basic construction of the table statement is consistent with the single-table operation. There are many tables relationship one to one, one to many and many to many, respectively, can be created in the following three ways:

# 一对一,外键 + 唯一
ad=models.OneToOneField(to="AuthorDetail", to_field="id", on_delete=models.CASCADE)

# 一对多,外键
publishs=models.ForeignKey(to="Publish", to_field="id", on_delete=models.CASCADE)

# 多对多,创建第三张表
authors=models.ManyToManyField(to='Author')

When operating one or one to many association table, we can operate through the class attribute table or form fields, field name is usually 类属性名 + 下划线 + 外键名:

  • Class adproperties: ,publishs
  • Field:ad_id ,publishs_id

For many-direct operation of the third generation new tables, table name 应用名 + 下划线 + 当前表名 + 下划线 + 属性名, may be operated by a third class attribute table fields and tables:

  • Class properties:authors
  • Table Name:app01_book_authors
  • idField: author_id, ,book_id

It will be discussed in detail below their specific usage.

Multi-table CRUD

increase

One to One

As described above, one field may be added to increase the data associated with another table or through the use of the class attribute table fields:

models.AuthorDetail.objects.create(
    birthday='2018-11-11',
    telephone='15122220000',
    addr='北京',
)

models.Author.objects.create(
    name='金龙',
    age=2,
    ad=models.AuthorDetail.objects.get(id=1),    # 类属性
)

models.Author.objects.create(
    name='金龙2',
    age=2,
    ad_id=2,    # 表字段
)

Many

Increase, with one-to-many is the same reason, you can add or through the class attribute table field:

models.Book.objects.create(
    title='白洁',
    publishDate='2011-01-01',
    price=200,
    publishs=models.Publish.objects.get(id=1)    # 类属性
)

models.Book.objects.create(
    title='白洁第二部',
    publishDate='2011-01-01',
    price=300,
    publishs_id=1    # 表字段
)

Many to many

A book can have multiple authors, an author may write many books. For example, No. 1 of the book is written by two authors numbered 1 and 2, then the relationship between the author and the book's table, we should create a relationship between the two books 1 2 1 author and book author 1, it like this:

+----+---------+-----------+
| id | book_id | author_id |
+----+---------+-----------+
|  1 |       1 |         1 |
|  2 |       1 |         2 |
+----+---------+-----------+

The specific operation in two ways, one is added through the object, and the other is a value added directly

Add an object by object

By finding the object of an object, use the Add method to add:

book_obj = models.Book.objects.get(id=1)
author1 = models.Author.objects.get(id=1)
author2 = models.Author.objects.get(id=2)
book_obj.authors.add(author1, author2)
# book_obj.authors.add(*[author1, author2])
By adding primary key id

By author id, adding author information directly book:

book_obj = models.Book.objects.get(id=1)
book_obj.authors.add(1, 2)
# book_obj.authors.add(*[1, 2])

delete

One to one and one to many

After one to one and one to many to find the object is deleted objects, direct delete Delete:

models.Author.objects.get(id=1).delete()

Many to many

Many-to-delete operation requires the use of query objects:

book_obj = models.Book.objects.get(id=1)    # 找到id为1的书
book_obj.authors.remove(3)  #删除id为1的书与id为3的作者之间的关系
book_obj.authors.remove(2, 3) # 删除id为1的书与id为2和3的作者之间的关系
book_obj.authors.clear()  # 清空id为1的书的所有作者信息 

modify

One to one and one to many

Modify the update, and one-to-many operation and single-table is the same:

models.Book.objects.filter(id=1).update(
    title='白洁新版',
    # publishs=models.Publish.objects.get(id=3),
    publishs_id=3
)

Many to many

book_obj.authors.set(['4',])  # 先清空再添加 clear+add  

Inquire

Based on cross-table query object

One to One
Forward inquiry

2 Golden Dragon query the author's home address

author_obj = models.Author.objects.get(name='金龙2')
# author_obj.ad -- 直接拿到authordetail表中的那个条记录对象
print(author_obj.ad.addr)
Reverse Lookup

Inquiries number to 151 at the beginning of the author's name

authordetail_obj = models.AuthorDetail.objects.filter(telephone__startswith='151').first()
print(authordetail_obj.author.name)
Many
Forward inquiry

Bai Jie new version of the book which is published by the

book_obj = models.Book.objects.filter(title='白洁新版').first()
print(book_obj.publishs.name)
Reverse Lookup

Tokyo publishing house published a book which

pub_obj = models.Publish.objects.get(name='东京出版社')
books = pub_obj.book_set.all().values('title')
# 东京出版社出版的名称中还有白洁的那些书
books = pub_obj.book_set.filter(title__contains='白洁').values('title')
print(books)
Many to many
Forward inquiry

Bai Jie new version of the author of this book who have

book_obj = models.Book.objects.filter(title='白洁新版').first()
authors = book_obj.authors.all().values('name')
print(authors)
Reverse Lookup

Inquiries about what book to write Jinlong 2

jinlong2_obj = models.Author.objects.get(name='金龙2')
ret = jinlong2_obj.book_set.all().values('title')
print(ret)
Cross-table query summary
  • Forward Query by property
  • If you are one, reverse lookup by class name in lowercase
  • And many-to-many, reverse lookup by class name in lowercase _set

Based on cross-table double-underlined query (join)

One to One

Forward-linked table on property

Query Xudong home address

ret = models.Author.objects.filter(name='旭东').values('ad__addr')
print(ret)

If expressed in SQL statements, it should look like this:

select app01_authordetail.addr from app01_author inner join app01_authordetail on app01_author.ad_id = app01_authordetail.id where app01_author.name='旭东';

Even reverse the table class name in lowercase

ret = models.AuthorDetail.objects.filter(author__name='旭东').values('addr')
print(ret)

Many

Discover what books published by Tokyo.

If the direct use of SQL statements should be written:

select app01_book.title from app01_publish inner join app01_book on app01_publish.id = app01_book.publishs_id where app01_publish.name='东京出版社';

The use of ORM, is written like this:

ret = models.Publish.objects.filter(name='东京出版社').values('book__title')
print(ret)
ret = models.Book.objects.filter(publishs__name='东京出版社').values('title')
print(ret)

Many to many

Inquiries about what book to write Jinlong 2

ret = models.Book.objects.filter(authors__name='金龙2').values('title')
print(ret)

ret = models.Author.objects.filter(name='金龙2').values('book__title')
print(ret)

Aggregate query

aggregate aggregate queries, the result is ordinary dictionary, QuerySet terminator.

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

obj = models.Book.objects.all().aggregate(a=Max('price')) #{'price__avg': 200.0}
print(obj)
Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) 

Grouping queries

Grouping queries written in SQL statement should be:

group by app01_book.publishs_id

For example: find the highest price of each book published by

After the first group values

ret = models.Book.objects.values('publishs_id').annotate(m=Max('price'))
print(ret)

Summary: values ​​written on the front annotate, meaning based on field values ​​in parentheses as the basis for grouping. annotate there is statistical results you have to do. Thus, the result is returned queryset type data, which is a dictionary:

{'publishs_id':1,'m':100}

After the first group values

ret = models.Publish.objects.annotate(m=Max('book__price')).values('m', 'name')
print(ret)

Summary: annotate directly written on the back of objects, meaning that all of the data in accordance with the previous table (the default is id value) of the grouping. Return result is that all models objects in front of the table (each object contains its statistical model object), and then to the value by values. Fields can write and direct statistical results when the value of an alias, also queryset type, which is the dictionary:

{'m': 100, 'name': '东京出版社'}

Queries highest price for each author's name and the publication of the book:

ret = models.Book.objects.values('authors__name', 'authors__id').annotate(m=Max('price'))  # group by authors__name,authors__id
print(ret)

ret = models.Author.objects.annotate(m=Max('book__price')).values('name', 'm')
print(ret)

Query F

Import ways:

from django.db.models import F

The results are in Table F query result set qualified after comparison of two fields.

Like point is greater than the number of inquiries about all the books the number of comments.

In the past, we can also be found by using a loop:

list1 = []
books = models.Book.objects.all()
for i in books:
    if i.dianzan > i.comment:
        list1.append(i)

If you are using F query, the code will be more simple and intuitive:

ret = models.Book.objects.filter(dianzan__gt=F('comment')).values('title')

ret = models.Book.objects.filter(dianzan__lt=F('comment')).values('title')
print(ret)

Field This four operations:

models.Book.objects.all().update(
    price=F('price') + 20  # 支持四则运算
)

Q query

Import ways:

from django.db.models import Q

Performs a logical operation for the query Q, Q of the connector:

& -- and
| -- or
~ -- not,取反

Like inquiries about point greater than 300 or less than the price of the book 300

ret = models.Book.objects.filter(Q(dianzan__gt=300)|~Q(price__lt=500),xx='oo').values('title')

ret = models.Book.objects.filter(Q(dianzan__gt=300)).values('title')

ret = models.Book.objects.filter(Q(Q(dianzan__gt=300)|~Q(price__lt=500))&Q(xx='oo')).values('title')    # Q查询能够进行各种复杂条件的拼接
print(ret)

Multi-table queries practice example:

    # 1 查询每个作者的姓名以及出版的书的最高价格
    ret = models.Author.objects.values('id','name').annotate(m=Max('book__price'))
    
    print(ret)

    # 2 查询作者id大于2作者的姓名以及出版的书的最高价格
    ret = models.Author.objects.filter(id__gt=2).values('name').annotate(a=Max('book__price'))
    print(ret)


    # 3 查询作者id大于2或者作者年龄大于等于3岁的女作者的姓名以及出版的书的最高价格
    ret = models.Author.objects.filter(Q(id__gt=2)|Q(Q(age__gte=3)&Q(sex='女'))).values('name').annotate(a=Max('book__price'))
    print(ret)

    # 4 查询每个作者出版的书的最高价格 的平均值
    ret = models.Book.objects.values('authors__name').annotate(m=Max('price')).aggregate(a=Avg('m'))
    print(ret)

    # 5 每个作者出版的所有书的最高价格以及最高价格的那本书的名称
    ret = models.Book.objects.values('authors__name').annotate(m=Max('price'))
    queryset({'authors__name':'xx','m':100},{'authors__name':'xx','m':100},)

Guess you like

Origin www.cnblogs.com/shuoliuchina/p/12521556.html