Django之模型層

Django之模型層

關鍵性字段及參數

AutoField:
    int自增列,必須填入參數primary_key=True,當model中若是沒有自增列,則會自動建立一個名爲id的列

IntegerField:
    一個整數類型,範圍在-2147483648 to 2147483647(通常不用來存手機號,位數也不夠,直接用字符串存)

CharField:
    字符類型,必須提供max_length參數,max_length表示字符長度

注意:django中的CharField對應Mysql數據庫中的varchar類型,沒有設置對應char類型的字段,可是能夠自定義新的字段

DateField:
    日期字段,日期格式:年月日,至關於python中的datetime.date()

DateTimeField:
    日期時間字段,格式:年月日 時分秒,至關於python中的datetime.datetime()

上述兩個日期字段有兩個配置參數:
    配置auto_now_add=True:建立數據的時候會把當前時間添加到數據庫
    配置auto_now=True:每次更新數據記錄的時候會更新該字段

自定義char類型字段python

from django.db import models

# Create your models here.
#Django中沒有對應的char類型字段,可是咱們能夠本身建立
class FixCharField(models.Field):
    '''
    自定義的char類型的字段類
    '''
    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):
        '''
        限定生成的數據庫表字段類型char,長度爲max_length指定的值
        :param connection:
        :return:
        '''
        return 'char(%s)'%self.max_length
#應用上面自定義的char類型
class Class(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=32)
    class_name=FixCharField(max_length=16)
    gender_choice=((1,'男'),(2,'女'),(3,'保密'))
    gender=models.SmallIntegerField(choices=gender_choice,default=3)

單獨的py文件測試ORM操做須要配置的參數sql

import os


if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day58.settings") #上面幾句從manage.py中複製過來
    import django
    django.setup()
    from app01 import models  #這句話必須在這下面導入

單表操做

新增數據

#第一種:有返回值,而且就是當前被建立的數據對象
  modles.Book.objects.create(name='',price='',publish='',author='',create_time='2019-5-1')

#第二種:先實例化產生對象,而後調用save方法保存
book_obj = models.Book(name='',price='',publish='',author='',create_time='2019-5-1')
book_obj.save()

刪除數據

#queryset方法
res = models.Book.objects.filter(name='').delete()

#對象放法
res = models.Book.objects.filter(name='').first()
res.delete()

修改數據

#queryset修改
models.Book.objects.filter(name='').update(price='')

#對象修改
book = models.Book.objects.filter(name='').first()
book.price = 66.66
book.save()  #對象只有保存方法,這樣也能實現修改需求

查詢數據

1.all():查詢全部結果

2.filter(**kwargs):它包含了與所給篩選條件相匹配的對象
res = models.User.objects.filter(name='jason',age=17)
filter內能夠放多個限制條件可是須要注意的是多個條件之間是and關係

3.get(**kwargs):返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會報錯,不推薦

4.exclude(**kwargs):它包含了與所給篩選條件不匹配的對象
res = models.User.objects.exclude(name='lucas')

5.order_by('字段名'):對查詢結果排序(升序),若是字段名前加-,則反序排
res = models.User.objects.order_by('age')   # 默認是升序
res = models.User.objects.order_by('-age')  # 能夠在排序的字段前面加一個減號就是降序

6.reverse():對查詢結果反向排序,注意要先有排序才能反向
res = models.User.objects.order_by('age').reverse()

7.count():返回數據庫中匹配查詢(queryset)的對象數量
res = models.User.objects.count()
res = models.User.objects.all().count()
res = models.User.object.filter(pk=1).count()

8.first():返回第一條記錄
res = models.User.objects.all().first()
res = models.User.objects.all()[0] #不支持負數

9.last():返回最後一條記錄
res = models.User.objects.all().last()

10.exists():若是queryset包含數據,就返回True,不然返回False
 res = models.User.objects.all().exists()
 res1 = models.User.objects.filter(name='jason',age=3).exists()
 
