django model layer (orm) 05

Configuration Test Script

Mode 1:

# 如果想单独测试django中的某个文件,需要手动配置测试脚本(在你应用下的tests.py文件中)
import os
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day55.settings")
    import django
    django.setup()
    
    # 在测试脚本搭建完毕之后,才能导入django文件进行测试
    from app01 import models

Option 2:

New direct an arbitrary name .py files, the way in 1 configured to take over the line.

django ORM basic operations

CRUD

First, create a model table:

from django.db import models
# Create your models here.
class Books(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateField()

1. Add (create ())

Add a record to the database

# 第一种 :
book_obj = models.Books.objects.create(title = '人性的弱点',price='172.44',publish_date='2008-08-08')  # 日期格式可以直接写,也可以通过datetime模块生成一个年月日传进去

# 第二种:(利用对象的绑定方法)
book_obj = models.Books(title = '未来简史',price='399.44',publish_date='2008-08-09')
book_obj.save()
'''
返回的是对象本身
'''

2. Modify (update ())

Table modify some fields in a record

res=models.Books.objects.filter(id=1).filter().filter().filter()...
'''
id可以写成pk,表示任意一张表的主键字段,我们不需要记自己建表时设置的主键字段的名字,直接写成pk=? 的形式,就more你是当前表的主键了;
返回的res是一个QuerySet对象,可以无限制的调用queryset对象,表示按照当前filter查询的结果继续按照你写的条件继续往下查询;
queryset对象还可以点query查看当前结果内部对应的sql语句
'''
res=models.Books.objects.filter(id=1)
print(res.query)
'''
SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1
'''

#方式1:
models.Books.objects.filter(id=1).update(price=88.88) # 当条件不存在时,filter空queryset对象,推荐使用filter进行查询。

# 方式2:
book_obj = models.Books.objects.get(pk=1)  # 返回的是对象本身,get在条件不存在时会报错,不推荐使用这种方法做修改操作。
book_obj.price = 88.88
book_obj.save()

3. Delete (delete ())

To delete a record in the table

# 方式1:
models.Books.objects.filter(pk=3).delete()
# 方式2:
book_obj = models.Books.objects.get(pk=3)
book_obj.delete()

Django terminal print SQL statements

For the sql statement inside your query orm corresponding print in the terminal, you can configure the following code in Django project settings.py configuration file:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

13 The basic query operations

all()

All inquiries

res = models.Books.objects.all()  # 查询所有 ,返回的结果QuerySet对象
'''
<QuerySet [<Books: Books object>, <Books: Books object>, <Books: Books object>, <Books: Books object>, <Books: Books object>, <Books: Books object>, <Books: Books object>, <Books: Books object>]>
'''

filter()

filter

res = models.Books.objects.filter(pk=2,title='活着')  # 返回的结果QuerySet对象,支持传多个参数 并且是and关系

get()

filter

res = models.Books.objects.get(title='活着',price = '99.9') # 获取的是数据对象本身,查询条件不存在报错,也可以传多个参数
'''
Books object
'''

first()

Queryset take the first data object, the return is a normal of the data object

res = models.Books.objects.filter(title='活着').first()

last()

Queryset taking the last data object, return is a normal data object

res = models.Books.objects.filter(title='活着').last()

count()

Number of statistical data, returns the number (number of data)

num = models.Books.objects.count()

values()

Gets the value of the data object specified in the field

# 按照指定条件查询
res = models.Books.objects.filter(pk=2).values('title','price')
print(res)  # <QuerySet [{'title': '活着', 'price': Decimal('99.90')}]>

# 查所有
res = models.Books.objects.values('title','price') # 可以传多个参数, 返回的是QuerySet对象,列表套字典
'''
<QuerySet [{'title': '三国演义', 'price': Decimal('99.99')}, {'title': '活着', 'price': Decimal('99.90')}, {'title': '许三多卖血记', 'price': Decimal('199.88')}, {'title': '平凡的世界', 'price': Decimal('166.66')}, {'title': '富国论', 'price': Decimal('888.88')}, {'title': '鬼谷子', 'price': Decimal('35.55')}, {'title': '人性的弱点', 'price': Decimal('172.44')}, {'title': '人性的弱点', 'price': Decimal('172.44')}]>
'''

values_list()

Gets the value of the data object specified in the field

res = models.Books.objects.values_list('title','price') # 可以传多个参数, 返回的是QuerySet对象,列表套元组
'''
<QuerySet [('三国演义', Decimal('99.99')), ('活着', Decimal('99.90')), ('许三多卖血记', Decimal('199.88')), ('平凡的世界', Decimal('166.66')), ('富国论', Decimal('888.88')), ('鬼谷子', Decimal('35.55')), ('人性的弱点', Decimal('172.44')), ('人性的弱点', Decimal('172.44'))]>
'''

order_by()

In accordance with the specified sort field

# 升序(两种写法)
res = models.Books.objects.order_by('price') # 默认是升序,返回的是queryset对象
res1 = models.Books.objects.all().order_by('price')
# 降序
res = models.Books.objects.order_by('-price')  # 字段前面加负号
res = models.Books.objects.order_by('price').values('title','price')
print(res)  # queryset对象可以继续通过点语法操作
'''
<QuerySet [{'title': '鬼谷子', 'price': Decimal('35.55')}, {'title': '活着', 'price': Decimal('99.90')}, {'title': '三国演义', 'price': Decimal('99.99')}, {'title': '平凡的世界', 'price': Decimal('166.66')}, {'title': '人性的弱点', 'price': Decimal('172.44')}, {'title': '人性的弱点', 'price': Decimal('172.44')}, {'title': '许三多卖血记', 'price': Decimal('199.88')}, {'title': '富国论', 'price': Decimal('888.88')}]>
'''

reverse()

Reverse the order, it must be ordered under the circumstances in order to reverse

res = models.Books.objects.all().order_by('price').reverse()

'''
res = models.Books.objects.reverse().values('title','price') # 不排序的情况下返回值按照数据库的id顺序打印,没办法帮你颠倒
print(res)  

res = models.Books.objects.all().order_by('price').reverse().values('title', 'price')
print(res)
"""
<QuerySet [{'title': '富国论', 'price': Decimal('888.88')}, {'title': '许三多卖血记', 'price': Decimal('199.88')}, {'title': '人性的弱点', 'price': Decimal('172.44')}, {'title': '人性的弱点', 'price': Decimal('172.44')}, {'title': '平凡的世界', 'price': Decimal('166.66')}, {'title': '三国演义', 'price': Decimal('99.99')}, {'title': '活着', 'price': Decimal('99.90')}, {'title': '鬼谷子', 'price': Decimal('35.55')}]>
"""
'''

exclude()

The exclusion, in accordance with the data specified conditions, the return data other than the excluded data

# 方式1
res = models.Books.objects.all().exclude(title='三国演义')  # queryset对象
# 方式2
res = models.Books.objects.exclude(title='三国演义')

exists()

Determine whether the results have value returns the result is a Boolean value

res = models.Books.objects.filter(pk=1).exists()
print(res)

distinct()

According to the conditions specified weight

res = models.Books.objects.values('title','price').distinct() # 可以传入多个去重条件,把这多个条件都一样的数据剔除掉  返回的是一个queryset对象

Dual-line query decline

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据;,也可以写成括号的形式
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
models.Tb1.objects.filter(name__contains="活")  # 获取name字段包含"活"的
models.Tb1.objects.filter(name__icontains="活") # icontains大小写不敏感
models.Tb1.objects.filter(id__range=[1, 3])  # id范围是1到3的,顾头顾尾 ,也可以写成括号的形式
res = models.Tb1.objects.filter(title__endswith='活')  # 以“活”开头的
res = models.Tb1.objects.filter(title__endswith='活')  # 以“活”结尾的

date字段:
date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据

res=models.Tb1.objects.filter(publish_date='2008-08-08') # 指定年月日

res=models.Tb1.objects.filter(publish_date__lte='2002-03-28')  # 日期小于等于2002-03-28的  也可以是lt,或者单独指定year,month,day

res=models.Tb1.objects.filter(publish_date__gte='2002-03-28')  # 日期大于等于2002-03-28的  也可以是gt
res=models.Tb1.objects.filter(publish_date__year='2007') # 只指定年份
res=models.Tb1.objects.filter(publish_date__month='08')  # 指定月份
res=models.Tb1.objects.filter(publish_date__day='29')  # 指定某一天

 models.Tb1.objects.filter(publish_date__week_day=2)  
 models.Tb1.objects.filter(publish_date__week_day__gte=2)

Table query

To build the table

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)
    stored = models.IntegerField(default=1000)
    saled = models.IntegerField(default=1000)

    def __str__(self):  # 打印对象是触发,控制打印格式
        return self.title
    """
      auto_now:每次修改的数据的时候 都会自动更新修改书籍(展示最新的一次修改时间)
      auto_now_add:当数据创建出来的时候 会自动将创建时间记录下来
   """

    publish = models.ForeignKey(to='Publish')  # 一对多关系,外键字段建在查询频率较高的一方
    authors = models.ManyToManyField(to='Author') # 多对多关系,多对多字段建在查询频率较高的一方

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

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()  #  对应到数据库的表当中是varchar类型,长度是254
    author_detail = models.OneToOneField(to='AuthorDetail')  # 一对一关系,一对多字段建在查询频率较高的一方
    def __str__(self):
        return self.name

