Django之操做數據庫

1:數據庫:python

2:MySQL驅動程序的安裝mysql

3:Django配置鏈接數據庫sql

4:在Django中操做數據庫數據庫

  (1)原生SQL語句操做django

  (2)ORM模型操做緩存

5:ORM模型的介紹安全

6:建立一個ORM模型並映射模型到數據庫中數據結構

7:模型經常使用的屬性app

  (1)經常使用的Field字段框架

  (2)Field字段經常使用的參數

  (3)模型中Meta的配置

8:外鍵

9:表關係

  (1)一對一

  (2)一對多(多對一)

  (3)多對多

10:模型的操做

  (1)數據的增刪改查

  (2)聚合函數

  (3)aggregate和annotate的區別

  (4)F表達式和Q表達式

11:查詢集(QuerySet

12:ORM模型遷移

-------------------------------------------------------------------------------------------------------------------------------

1數據庫:簡而言之就是存放數據的一個庫,用戶能夠對數據進行增刪改查;是網站重要的一個組成部分,只有提供了數據庫,網站才能動態的展現。經常使用的數據庫有MySQL,Oracle等。

2MySQL驅動程序的安裝:咱們使用Django來操做mysql,實際上底層使用的仍是python;所以若是咱們想要操做數據庫首先要安裝一個驅動;python3中有多個驅動可供選擇以下;

  (1)MySql-python :也就是MySQLdb 。是對C語言操做mysql的一個簡單封裝;只支持python2,不支持python3,運行速度最快。

  (2)mysqlclient:是MySql-python的另外一個分支,支持python3。

  (3)pymsql:純python實現的一個驅動,效率不高,能夠和python無縫鏈接。

  (4)mysql-connector-python:mysql官方推出的,純python開發的,效率不高

本文使用的是mysqlclient:   安裝方式: pip install mysqlclient

3:Django配置鏈接數據庫:在操做數據庫以前須要Django先鏈接上數據庫,不須要單首創建一個鏈接對象,只須要在setting中作好相關的配置便可。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',   #數據庫引擎(mysql仍是Oracle)
        'NAME': "my01",  #數據庫的名字
        "USER":"root",    #數據庫的用戶名
        "PASSWORD":"qwe123",    #數據庫密碼
        "HOST":"localhost",   #數據庫的主機地址
        "PORT":"3306"      #數據庫的端口號
    }
}

4:在Django中操做數據庫:Django操做數據庫有兩種方式。第一種是原生的SQL語句操做,另外一種是ORM模型操做

  (1)原生SQL語句操做

    缺點:(1)重複利用率不高(2)不易修改(3)安全問題(SQL注入)

  (2)ORM模型操做

5:ORM模型的介紹

  (1)ORM,全稱Object Relational Mapping,中文叫作對象-關係映射。

  (2)經過ORM咱們能夠經過類的方式來操做數據庫,經過把類映射成表,把實例映射爲行,把屬性映射爲字段;ORM在執行對象操做的時候最終仍是會把對應的操做轉換爲SQL語句。

6:建立一個ORM模型並映射模型到數據庫中

  第一步:建立一個User模型類(在數據庫中的表現:類--表名(app的名字_類名(小寫)),屬性--字段,實例-行)

class User(models.Model):
    username = models.CharField(max_length=10)
    telephone = models.CharField(max_length=11)
    email = models.EmailField()
    sex = models.BooleanField()

  第二步:執行makemigrations [app_name]       #後面能夠跟APP的名字,生成遷移腳本文件

  第三步:執行migrate [app_name]     #映射到數據庫中