11.values('字段名',):返回一個特殊的queryset,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列
res = models.User.objects.values('name')  #列表套字典
res = models.User.objects.values('name','age')

12.values_list('字段名'):與values()很是類似,返回的是一個元組序列,values返回的是一個字典序列
res = models.User.objects.values_list('name','age')  #列表套元組

13.distinct():從返回結果中剔除重複記錄
res = models.User.objects.values('name','age').distinct()

基於雙下劃線的查詢

# 價格大於
filter(price__gt='90')

# 價格小於
filter(price__lt='90')

# 價格大於等於
filter(price__gte='90')

# 價格小於等於
filter(price__lte='90')

# 存在與某幾個條件中
filter(price__in=['11','22','33'])

# 在某個範圍
filter(price__range=[50,90]) #顧頭顧尾

# 模糊查詢
filter(title__contains='n')  # 區分大小寫
filter(title__icontains='P')  # 忽略大小寫

# 以什麼開頭
filter(name__startswith='y')

# 以什麼結尾
filter(name__endswith='m')

# 按年查詢
filter(ctime__year='2019')
返回queryset對象的方法:all()、filter()、exclude()、order_by()、reverse()、distinct()
 
values():返回一個可迭代的字典序列

values_list():返回一個可迭代的元組序列

多表操做

表與表之間的關係

一對一(OneToOneField):一對一字段不管建在哪張表裏面均可以,可是推薦建在查詢頻率比較高的那張表裏面數據庫

一對多(ForeignKey):一對多字段建在多的那一方django

多對多(ManyToManyField):多對多字段不管建在哪張表裏面均可以,可是推薦建在查詢頻率比較高的那張表裏面app

新增

# 直接寫id
models.Book.objects.create(title='紅樓夢',price=66.66,publish_id=1)
# 傳數據對象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='三國演義',price=199.99,publish=publish_obj)

修改

# queryset修改
models.Book.objects.filter(pk=1).update(publish_id=3)
# 傳對象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)

# 對象修改
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.publish_id = 3  # 點表中真實存在的字段名
book_obj.save()

publish_obj = models.Publish.objects.filter(pk=2).first()
book_obj.publish = publish_obj # 點orm中字段名,傳該字段對應的表的數據
book_obj.save()

刪除

# queryset刪除
models.Book.objects.filter(pk=1).delete()
# 對象刪除
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.delete()

多表綁定關係

添加關係

# add:支持傳數字或對象,而且均可以傳多個
# 直接寫id
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.author.add(1)  # 給id爲3的書綁定做者id爲1的做者
book_obj.author.add(2,3)  # 給id爲3的書綁定做者id爲2和3的做者

# 傳對象
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.author.add(author_obj)

修改

# set:傳的必須是可迭代對象
book_obj = models.Book.objects.filter(pk=3).first()
# 能夠傳數字或對象,而且支持傳多個
book_obj.author.set((1,))  # 將以前的綁定關係清掉,從新與做者id爲1的綁定

book_obj.author.set((1,2,3))

# 傳對象
author_list = models.Author.objects.all()
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.author.set(author_list)

刪除

# remove:能夠傳數字或對象,而且支持多個
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.author.remove(1)  # 刪除id爲3的書與id爲1的做者的綁定關係
book_obj.author.remove(2,3)
# 傳單個對象
author_obj = models.Author.objects.all().first()
book_obj.author.remove(author_obj)
# 傳多個對象
author_list = models.Author.objects.all()
book_obj.author.remove(*author_list)  # 須要將queryset打散

清空

# clear:清空的是你當前這個表記錄對應的綁定關係
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.author.clear()  # 清空id爲3的書與做者的綁定關係

基於對象的表查詢

正向:查詢按字段測試

book_obj = models.Book.objects.filter(title='三國演義').first()
print(book_obj.publish.email)  # 查詢三國演義對應出版社的郵箱,多對一的關係,.字段名就能直接跳轉到對應的publish表,而且就是一個對象,直接.屬性就能拿到值