class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=64)
    def __str__(self):
        return self.addr
'''
模型表类建完以后,要使用数据库迁移命令,把表迁移到数据库当中,建表才算完毕
python3 manage.py makemigrations
python3 manage.py migrate
'''

Deletions of many field data change search

increase

# 方式1:
models.Book.objects.create(title='三国演义',price=222.33,publish_id=1)  # 直接传表里面的实际字段和数据主键值  
# 方式2:
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj)  # 传虚拟字段  跟数据对象即可

change

# 方式1:
models.Book.objects.filter(pk=1).update(publish_id=2)
# 方式2:
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)

delete

models.Publish.objects.filter(pk=1).delete() # 默认级联删除,级联更新,这里删除id=1的出版社,出版社id=1的图书也都跟着删除

Deletions of many to many field data change search

Increase (add)

book_obj = models.Book.objects.filter(pk=2).first()
# print(book_obj.publish) # Publish object
# print(book_obj.authors) # app01.Author.None  已经跨到第三张表了

# 方式1:(add支持传入多个,以逗号分开)
book_obj.authors.add(1) # 在第三张表里面给此书籍对象绑定一个author_id=1的作者  

# 方式2:
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj1,author_obj2)  

Summary : the Add method to add data toward the third relational table, which is to support digital transmission - "add (1,2); also supports objects pass, add (author_obj, author_obj1); and both may be plural.