7:模型經常使用的屬性

  (1)經常使用的Field字段

    AutoField:int類型,自動增加

    BigAutoField:相似於AutoField,範圍1-9223372036854775807

    BooleanField:tinyint類型,True/False 

    CharField:  varchar類型,使用時必須指定最大長度,即max_length參數必須傳遞

    DateField: 日期類型;兩個參數auto_now:每次保存的時候都是用當前的時間,好比記錄一個記錄修改的日期;auto_now_add:在數據第一次建立的時候用當前的時間,好比記錄第一次入庫的時間。

    DateTimeField:日期時間類型;不只能夠存儲日期還能夠存儲時間。兩個參數(auto_now和auto_now_add)

    TimeField:時間類型;

    EmailField:varchar類型;最大長度254

    FileField:用來存儲文件的

    FloatField:浮點類型

    ImageField:存儲圖片

    IntegerField:整型,-2147483648 - 2147483647

    BigIntegerField:大整形,

    PositiveIntegerField:正整型;0-2147483647

    SmallIntegerField:小整型,-32768 - 32767

    TextField:大量的文本類型,longtext

    UUIDField:存儲uuid格式的字符串,是一個32位的全球惟一的字符串,通常作主鍵

    URLField:存儲url格式的字符串,max_length默認是200

  (2)Field字段經常使用的參數

    null:表示映射爲表的時候是否能夠爲空,默認爲False(不能爲空);在使用字符串相關的Field時(CharField、TextField)通常保持默認的False,由於即使是Flase,Django也會建立一個空字符串 " "做爲默認值傳遞進去,若是再設置爲True的話,就會用null來存儲空值,默認值就變爲了兩個(""和null)

    blank:表示驗證的時候是否能夠爲空,默認是False。(和null的區別:null是一個數據庫級別的,blank是表單驗證級別的)

    db_column:表示字段在數據庫中的名字

    default:默認值,能夠是一個值或者函數,不支持lambda表達式,而且不支持列表、字典。集合等可變的數據結構

    primary_key:默認值false,是否爲主鍵

    unique:是否惟一,通常手機號或者郵箱用

  (3)模型中Meta的配置

    對於一些模型級別的配置,咱們能夠在模型中定義一個類,叫作Meta,而後在這個類中添加一些類屬性來控制模型。好比在映射到數據庫中表的名字使用本身定義的。

from django.db import models

class User(models.Model):
    username = models.CharField(max_length=10)
    telephone = models.CharField(max_length=11)
    email = models.EmailField()
    sex = models.BooleanField(db_column="sex_a")
    create_time = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        db_table = "User",      //表的名字
        ordering = ["create_time"]   //在查找數據的時候根據添加的時間排序

 8:外鍵

   若是一張表中非主鍵的某個字段指向了另外一張表中的主鍵,那麼這個字段就是該表的外鍵。

  外鍵的做用是:防止一張表過於複雜(好比一個需求是一個名字對應一張照片,若是保存在同一種表中數據可能有些亂,最好是分開兩張表,一種保存名字,另外一張保存圖片,同時兩張表又有一種制約,能夠經過名字找到這張圖片,或者經過圖片找到這個名字)。

  在mysql中,表有兩種引擎,一種是InnoDB,支持外鍵的使用;另外一種是myisam,暫時不支持外鍵的使用。

  Django中的外鍵使用ForeignKey(to,on_delete,**options),第一個參數是引用的是哪一個模型,第二個參數是使用外鍵引用的模型被刪除的時候,這個字段該如何處理。

  注意:若是引用的模型在另外一個APP中,則第一個參數須要添加app_name.模型名;若是引用的是模型自己本身能夠用self或者模型本身的名字

from django.db import models
 
class User(models.Model):         //用戶模型
    username = models.CharField(max_length=10)
    password = models.CharField(max_length=20)


class Article(models.Model):   //文章模型
    title = models.CharField(max_length=20)
    content = models.TextField()
    author = models.ForeignKey("User",on_delete=models.CASCADE)         //外鍵
    category = models.ForeignKey("login.Tags",on_delete=models.CASCADE)  //另外一個app,login中model的Tags模型