book_obj = models.Book.objects.filter(title='西遊記').first()
print(book_obj.author.all())  # 查詢西遊記對應的做者,多對多關係,.字段名跳轉到author表,可是不能直接經過.屬性拿到值

user_obj = models.Author.objects.filter(name='lucas').first()
print(user_obj.authordetail.phone)  # 查詢名爲lucas的電話號碼,一對一關係,.字段名跳轉到對應的authordetail表,直接.屬性拿到值

反向:查詢按對應表名小寫code

publish_obj = models.Publish.objects.filter(name='東方出版社').first()
print(publish_obj.book_set.all())  # 查詢東方出版社出版的書,一對多關係,

author_obj = models.Author.objects.filter(name='lucas').first()
print(author_obj.book_set.all())  # 查詢lucas寫過的全部書,多對多關係

authordetail_obj = models.AuthorDetail.objects.filter(phone=111).first()
print(authordetail_obj.author.name)  # 查詢電話號碼爲111的做者,一對一關係

基於雙下劃線的查詢

正向orm

res = models.Book.objects.filter(title='三國演義').values('publish__addr','title')
print(res)  # 查詢書籍爲三國演義的出版社地址,字段名__屬性就能直接拿到值

res = models.Book.objects.filter(title='西遊記').values("authors__name",'title')
print(res)  # 查詢書籍爲西遊記的做者的姓名

res = models.Author.objects.filter(name='lucas').values('authordetail__addr')
print(res)  # 查詢做者lucas的家鄉

反向對象

res = models.Publish.objects.filter(name='南方出版社').values('book__title')
print(res)  # 查詢南方出版社出版的書

res = models.AuthorDetail.objects.filter(phone=120).values('author__name')
print(res)  # 查詢電話號碼爲120的做者姓名

res = models.Author.objects.filter(name='lucas').values('book__title')
print(res)  # 查詢做者爲lucas的寫的書的名字

res = models.Book.objects.filter(title='三國演義').values('authors__authordetail__phone')
print(res)  # 查詢書籍爲三國演義的做者的電話號碼
# 查詢lucas做者的手機號
# 正向
res = models.Author.objects.filter(name='lucas').values('authordetail__phone')
print(res)

# 反向
res = models.AuthorDetail.objects.filter(author__name='lucas').values('phone')
# 查詢出版社爲東方出版社的全部圖書的名字和價格
# 正向
res = models.Publish.objects.filter(name='東方出版社').values('book__title','book__price')
# 反向
res = models.Book.objects.filter(publish__name='東方出版社').values('title','price')
# 查詢東方出版社出版的價格大於400的書
# 正向
res = models.Publish.objects.filter(name='東方出版社',book__price__gt=400).values('book__title')

# 反向
res = models.Book.objects.filter(price__gt=400,publish__name='東方出版社').values('title')

集合查詢 aggregate

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

# 查詢書籍id爲3的做者個數
res = models.Book.objects.filter(pk=3).aggregate(count_num=Count('author'))  # k,v鍵值對

# 查詢全部出版社出版的平均價格
res = models.Publish.objects.aggregate(avg_price=Avg('book__price'))

# 統計東方出版社出版的書籍的個數
res = models.Publish.objects.filter(name='東方出版社').aggregate(count_num=Count('book__id'))

分組查詢(group by) annotate

# 統計每一個出版社出版的書的平均價格
res = models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name','avg_price')

# 統計每一本書的做者的個數
res = models.Book.objects.annotate(count_num=Count('author')).values('title','count_num')

# 統計出每一個出版社賣的最便宜的書的價格
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')

# 查詢每一個做者出的書的總價格
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')

django終端打印sql語句(瞭解)

若是你想知道你對數據庫進行操做時,Django內部究竟是怎麼執行它的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',
        },
    }
}

配置好以後,再執行任何對數據庫進行操做的語句時,會自動將Django執行的sql語句打印到pycharm終端上

相關文章
相關標籤/搜索