Change (set)

book_obj = models.Book.objects.filter(pk=2).first()
# 方式1:
book_obj.authors.set((1,3))
book_obj.authors.set([1,])
# 方式2:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj,author_obj1))

Summary : SET method for modifying data in the table-many relationship, the digital transmission may be an object to be passed, but one or more parameters passed in must be the object an iterative, i.e. by parentheses or brackets, inside incoming number of parameters you need. ps: set ((1,3)) , set ((author_obj, author_obj1))

Delete (remove)

book_obj = models.Book.objects.filter(pk=2).first()
# 方式1:
book_obj.authors.remove(100)
book_obj.authors.remove(1,2)
# 方式2:
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj,author_obj1)

Summary : Remove method , either the digital transmission may be subject to wear; and a plurality of mass support no iteration; ps: remove (1,2), remove (author_obj, author_obj1)

Clear (clear)

Delete all recorded data in a third table

 book_obj = models.Book.objects.filter(pk=2).first()
 book_obj.authors.clear()

Cross-table query

Pros and cons to the query:
are object-based query across tables
relationship field in which anyone who is associated with the look-up table is positive
if the relationship field is not in the current table is reverse

Forward query by field: forward query, the query is out when there are a plurality of data, it is necessary point .all (); ps: app01.Author.None, once they see the results only need to add .all () to

