Django:04.ORM操作

一、Django連接數(shù)據(jù)庫(kù)操作

1、創(chuàng)建數(shù)據(jù)庫(kù) (注意設(shè)置 數(shù)據(jù)的字符編碼)
由于Django自帶的orm是data_first類型的ORM,使用前必須先創(chuàng)建數(shù)據(jù)庫(kù)
create database ayalysis default character set utf8 collate utf8_general_ci;
2、修改project中的settings.py文件中設(shè)置 連接 MySQL數(shù)據(jù)庫(kù)(Django默認(rèn)使用的是sqllite數(shù)據(jù)庫(kù))

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'ayalysis',
    'USER': 'totd',
    'PASSWORD': 'totd890',
    'HOST': '192.168.182.128',
    'PORT': '3306',
    }
}

3、查看orm操作執(zhí)行的原生SQL語(yǔ)句,在project中的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',
        },
    }
}

4、修改project 中的__init__py 文件設(shè)置 Django默認(rèn)連接MySQL的方式

import pymysql
pymysql.install_as_MySQLdb()

5、setings文件注冊(cè)APP

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config', 
]

6、進(jìn)行數(shù)據(jù)遷移,在winds cmd或者Linux shell的項(xiàng)目的manage.py目錄下執(zhí)行

python manage.py makemigrations  #根據(jù)app下的migrations目錄中的記錄,檢測(cè)當(dāng)前model層代碼是否發(fā)生變化?
python manage.py migrate         #把orm代碼轉(zhuǎn)換成sql語(yǔ)句去數(shù)據(jù)庫(kù)執(zhí)行
python manage.py migrate --fake    #只記錄變化,不提交數(shù)據(jù)庫(kù)操作

二、字段類型

Django提供了很多字段類型,比如URL/Email/IP/ 但是mysql數(shù)據(jù)沒(méi)有這些類型,這類型存儲(chǔ)到數(shù)據(jù)庫(kù)上本質(zhì)是字符串?dāng)?shù)據(jù)類型,其主要目的是為了封裝底層SQL語(yǔ)句

1. 字符串類

name=models.CharField(max_length=32)

  • EmailField(CharField):
  • IPAddressField(Field)
  • URLField(CharField)
  • SlugField(CharField)
  • UUIDField(Field)
  • FilePathField(Field)
  • FileField(Field)
  • ImageField(FileField)
  • CommaSeparatedIntegerField(CharField)

models.CharField 對(duì)應(yīng)的是MySQL的varchar數(shù)據(jù)類型

MySQL知識(shí)點(diǎn)補(bǔ)充:

char 和 varchar的區(qū)別 :
共同點(diǎn)是存儲(chǔ)數(shù)據(jù)的長(zhǎng)度,不能 超過(guò)max_length限制;
不同點(diǎn)是varchar能根據(jù)數(shù)據(jù)實(shí)際長(zhǎng)度存儲(chǔ),char按指定的max_length來(lái)存儲(chǔ)數(shù)據(jù);所有前者更節(jié)省硬盤空間。

2. 時(shí)間字段(詳細(xì)使用
  • models.DateTimeField(null=True)
  • models.DateField()
  • models.TimeField() # 不常用
3、數(shù)字字段

(max_digits=30,decimal_places=10)總長(zhǎng)度30小數(shù)位 10位)

  • models.IntegerField() # 數(shù)字
  • models.FloatField() # 浮點(diǎn)
  • models.DecimalField(max_digits=8,decimal_places=3) # 精確浮點(diǎn)
4、枚舉字段
choice=(
        (1, '男'),
        (2, '女'),
        (3, '其他')
    )
gender=models.IntegerField(choices=choice)    # 枚舉類型

擴(kuò)展:在數(shù)據(jù)庫(kù)存儲(chǔ)枚舉類型,比外鍵有什么優(yōu)勢(shì)?
1、無(wú)需連表查詢性能低,省硬盤空間(選項(xiàng)不固定時(shí)用外鍵)
2、在modle文件里不能動(dòng)態(tài)增加(選項(xiàng)一成不變用Django的choice)

