Djangoのモデル層(ORM)05

設定のテストスクリプト

モード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

オプション2:

新任意の名前の.pyファイル、ラインを引き継ぐように設定1で道を指示します。

DjangoのORMの基本的な操作

CRUD

まず、モデルのテーブルを作成します。

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. [追加](()を作成します)

データベースにレコードを追加します。

# 第一种 :
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.変更(更新())

表レコード内のいくつかのフィールドを変更します

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())

テーブル内のレコードを削除するには

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

ジャンゴターミナル印刷SQL文

ターミナルでの印刷に対応するクエリのORM内のSQL文について、あなたはDjangoプロジェクトsettings.pyの設定ファイルに次のコードを設定することができます。

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基本的なクエリ操作

すべて()

すべてのお問い合わせ

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>]>
'''

フィルタ()

フィルタ

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

取得する()

フィルタ

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

最初()

最初のデータ・オブジェクトを取るクエリセット、リターンは、データオブジェクトの正常な動作です

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

最終()

クエリセットは、最後のデータオブジェクトを取って、リターンは、通常のデータオブジェクトであります

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

カウント()

統計データの数、返品数(データ数)

num = models.Books.objects.count()

値()

フィールドで指定されたデータオブジェクトの値を取得します。

# 按照指定条件查询
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()

フィールドで指定されたデータオブジェクトの値を取得します。

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()

指定されたソートフィールドに従い、

# 升序(两种写法)
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')}]>
'''

逆()

順序を逆にし、それを逆にするために、状況下で注文する必要があります

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')}]>
"""
'''

除外()

除外されたデータ以外のデータ指定された条件、戻りデータに基づいて排除、

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

()が存在します

結果は、値のリターンを持っているかどうか、結果がブール値であるかを決定

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

別個の()

重みを指定した条件によると、

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

デュアルラインクエリ下落

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)

テーブル作成クエリ

テーブルを作成するには

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
'''

多くのフィールドのデータを変更して再検索の欠失

増加

# 方式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)  # 传虚拟字段  跟数据对象即可

変更

# 方式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)

[削除]

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

多くのフィールドのデータを変更して再検索には多くの欠失

増加(アドオン)

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)  

要約Addメソッドデジタル伝送をサポートするためである、第三のリレーショナルテーブルに向けてデータを追加する- 「(1,2)を追加し、また、オブジェクトが通過サポート、(author_obj、author_obj1)を加え、そして両方が複数であってもよいです。

変更(セット)

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))

要約のためのSETメソッドテーブル対多の関係でデータを修正する、デジタル送信が渡されるオブジェクトであってもよいが、パラメータが渡された1つ以上の括弧またはブラケットによって、すなわち、反復オブジェクトである必要があり、内部あなたが必要とするパラメータの着信番号。PS:セット((1,3)) 、セット((author_obj、author_obj1))

[削除(削除)

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)

要約Removeメソッド、いずれかの摩耗を受けることができるデジタル伝送;および反復質量支持体の複数; PS:削除(1,2)、削除(author_obj、author_obj1)

クリア(クリア)

3番目のテーブルに記録されたすべてのデータを削除します。

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

クロステーブルのクエリ

クエリに長所と短所:
テーブルの間でオブジェクトベースのクエリされている
ルックアップテーブルに関連付けられている誰もが正である関係フィールド
関係フィールドは、現在のテーブルに存在しない場合は逆であります

フィールドによって前方クエリ:データが複数ある場合、前方クエリは、クエリが実行され、それが必要なポイント.ALL(); PS:app01.Author.None、彼らは(のみ.ALL追加する必要がある結果が表示されたら)へ

**小文字+ _set内のテーブル名で逆引き参照:**しかし、多くの中で、多くの状況への多くは、だけで追加する必要があります; 1人の関係、ノーショーの小文字プラス_setを一つに。

フォワード問い合わせ

1.出会う書籍出版社の名前の主キーを2

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

2.クエリ冊の本の著者の名前の主キー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.クエリの作成者はジェイソンの電話番号です

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

要約:フォワード問い合わせ、複数のデータ点.ALLする必要があります()が存在する外照会します。

PS:app01.Author.None、彼らは結果のみ(.ALLを追加する必要が表示されたら)缶

逆引き参照

4.お問い合わせを押して、東洋プレス出版された本であります

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

5.クエリの作成者はジェイソンが本を書いています

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.電話番号は、著者名のクエリ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

衰退の二重線に基づいて、クロステーブルのクエリ

ダブル衰退ラインと手術台のクエリに基づいて、2つのテーブルからなるテーブルを作成し、DjangoのORM文の使用はの操作より簡潔を作り、必要な情報をチェックアウトすることができます。

出版社名2 PK 1.照会書

# 方式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': '北方出版社'}]>

作者の名前とメールPKなど2.クエリの本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'}]>

要約ベーステーブルで誰モデル以降のポイントを

3.クエリの作成者はエゴンホームアドレスであります

# 方式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.クエリは東洋プレスの名前では、本を出版しました

# 方式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.クエリは2冊PK電話番号の著者であります

# 方式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)

集計関数

1.キーワードの集計

また、インポートする必要があります。2.モジュール
django.db.modelsからは、MAX、MIN、合計インポート 、平均、カウントを

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}
'''

クエリをグループ化

1.キーワードの注釈
重合による2.機能
django.db.modelsからは、MAX、MIN、合計インポート 、平均、カウントを

1.対応する著者の各書籍のタイトルや番号の統計情報の数

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

各書籍の2.統計は、最も安い価格を押して名前価格を販売しました

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

3.統計より本の著者より

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

書籍名の合計金額の各クエリの4合計価格

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

F Qクエリとクエリ

クエリF

  1. チェック在庫数が販売、書籍の数よりも大きいです
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.すべての書籍の価格は、100をバラ

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

3.ブックのすべてのバックの名前のすべての単語「爆発モデル」サフィックス

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

Qクエリ

1本のタイトルは、三国の書籍や在庫数についてのお問い合わせは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は、高度な使用法オブジェクト

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フィールドとパラメータ

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,小数位长度

カスタムchar型のフィールド

# 如何自定义字段类型
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

おすすめ

転載: www.cnblogs.com/zhangchaocoming/p/11955422.html