** reverse lookup by table name in lowercase + _set: ** However, in many, many to many circumstances, only need to add; in one to one relationship, no show lowercase plus _set.

Forward inquiry

1. Discover books primary key for the name of the publisher 2

book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish)  # 出版社对象
print(book_obj.publish.name)

2. Query the primary key for the name of the author of books 4

book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors)  # app01.Author.None,跨入到了Author这张表中。
print(book_obj.authors.all())   # 一本书可能有多个作者,所以需要点.all()  返回的是queryset对象,列表内部是一个个的作者对象<QuerySet [<Author: Author object>, <Author: Author object>]>,这个是设置打印格式之后的显示:<QuerySet [<Author: zhang>, <Author: liu>]>,表示id=4 的书籍,有两个作者。

3. Query author is jason phone number

author_obj = models.Author.objects.filter(name='zhang').first()
print(author_obj.author_detail)  # AuthorDetail object
print(author_obj.author_detail.phone)

Summary: Forward inquiry, when queried out there are a plurality of data, the need to point .all ();

ps: app01.Author.None, once they see the results only need to add .all () can

Reverse Lookup

4. Inquiries Press is Oriental Press published books

publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set)  # app01.Book.None
print(publish_obj.book_set.all())

5. Query author is jason wrote books

author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set)  # app01.Book.None
print(author_obj.book_set.all())  # app01.Book.None

6. The phone number is the author name query 120

author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author)  # Author object  不需类名小写+_set,直接作者详情对象点类名(Author)小写即可 
print(author_detail_obj.author.email)  # 120qq.com

Cross-table query based on the double line of decline

Based on the operating table query with a double decline line, make a table consisting of two tables, the use of a django orm statement can check out the information you want, make the operation more concise of.

1. Query books for the publishing house name 2 pk

# 方式1:正向查询
res = models.Book.objects.filter(pk=2).values('publish__name')
print(res)  # <QuerySet [{'publish__name': '东方出版社'}]>
# 方式2:反向查询
res = models.Publish.objects.filter(book__pk=2).values('name')
print(res)  # <QuerySet [{'name': '北方出版社'}]>

2. Query books as author name and email pk 2

# 方式1:正向查询
res =models.Book.objects.filter(pk=2).values('authors__name','authors__email')
print(res)  # <QuerySet [{'authors__name': 'zhang', 'authors__email': '[email protected]'}, {'authors__name': 'liu', 'authors__email': '120qq.com'}]>  不需要像上面基本方法的跨表查询,这里不需要用点.all()

# 方式2:反向查询
res =models.Author.objects.filter(book__pk=2).values('name','email')
print(res)  # <QuerySet [{'name': 'zhang', 'email': '[email protected]'}, {'name': 'liu', 'email': '120qq.com'}]>

Summary : whoever models later point in the base table Who

3. Query author is egon home address

# 方式1:正向查询
res=models.Author.objects.filter(name='egon').values('author_detail__addr')
print(res)

# 方式2:反向查询
res=models.AuthorDetail.objects.filter(author__name='egon').values('addr')
print(res)

4. Press the query is the name of Oriental Press published the book

# 方式1:正向查询
res = models.Publish.objects.filter(name='东方出版社').values('book__title')
print(res)

# 方式2:反向查询
res = models.Book.objects.filter(publish__name='东方出版社').values('title')
print(res)

5. Query is the author of 2 books pk phone number

# 方式1:正向查询
res=models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
print(res)

# 方式2:反向查询
res=models.Author.objects.filter(book__pk=2).values('author_detail__phone')
print(res)

Aggregate function

1. Keyword aggregate

2. The modules also need to import
from django.db.models import Max, Min, Sum , Avg, Count