class Comment(models.Model):
    content = models.TextField()
    origin_comment = models.ForeignKey("self",on_delete=models.CASCADE,null=True)   //外鍵是模型本身
    # origin_comment = models.ForeignKey("Comment",on_delete=models.CASCADE,null=True)

  外鍵刪除操做:

  若是一個模型引用了外鍵,在對方那個模型被刪除掉,該進行什麼樣的操做;經過on_delete來指定:

    CASCADE:級聯操做,若是外鍵對應的那條數據被刪除,那麼這條數據也被刪除。

    PROTECT:受保護,即只要這條數據引用了外鍵的那條數據,那麼就不能刪除外鍵的那條數據。

    SET_NULL:設置爲空,若是外鍵的那條數據被刪除,那麼本條數據設置爲空,前提是這個字段能夠爲空。

    SET_DEFAULT:設置爲默認值,若是外鍵的那條數據被刪除,那麼本條數據設置默認值,前提是要指定一個默認值。

    SET():若是外鍵那條數據被刪除,則調用set函數的值,做爲外鍵的值

    DO_NOTHING:不採起任何行爲,看數據庫級別的約束。

 

9:表關係:表之間的關係都是經過外鍵進行關聯的,三種關係,一對一,一對多(多對一),多對多

  (1)一對一

    應用場景:一個用戶和一個用戶信息表

    實現方式:經過OneToOneField來實現 

  (2)一對多(多對一)

    應用場景:好比做者和文章之間的關係,一個做者能夠有多篇文章,可是一篇文章只能有一個做者

    實現方式:一對多或者多對一,都是經過ForeignKey來實現的    

  (3)多對多

    應用場景:好比文章和標籤之間的關係;一篇文章能夠有多個標籤,一個標籤能夠被多篇文章引用

    實現方式:經過ManyToManyField來實現

  表之間的查詢方式:related_name和related_query_name;咱們依然使用上面的User模型和Article模型來舉例:

  (1)若是咱們想要經過文章獲取該做者:

 article = Article.objects.first()   //獲取這篇文章
 print(article.author.username)    //直接經過author獲取做者

  (2)若是想要經過做者獲取其下的全部文章方式有兩種:

#方式一:Django默認每一個主表都有一個默認的屬性來獲取子表的信息,這個屬性就是子表模型的小寫加上_set(),默認返回一個querydict對象,能夠進一步操做 
author = User.objects.first()
 print(author.article_set.all())

#方式二:在默認中添加related_name,之後主表直接經過這個值來獲取子表的信息,獲得的也是一個querydict對象。
author = models.ForeignKey("User",on_delete=models.CASCADE,related_name="article")

#咱們能夠直接使用這個值
print(author.article.first().title)

  (3)relate_name=「+」,表示禁止使用反向查詢

10:模型的操做:在ORM框架中,全部的模型操做其實都是映射到數據庫中一條數據的操做,所以模型操做也就是數據庫表中數據的操做。

  (1)數據的增刪改查

      一:以上面表User爲例:

        (1)增長數據:

User.objects.create(username="王三",password="123")

       (2)查數據:(all(),get(),filter())

  #查找全部的數據:返回的是一個queryset集合,沒有知足條件返回空列表
    users = User.objects.all()
    for user in users:
        print(user.username)
    print(users)

    #查找單個的對象,返回一個對象,沒有知足條件時報錯
    user = User.objects.get(username="張帆")
    print(user.username)

    #數據過濾查找filter;查詢的時候有時須要對數據進行過濾再查詢,返回全部知足條件的QuerySet集合
    user = User.objects.filter(username="張帆",password="213123")
    print(user)

    #數據排序;查找數據的時候都是無序的,若是想對某個數據進行排序使用order_by,反向排序加個減號
    users = User.objects.order_by("username")

       (3)改數據:

 #修改數據:獲取這條數據,對屬性修改,而後保存
    user = User.objects.get(username="張帆")
    user.username = "李四"
    user.save()

       (4)刪除數據

 #刪除數據;獲取數據,而後執行delete()函數
    user = User.objects.get(username="李四")
    user.delete()

      二:查詢條件:查找的時候通常使用filter,get,exclude三個方法來實現,咱們能夠對其傳遞不一樣的參數,來實現不一樣的需求。格式(約束條件_查找條件)

        第一組:精確和like

          exact:使用精確 = 進行查找 ; User.objects.get(id_exact = 2),若是提供一個None值,sql層面被解釋爲null

          iexact:  使用like進行查找

        第二組:包含(title_contains = "hello")

          contains:大小寫敏感

          icontains:大小寫不敏感

          第三組:提供包含在容器中值,容器能夠是列表,元組,任意一個可迭代的對象

          in:User.objects.get(id_in=[1,2,3])

          也能夠傳遞一個queryset對象進去:獲取標題中包含張三的文章

          username = User.objects.filter(username_contains = "張三")

          user = Article.objects.filter(title_in = username)

        第四組:(id__gt = 3)

          gt:大於

          gte:大於等於

          lt:小於

          lte:小於等於

        第五組:判斷某個字段是否以某個值爲開始(結束) (title_startwith = "hello")

          startwith:

          istartwith:

          endswith:

          iendswith:

        第六組:

          range:判斷是否在某個區間;(create_time = range(start,end))

        第七組:根據時間查詢

          date:年月日  (create_time_date=date(2018,3,23))

          year:年(create_time_year = 2108)

          month:月(同上)

          day:天(同上)

          wek_day:星期幾(1表示星期天,7表示星期六)

          time:時分秒(create_time= datetime_time(2,2,2)),2點2分2秒

        第八組:是否爲空

          isnull:(title_isnull = False) 不爲空

        第九組:正則

          regex:大小寫敏感:(title_regex=r"hello")

          iregex:大小寫不敏感:(title_regex=r"hello")

     三:關聯表查詢 

        好比有兩個模型,一個是User,一個是Article;想要獲取文章標題中帶有「中國」的用戶

        user = User.objects.filter(article_title_contains = "hello")    

  (2)聚合函數:聚合函數是同aggregate方法來實現的。

      (1)Avg:求平均值

      (2)Count:獲取指定對象的個數

      (3)Max和Min:獲取最大值最小值

      (4)Sum:求和

假設有這樣一個模型:

class BookOrder(models.Model):
    book_name = models.CharField(max_length=12)
    price = models.FloatField()

數據表爲:

  # result = BookOrder.objects.aggregate(Avg("price"))    //全部書的平均價格,名字規則爲field_avg組成
    result = BookOrder.objects.aggregate(book_price = Avg("price"))    //給這個價格指定一個名字
    print(result)
 
    result = BookOrder.objects.aggregate(book_num = Count("id"))   //求全部的書
    print(result)

    result = BookOrder.objects.aggregate(book_price_max = Max("price"))  //求最大值
    print(result)

    result = BookOrder.objects.aggregate(book_price_min=Min("price"))  //求最小值
    print(result)

    result = BookOrder.objects.aggregate(books_price = Sum("price"))  //求最和
    print(result)

  (3)aggregate和annotate的區別

 

  (4)F表達式和Q表達式

   F表達式是用來優化ORM模型操做數據庫的,並不會馬上去數據庫中獲取數據,而是在生成SQL語句的時候,動態的獲取傳給F表達式的值

BookOrder.objects.update(price = F("price")+100)            //更新圖書的價格

  Q表達式:通常查詢條件比較多的時候使用,可使用與或非,&,|,~

books = BookOrder.objects.filter(Q(id=3) | Q(book_name__contains=""))

