ディレクトリ
設定のテストスクリプト
モード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
- チェック在庫数が販売、書籍の数よりも大きいです
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