from django.db.models import Max, Min, Sum, Count, Avg
 # 1.筛选出价格最高的书籍的
 res = models.Book.objects.aggregate(mr = Max('price'))
 print(res)  # {'mr': Decimal('222.99')}
    
 # 2.求书籍总价格
  res = models.Book.objects.aggregate(sm = Sum('price'))
  print(res)  # {'sm': Decimal('600.58')}

  # 3.求书籍平均价格
  res = models.Book.objects.aggregate(av = Avg('price'))
  print(res)   # {'av': 150.145}
  # 4.一起使用
  res=models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price'))
  print(res)
'''
{'price__max': Decimal('222.99'), 'price__min': Decimal('88.80'), 'price__sum': Decimal('600.58'), 'price__count': 4, 'price__avg': 150.145}
'''

Grouping queries

1. Keyword Annotate
2. functions by means of polymerization
from django.db.models import Max, Min, Sum , Avg, Count

1. The number of statistics for each book title and number of the corresponding author

res=models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
print(res)

2. Press the statistics of each book sold the cheapest price Press Name Price

res=models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
print(res)

3. statistics more than a book author

res=models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
print(res)

4. The total price of each query of the total price of the book's name

res=models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
print(res)

F Q queries and query

Query F

  1. Check inventory number is greater than the number of books sold
from django.db.models import F,Q
res = models.Book.objects.filter(kun_cun__gt = F('mai_cun')).values('title')  # 后面的条件是来自于数据库的其他字段值
print(res)  # <QuerySet [{'title': '天龙八部'}]>

2. The price of all books rose 100

models.Book.objects.all().update(price=F('price') + 100)

3. The names of all the back of the book all the words "explosion models" suffix

from django.db.models.functions import Concat
from django.db.models import Value
ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))

Q query

1. The title of the book is an inquiry about the Three Kingdoms books or inventory number is 500

from django.db.models import Q
res = models.Book.objects.filter(title='三国演义',kun_cun=500)  # and关系
res = models.Book.objects.filter(title='三国演义',kun_cun=500)  # and关系
res = models.Book.objects.filter(Q(title='三国演义'),Q(kun_cun=500))# Q包裹之后逗号还是and关系
res = models.Book.objects.filter(Q(title='三国演义') | Q(kun_cun=500))  #  |就是or的关系
res = models.Book.objects.filter(~Q(title='三国演义')|Q(kun_cun=500))  # ~就是not关系
print(res)

Q Objects Advanced Usage

q = Q()
q.connector = 'or'  # 默认是and  可以改成or
q.children.append(('title','三国演义'))
q.children.append(('kun_cun__gt',500))
res = models.Book.objects.filter(~q)  # 取反
print(res)

from django.db import transaction

with transaction.atomic():
    # 在缩进的代码中书写数据库操作
    # 该缩进内的所有代码 都是一个事务
    pass

orm fields and parameters

orm字段及参数
    CharField     varchar
    IntegerField   int
    BigIntegerField   bigint
    EmailField    varchar(254)
    DateField
    DateTimeField
    
    auto_now:每次修改数据的时候 都会自动将当前修改时间更新上去  实时更新
    auto_now_add:在创建数据的时候 会将当前时间自动记录 之后不会自动修改  除非你人为修改
        
     AutoField     auto_increment   

     BooleanField    布尔值  
        该字段在存储的时候 你只需要传布尔值True或False
         它会自动存成1/0
        
     TextField  专门用来存大段文本

     FileField  专门用来文件路径   '/etc/data/a.txt'   
        upload_to = '/etc/data'
        给该字段传值的时候 直接传文件对象
        会自动将文件对象保存到upload_to后面指定的文件路径中
        然后将路径保存到数据库
        
    DecimalField(Field)
    - 10进制小数
    - 参数:
        max_digits,小数总长度
        decimal_places,小数位长度

Custom char field

# 如何自定义字段类型
class MyCharField(models.Field):
    def __init__(self,max_length,*args,**kwargs):
        self.max_length = max_length
        # 重新调用父类的方法
        super().__init__(max_length=max_length,*args,**kwargs)

     def db_type(self, connection):
         return 'char(%s)'%self.max_length

Guess you like

Origin www.cnblogs.com/zhangchaocoming/p/11955422.html