11:查詢集(QuerySet

 

  (1)查詢集就是經過查詢後獲得的一個對象集合。

  Django中查詢操做都是經過 模型名.objects的方式進行;這個objects是一個Manager對象,而這個Manager這個類是一個空殼的類,它自己沒有任何的屬性和方法;都是經過Python從QuerySet類中動態的添加過來的。

class Manager(BaseManager.from_queryset(QuerySet)):
    pass


class BaseManager:
    @classmethod
    def from_queryset(cls, queryset_class, class_name=None):
        if class_name is None:
            class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
        return type(class_name, (cls,), {
            '_queryset_class': queryset_class,
            **cls._get_queryset_methods(queryset_class),
        })

   
class QuerySet:
"""Represent a lazy database lookup for a set of objects."""

def __init__(self, model=None, query=None, using=None, hints=None):
self.model = model
self._db = using
self._hints = hints or {}
self.query = query or sql.Query(self.model)
self._result_cache = None
self._sticky_filter = False
self._for_write = False
self._prefetch_related_lookups = ()
self._prefetch_done = False
self._known_related_objects = {} # {rel_field: {pk: rel_obj}}
self._iterable_class = ModelIterable
self._fields = None


    ............(後面省略)
 

  (2)兩大特性:

    惰性執行:建立查詢集不會馬上執行,只到調用數據時纔會去數據庫中查詢,調用數據包括:迭代,使用步長作切片操做,調用len函數,調用list函數,判斷

    緩存:使用同一個查詢集,第一次會發生數據庫查詢,而後django會把數據緩存起來,之後再使用的時候不會去數據庫查詢而是直接使用

  (3)經常使用的API:

    1.filter:將知足條件的數據提取出來,返回一個queryset對象

    2.exclude:排除知足條件的對象,返回一個queryset對象

    3.annotate:

    4.order_by:排序(倒序加減號),多個order_by鏈式使用時,會把前面的打亂,之後面的爲準

    5.values:規定提取那些字段,返回的是一個字典類型。默認會把全部字段都提取出來

    6.values_list:同上,不過返回的是一個元組

    7.defer:過濾掉一些字段,返回的是一個模型

    8.only:只保留這個字段(和上面相反)

    9.all:返回queryset對象

    10.select_related:

    11.prefetch_related:

    12.get:只返回一條知足條件的數據,若是是多條或者沒有都會報錯

    13.create:建立一條數據,並保存

    14.get_or_create:若是數據庫中存在這個數據就返回,不存在就建立;返回一個元組(第一個參數是這個對象,第二個參數是boolean類型)

    15.bulk_create:一次建立多個數據;bulk_create([book_name="111",book_name="222"])

    16.count:獲取數據的個數,比len函數高效

    17.first和last:返回queryset中的第一條和最後一條

    18.aggregate:使用聚合函數

    19.exists:判斷是否存在

    20.distinct:去掉重複的數據;

    21.update:更新

    22.delete:刪除數據

    23.切片:Books.objects.all()[1:3];切片不是把數據都提取出來再作切片,而是在底層直接使用LIMIE和OFFSET

 12:ORM模型遷移

  (1)makemigrations:將模型生成遷移腳本

      app_label:後面跟一個或者多個app,只會針對這幾個app生成遷移腳本,若是沒有寫就是針對全部都生成

      --name:給這個遷移腳本生成一個名字

      --empty:生成一個空的遷移腳本

  (2)migrate:將生成的遷移腳本映射到數據庫中

      app_label:規定那幾個app

      app_label migrationname;將某個app下指定名字的migration文件映射到數據庫中

      --fake:能夠將指定的遷移腳本文件名字添加到數據庫中,可是並不會把遷移腳本文件轉換爲sql語句,修改數據庫中的表

      --fake-initial:將第一次生成的遷移文件版本號記錄在數據庫中,但並不會執行遷移腳本

  (3)showmigrations:查看某個app的遷移文件;若是後面沒有app將查看全部的

  (4)sqlmigrate:查看某個遷移文件映射到數據庫中轉換的SQL語句

相關文章
相關標籤/搜索