5、其他字段
db_index = True 表示設(shè)置索引
unique(唯一的意思) = True 設(shè)置唯一索引

聯(lián)合唯一索引
class Meta:
unique_together = (
    ('email','ctime'),
)
聯(lián)合索引(不做限制)
index_together = (
    ('email','ctime'),
)
ManyToManyField(RelatedField)  #多對(duì)多操作

三、字段參數(shù)介紹

  1. 數(shù)據(jù)庫(kù)級(jí)別生效
  2. Django admin級(jí)別生效
    針對(duì) dango_admin生效的參數(shù)(正則匹配)(使用Django admin就需要關(guān)心以下參數(shù)?。。?/li>
  • blank #是否為空
  • editable=False # 是否允許編輯
  • help_text="提示信息" # 提示信息
  • choices=choice # 提供下拉框
  • error_messages="錯(cuò)誤信息" # 錯(cuò)誤信息
  • validators # 自定義錯(cuò)誤驗(yàn)證(列表類型),從而定制想要的驗(yàn)證規(guī)則(EmailValidator,URLValidator,DecimalValidator,MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator)
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator

test = models.CharField(
    max_length=32,
    error_messages={
        'c1': '優(yōu)先錯(cuò)信息1',
        'c2': '優(yōu)先錯(cuò)信息2',
        'c3': '優(yōu)先錯(cuò)信息3',
    },
    validators=[
        RegexValidator(regex='root_\d+', message='錯(cuò)誤了', code='c1'),
        RegexValidator(regex='root_112233\d+', message='又錯(cuò)誤了', code='c2'),
        EmailValidator(message='又錯(cuò)誤了', code='c3'), ]

四、單表操作

1. ORM使用方式

ORM操作可以使用類實(shí)例化,obj.save()的方式,也可以使用create()的形式

2. QuerySet數(shù)據(jù)類型介紹
  • QuerySet與惰性機(jī)制:
    所謂惰性機(jī)制指Userinfo.objects.all()或者.filter()等都只是返回了一個(gè)QuerySet(查詢結(jié)果集對(duì)象),它并不會(huì)馬上執(zhí)行sql,而是當(dāng)調(diào)用QuerySet的時(shí)候才執(zhí)行。
  • QuerySet特點(diǎn):
    <1>可迭代的
    <2>可切片
    <3>惰性計(jì)算和緩存機(jī)制
def queryset(request):
    books=models.Book.objects.all()[:10]  #切片 應(yīng)用分頁(yè)
    books = models.Book.objects.all()[::2]
    book= models.Book.objects.all()[6]    #索引
    print(book.title)
    for obj in books:                     #可迭代
        print(obj.title)
    books=models.Book.objects.all()          #惰性計(jì)算--->等于一個(gè)生成器,不應(yīng)用books不會(huì)執(zhí)行任何SQL操作
    # query_set緩存機(jī)制1次數(shù)據(jù)庫(kù)查詢結(jié)果query_set都會(huì)對(duì)應(yīng)一塊緩存,再次使用該query_set時(shí),不會(huì)發(fā)生新的SQL操作;
    #這樣減小了頻繁操作數(shù)據(jù)庫(kù)給數(shù)據(jù)庫(kù)帶來(lái)的壓力;
    authors=models.Author.objects.all()
    for author in  authors:
        print(author.name)
    print('-------------------------------------')
    models.Author.objects.filter(id=1).update(name='張某')
    for author in  authors:
        print(author.name)
    #但是有時(shí)候取出來(lái)的數(shù)據(jù)量太大會(huì)撐爆緩存,可以使用迭代器優(yōu)雅得解決這個(gè)問(wèn)題;
    models.Publish.objects.all().iterator()
    return HttpResponse('OK')
3. 增刪改查操作

  • orm添加一條記錄的方法
def orm(request):
    # 單表
    # 1、表.objects.create()
    models.Publish.objects.create(name='浙江出版社',addr="浙江.杭州")
    models.Classify.objects.create(category='武俠')
    models.Author.objects.create(name='金庸',sex='男',age=89,university='東吳大學(xué)')
    # 2、類實(shí)例化:obj=類(屬性=XX) obj.save()
    obj=models.Author(name='吳承恩',age=518,sex='男',university='龍溪學(xué)院')
    obj.save()
    
    # 1對(duì)多
    # 1、表.objects.create()
    models.Book.objects.create(title='笑傲江湖',price=200,date=1968,classify_id=6, publish_id=6)
    # 2、類實(shí)例化:obj=類(屬性=X,外鍵=obj)obj.save()
    classify_obj=models.Classify.objects.get(category='武俠')
    publish_obj=models.Publish.objects.get(name='河北出版社')
    # 注意以上獲取得是和 book對(duì)象 向關(guān)聯(lián)的(外鍵)的對(duì)象
    book_obj=models.Book(title='西游記',price=234,date=1556,classify=classify_obj,publish=publish_obj)
    book_obj.save()
    
    # 多對(duì)多
    # 如果兩表之間存在雙向1對(duì)N關(guān)系,就無(wú)法使用外鍵來(lái)描述其關(guān)系了;只能使用多對(duì)多的方式,新增第三張表關(guān)系描述表;
    book=models.Book.objects.get(title='笑傲江湖')
    author1=models.Author.objects.get(name='金庸')
    author2=models.Author.objects.get(name='張根')
    book.author.add(author1,author2)

    # 書籍和作者是多對(duì)多關(guān)系,
    # 切記:如果兩表之間存在多對(duì)多關(guān)系,例如書籍相關(guān)的所有作者對(duì)象集合,作者也關(guān)聯(lián)的所有書籍對(duì)象集合
    book=models.Book.objects.get(title='西游記')
    author=models.Author.objects.get(name='吳承恩')
    author2 = models.Author.objects.get(name='張根')
    book.author.add(author,author2)
    # add()    # 添加
    # clear()    # 清空
    # remove()     # 刪除某個(gè)對(duì)象
    return HttpResponse('OK')

根據(jù)條件判斷,增加?更新?

# 根據(jù)user=user去查找,如果找到更新 如果沒(méi)有找到創(chuàng)建defaults={} 中的數(shù)據(jù)
tk = gen_tcoken(username)
models.Token.objects.update_or_create(user=user, defaults={'token': tk})
# 刪除指定條件的數(shù)據(jù)
models.Tb1.objects.filter(name='seven').delete() 
def delete(request):
    # 修改方式1 update()
    ret = models.Book.objects.filter(id=1).update(price=3)

    # 修改方式2 obj.save()
    book_obj=models.Book.objects.get(id=1)
    book_obj.price=5
    book_obj.save()
def ormquery(request):
    # query_set對(duì)象集合 [對(duì)象1、對(duì)象2、.... ]
    books=models.Book.objects.all()
    books=models.Book.objects.filter(id__gt=2,price__lt=100) 
    # 單個(gè)對(duì)象,沒(méi)有找到會(huì)報(bào)錯(cuò)
    book=models.Book.objects.get(title__endswith='金')
    book1 = models.Book.objects.filter(title__endswith='金').first()
    book2 = models.Book.objects.filter(title__icontains='瓶').last()
    # query_set字典集合 [{一條記錄},{一條記錄} ]
    books=models.Book.objects.values(
                    'title','price',
                    'publish__name',
                    'date',
                    'classify__category',    # 正向連表: 外鍵字段___對(duì)應(yīng)表字段
                    'author__name',    # 反向連表: 小寫表名__對(duì)應(yīng)表字段
                    'author__sex',    # 區(qū)別: 正向 外鍵字段__,反向 小寫表名__
                    'author__age',
                    'author__university')
    books=models.Book.objects.values('title','publish__name').distinct()  
    # exclude 按條件排除。。。
    # distinct()去重, exits()查看數(shù)據(jù)是否存在? 返回 true 和false
    a=models.Book.objects.filter(title__icontains='金')
    return HttpResponse('OK')

連表查詢

# 反向連表查詢:
# 1、通過(guò)object的形式反向連表, obj.小寫表名_set.all()
publish=models.Publish.objects.filter(name__contains='湖南').first()
books=publish.book_set.all()
for book in  books:
    print(book.title)

# 通過(guò)object的形式反向綁定外鍵關(guān)系
authorobj = models.Author.objects.filter(id=1).first()
objects = models.Book.objects.all()
authorobj.book_set.add(*objects)
authorobj.save()
    
# 2、通過(guò)values雙下滑線的形式,objs.values("小寫表名__字段")
# 注意對(duì)象集合調(diào)用values(),正向查詢是外鍵字段__XX,而反向是小寫表名__YY看起來(lái)比較容易混淆;
books=models.Publish.objects.filter(name__contains='湖南').values('name','book__title')
authors=models.Book.objects.filter(title__icontains='我的').values('author__name')
print(authors)

# fifter()也支持__小寫表名語(yǔ)法進(jìn)行連表查詢:在publish標(biāo)查詢 出版過(guò)《笑傲江湖》的出版社
publishs=models.Publish.objects.filter(book__title='笑傲江湖').values('name')
print(publishs)

# 查詢誰(shuí)(哪位作者)出版過(guò)的書價(jià)格大于200元
authors=models.Author.objects.filter(book__price__gt=200).values('name')
print(authors)

# 通過(guò)外鍵字段正向連表查詢,出版自保定的書籍;
city=models.Book.objects.filter(publish__addr__icontains='保定').values('title')
print(city)

五、ORM連表操作

在django使用orm的時(shí)候,我們可以把一對(duì)多,多對(duì)多,分為正向和反向查找兩種方式。

  • 正向查找:
    ForeignKey在 UserInfo表中,如果從UserInfo表開(kāi)始向其他的表進(jìn)行查詢,這個(gè)就是正向操作,反之如果從UserType表去查詢其他的表這個(gè)就是反向操作。
    一對(duì)多:models.ForeignKey(其他表)
    多對(duì)多:models.ManyToManyField(其他表)
    一對(duì)一:models.OneToOneField(其他表)
  • 正向連表操作總結(jié):
    所謂正、反向連表操作的認(rèn)定無(wú)非是Foreign_Key字段在哪張表決定的,F(xiàn)oreign_Key字段在哪張表就可以哪張表使用Foreign_Key字段連表,反之沒(méi)有Foreign_Key字段就使用與其關(guān)聯(lián)的 小寫表名;

1對(duì)多:對(duì)象.外鍵.關(guān)聯(lián)表字段,values(外鍵字段__關(guān)聯(lián)表字段)
多對(duì)多:外鍵字段.all()

  • 反向連表操作總結(jié):
    通過(guò)value、value_list、fifter 方式反向跨表:小寫表名__關(guān)聯(lián)表字段
    通過(guò)對(duì)象的形式反向跨表:小寫表面_set().all()

ORM跨表查詢操作示例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文:https://my.oschina.net/liuyuantao/blog/751438 查詢集API 參...
    陽(yáng)光小鎮(zhèn)少爺閱讀 3,958評(píng)論 0 8
  • Django 準(zhǔn)備 “虛擬環(huán)境為什么需要虛擬環(huán)境:到目前位置,我們所有的第三方包安裝都是直接通過(guò) pip inst...
    33jubi閱讀 1,391評(píng)論 0 5
  • 模塊間聯(lián)系越多,其耦合性越強(qiáng),同時(shí)表明其獨(dú)立性越差( 降低耦合性,可以提高其獨(dú)立性)。軟件設(shè)計(jì)中通常用耦合度和內(nèi)聚...
    riverstation閱讀 2,219評(píng)論 0 8
  • Django 1.8.2 文檔Home | Table of contents | Index | Modules...
    軒轅小愛(ài)閱讀 2,425評(píng)論 0 2
  • ORM ??ORM框架的目的是不再使用SQL語(yǔ)句,讓用戶使用對(duì)象類和對(duì)象的方式和這個(gè)框架內(nèi)部的方法來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作...
    Pope_Li閱讀 1,154評(píng)論 0 1

友情鏈接更多精彩內(nèi)容