天天看點

Django世界-邁出第一步-安裝和建立Django

Dajngo學習

  • Django
    • 安裝Django
    • 建立Django項目
      • 無建立虛拟環境的情況下
      • 有建立虛拟環境的情況下
    • Django檔案含義
    • Django連接配接資料庫并建立表的操作步驟
      • Dajngo 資料事務性
      • Dajngo 建立資料表
      • Dajngo 資料表外鍵
        • Dajngo 資料表儲存外鍵
      • Dajngo 資料表删除外鍵
      • Dajngo 資料時間字段
        • Django 時間校驗
        • Django 轉換時間
      • Dajngo ORM(Objects Relational Mapping)
    • 建立 Dajngo 超級管理者
    • 總結

Django

Django是一個開放源代碼的Web應用架構,由Python寫成。采用了MTV的架構模式,即模型M,視圖V和模版T。

安裝Django

  1. 下載下傳好Django 的安裝包:

    Django-2.2.7.tar.gz

  2. 解壓安裝包:

    tar -zxvf Django-2.2.7.tar.gz

  3. 進入安裝包:

    cd Djang-2.2.7

  4. 安裝Django:

    sudo python setup.py install

  5. 檢視Django版本:

    django-admin.py -- version

建立Django項目

無建立虛拟環境的情況下

  1. 找到想安裝的檔案下:

    django-admin startproject mydjango

  2. 進入Django項目下:

    cd mydjango

  3. 建立app:

    python manage.py startapp django

  4. 運作項目:

    python manage.py runserver 0.0.0.0:8000

安裝出現的問題:

Are you sure it installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?

解決辦法

python -m pip install Django

有建立虛拟環境的情況下

  1. 建立檔案夾 :

    mkdir wgt

  2. 進入檔案夾:

    cd wgt

  3. wgt 建立虛拟環境 venv:

    python3 -m venv venv

  4. 啟動虛拟環境:

    source wgt/venv/bin/activate

  5. 虛拟環境下安裝Django:

    pip install django

  6. 退出虛拟機 :

    deactivate

Django檔案含義

  1. settings.py : Django 如何與你的系統互動以及如何管理項目,修改一些設定,或者添加一些配置,中間鍵。
  2. urls.py: 告訴Django應該建立哪些頁面來響應浏覽請求
  3. wsgi.py : 幫助Django提供他建立的檔案(web server gateway interface)
  4. init.py : 配置資料庫導入包

Django連接配接資料庫并建立表的操作步驟

  1. settings檔案的DATABASES中配置資料庫
  2. makemgirations建立資料庫變更檔案

    python manage.py makemigrations

    + 檔案名
  3. migrate将變更檔案應用到資料庫中

    python manage.py migrate

    + 檔案名
  4. 建立app,并将app添加到settings中的INSTALLED_APPS中
  5. 在app的models檔案中建立資料模型
  6. makegirations建立資料庫變更檔案
  7. migrate将變更檔案應用到資料庫注意:

    隻要對資料模型做了更改或者添加了新的資料模型,

  8. 資料庫介紹:Django項目預設 sqlite3 資料庫, 生成的資料庫名為 db.sqlite3

    sqlite3 僅供測試使用,可以通過配置修改為使用 mysql

  9. 手動建立建立資料庫 :

    create database db_django charest=utf-8

  10. 初始化mysql 驅動 :

    import pymysql , pymysql.install_as_MySQLdb()

setting.py 配置資料庫:

DATABASES = {
	    # 配置使用mysql
	        DATABASES = {
	        'default': {
	            'ENGINE': 'django.db.backends.mysql',  # 資料庫産品
	            'NAME': 'db_Django', # 資料庫名
	            'HOST': 'localhost', # 主機位址,本機使用localhost,生産環境為實際主機ip
	            'PORT': '3306',  # 端口
	            'USER': 'root',  # 使用者名
	            'PASSWORD': 'root',  # 密碼
	        }
}
           

Dajngo 資料事務性

資料庫結構的特點

  1. 資料結構化 資料之間具有聯系,面向整個系統。
  2. 資料的共享性高,備援度低,易擴充
  3. 資料獨立性高
  4. 資料由DBMS統一管理和控制

資料庫的事務性

字段 含義
Atomic(原子性) 指整個資料庫事務是不可分割的工作機關。隻有使據庫中所有的操作執行成功,才算整個事務成功;事務中任何一個SQL語句執行失敗,那麼已經執行成功的SQL語句也必須撤銷,資料庫狀态應該退回到執行事務前的狀态。
Consistency(一緻性) 指資料庫事務不能破壞關系資料的完整性以及業務邏輯上的一緻性。例如對銀行轉帳事務,不管事務成功還是失敗,應該保證事務結束後ACCOUNTS表中Tom和Jack的存款總額為2000元。
Isolation(隔離性) 指的是在并發環境中,當不同的事務同時操縱相同的資料時,每個事務都有各自的完整資料空間。
Durability(持久性) 指的是隻要事務成功結束,它對資料庫所做的更新就必須永久儲存下來。即使發生系統崩潰,重新啟動資料庫系統後,資料庫還能恢複到事務成功結束時的狀态。

事務性

在儲存訂單資料中,涉及到多張表(OrderInfo、OrderGoods、SKU)的資料修改,對這些資料的修改應該是一個整體事務,即要麼一起成功,要麼一起失敗。

Django中對于資料庫的事務,預設每執行一句資料庫操作,便會自動送出。我們需要在儲存訂單中自己控制資料庫事務的

執行流程。

在Django中可以通過django.db.transaction子產品提供的atomic來定義一個事務,atomic提供兩種用法

from django.db import transaction

    @transaction.atomic
    def viewfunc(request):
    # 這些代碼會在一個事務中執行
        …
           
with語句用法是:

from django.db import transaction
from rest_framework.views import APIView
class OrderAPIView(APIView):
    def post(self,request):
        ....
        with transation.atomic():
            # 設定事務復原的标記點
            sid = transation.savepoint()

            ....
            # 出現異常時 復原事物
            try:
                ....
            except:
                transation.savepoint_rallback(sid)


            transaction.savepoint_commit(save_id)
           
在Django中,還提供了儲存點的支援,可以在事務中建立儲存點來記錄資料的特定狀态,資料庫出現錯誤時,可以恢複到資料儲存點的狀态
from django.db import transaction
//建立儲存點
save_id = transaction.savepoint()

//復原到儲存點
transaction.savepoint_rollback(save_id)

//送出從儲存點到目前狀态的所有資料庫事務操作
transaction.savepoint_commit(save_id)
           

Dajngo 建立資料表

class user(models.MOdel):
      name = models.CharField(max_length=128, unique=True) //必填,最長不超過128個字元,并且唯一,也就是不能有相同姓名;
      password = models.CharField(max_length=256)//必填,最長不超過256個字元(實際可能不需要這麼長);
      email = models.EmailField(unique=True) //使用Django内置的郵箱類型,并且唯一;
      sex = models.CharField(max_length=32, choices=gender, default="男") // 性别,使用了一個choice,隻能選擇男或者女,預設為男;
      c_time = models.DateTimeField(auto_now_add=True)

      def __str__(self):
          return self.name // 使用__str__方法幫助人性化顯示對象資訊;

      class Meta: //資料裡定義使用者按建立時間的反序排列,也就是最近的最先顯示;
          db_table = 'user' // 命名資料庫名字是: user
          ordering = ["-c_time"]  // 以 建立時間從大到小排序
          verbose_name = "使用者"
          verbose_name_plural = "使用者"
           

Dajngo 資料表外鍵

關于ForeignKey.on_delete的幾個選項;

當一個model對象的ForeignKey關聯的對象被删除時,預設情況下此對象也會一起被級聯删除的。

字段 含義
CASCADE 預設值,model對象會和ForeignKey關聯對象一起被删除
SET_NULL 将model對象的ForeignKey字段設為null。當然需要将null設為True
SET_DEFAULT 将model對象的ForeignKey字段設為預設值。
Protect 删除ForeignKey關聯對象時會生成一個ProtectedError,這樣ForeignKey關聯對象就不會被删除了
字段 含義
models.CASCADE 預設為models.CASCADE 級聯删除。當删除’一’時,‘多’會被删除。
modles.PROTECT 當删除一個具有外鍵關系的對象時,會引發一個異常,阻止删除該對象
models.SET_NULL 設定删除對象所關聯的外鍵字段為null。但字段的null屬性必需為True
models.SET_DEFAULT 設定删除對象所關聯的外鍵字段為預設的值。
models.SET(value) 設定删除對象所關聯的對象的外鍵字段為value,value也可以是一個可調用函數

Dajngo 資料表儲存外鍵

何時使用save(commit=False)方法

Stackoverflow上其實已經有了一段非常精煉的答案。英文原文如下,我把它翻譯了一下:

That is useful when you get most of your model data from a form, but need to populate some null=False fields with non-form data.

Saving with commit=False gets you a model object, then you can add your extra data and save it.

當你通過表單擷取你的模型資料,但是需要給模型裡null=False字段添加一些非表單的資料,該方法會非常有用。如果你指定commit=False,

那麼save方法不會了解将表單資料存儲到資料庫,而是給你傳回一個目前對象。這時你可以添加表單以外的額外資料,再一起存儲。

何時使用save_m2m方法及如何使用

save_m2m方法隻用來存儲多對多的關系。當你同時滿足下面兩個條件時,你需要使用此方法。如果你直接使用save()或form_valid()方法,是可以直接存儲多對多(m2m)關系的,不需要用save_m2m。

你使用了save(commit=False)方法

你的model裡有多對多的關系(比如tags)

if user_create_form.is_valid():
            new_user = user_create_form.save(commit=False)
            new_user.password = make_password(user_create_form.cleaned_data['password'])
            if 'file' in request.FILES:
                file_name = 'media/image/' + request.POST.get('name') + '_' + str(int(time.time())) + '.' + \
                            file_obj.name.split('.')[
                                -1]  # 構造檔案名以及檔案路徑
                print(file_name)
                with open(file_name, 'wb+') as f:
                    print(file_obj.read())
                    f.write(file_obj.read())
                new_user.image = file_name[6:]
            new_user.save()
            user_create_form.save_m2m()

            ret = {'status': 'success'}
           

Dajngo 資料表删除外鍵

記錄一下踩的坑,同一個資料庫下兩個表,舉個例子 user_info 表中的 username字段設定為外鍵,關聯了 表user_pwd中的主鍵字段 

user,現在因為重建表結構等原因,要把這個外鍵删除,這裡的删除文法為:

alter table 表名 drop foreign key 外鍵别名;
           

需要注意的是,外鍵别名并不是設定為外鍵的字段名,

假如我們直接 alter table user_info drop foreign key username;這時候會報文法錯誤!

我們要在指令行輸入 

show create table user_info

;這時候會顯示建表的資訊,有這麼一句話
這時候我們要這麼修改

alter table user_info drop foreign key user_info;

這個時候就删除了表中字段的外鍵限制,這時候我們再 

alter table user_info drop username

,就可以删除這個原本是外鍵的字段了!

Dajngo 資料時間字段

字段 含義
DateTimeField 日期+時間,與python裡的 datetime.datetime 執行個體同,資料庫字段内容為 2018-08-30 16:31:00
DateField 日期,與python裡的 datetime.date 執行個體同。資料庫字段内容為 2018-08-30,datetime.date 傳到前台的值會轉換成 2019年12月5日

有以下兩個可選的選項,均為bool類型:

參數1:auto_now,預設值為false,設定為true時,每次執行 save 操作時,将其值設定為目前時間,并且每次修改model,都會自動更新。

使用場景:這個參數在需要存儲“最後修改時間”的場景下,十分友善。

注意:設定該參數為true時,并不意味着字段的預設值設為目前時間,而是指字段會被“強制”更新到目前時間,你無法程式中手動為字段指派;如果使用django自帶的admin管理器,那麼該字段在admin中是隻讀的。

參數2:auto_now_add,預設值為false,設定為true時,會在model對象第一次被建立時,将字段的值設定為建立時的時間,以後修改對象時,字段的值不會再更新。

使用場景:該屬性通常被用在存儲“建立時間”的場景下。

注意:一旦被設定為True,就無法在程式中手動為字段指派,在admin中字段也會成為隻讀的。

auto_now和auto_now_add被設定為True後,這樣做會導緻字段成為editable=False和blank=True的狀态。editable=False将導緻字段不會被呈現在admin中,blank=Ture表示允許在表單中不輸入值。

Django 時間校驗

//轉換成規範的時間
print(datetime.datetime.strptime(date_text, '%Y-%m-%d 00:00:00'))
           
//判斷是否是時間格式
def validate(date_text):
    try:
        datetime.datetime.strptime(date_text, '%Y-%m-%d 00:00:00')
        flag = True
    except ValueError:
        flag = False
    return flag
           

Django 轉換時間

//下載下傳資料時,将不規範的時間轉換
# cls=DateEnconding 轉換成 2019/12/9
  result = json.dumps(data, cls=DateEnconding)

  class DateEnconding(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime.date):
            return o.strftime('%Y/%m/%d')

           

安裝出現的問題:

init() missing 1 required positional argument: ‘on_delete’

解決辦法

category = models.ForeignKey(Category, verbose_name=‘分類’, on_delete=models.CASCADE)

在末尾加上 on_delete=models.CASCADE

安裝Pymysql的問題:

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None

解決辦法

找到Python安裝路勁下的Python36-32\Lib\site-packages\django\db\backends\mysql\base.py檔案将檔案中的如下代碼注釋

if version < (1, 3, 3):

raise ImproperlyConfigured(“mysqlclient 1.3.3 or newer is required; you have %s” % Database.version)

重新在項目manage.py路勁下執行如下指令即可

安裝資料庫出現的問題:

No changes detected

解決辦法

第一步:

删除該app下的migrations下的所有檔案。

第二步:

進入資料庫,将對應的該app所有相關表删除

第三步:執行一下三條指令

blog>python manage.py makemigrations --empty myblog

blog>python manage.py makemigrations

blog>python manage.py migrate

或者

python manage.py migrate --fake

Dajngo ORM(Objects Relational Mapping)

** 對象關系映射,是一種程式技術,用于實作對象程式設計語言裡不同類型系統的資料之間的轉換,ORM模型的簡單性簡化了資料庫查詢過程。使用ORM查詢工具,使用者可以通路期望資料,而不必了解資料庫的底層結構。**

ORM将對對象的操作轉換為原生SQL

優點

易用性,可以有效減少重複SQL

性能損耗少

設計靈活,可以輕松實作複雜查詢

移植性好

  1. 模型查詢
    1. 模型成員objects
      Django預設通過模型的objects對象實作資料查詢
                 
    2. 過濾器
      Django有兩種過濾器用于篩選記錄
                 
      filter    : 傳回符合篩選條件的資料集
      exclude   : 傳回不符合篩選條件的資料集
                 
      1. all() 傳回所有資料

        filter() 傳回符合條件的資料

        filter(條件1,條件2,條件3)

        filter(條件1).filter(條件2).filter(條件3)

        exclude() 查詢不滿足條件的資料

      1. order_by() 排序

        升序:模型名.objects.all().order_by(‘id’)

        降序:模型名.objects.all().order_by(’-id’)

      1. 運算符

        icontains:大小寫不敏感

        contains:大小寫敏感

        模型名.objects.filter(s_name__icontains=‘小’)

        startswith:以什麼開始

        endswith:以什麼結束

      1. 範圍查詢

        gt gte:大于、大于等于 —>greater than greater than equal

        lt lte:小于、小于等于

        in:在範圍之内

      1. values 擷取

        values方法可以擷取number字段的字典清單。

        values_list可以擷取number的元組清單。

        values_list方法加個參數flat=True可以擷取number的值清單。

      1. 查詢單個資料

        get():傳回一個滿足條件的對象

        擷取不到資料會報錯

        get隻能傳回一個對象,如果找到多個會引發模型類MultiObjectsReturned異常

        get_or_create():擷取不到對象就建立對象

        get_or_update();擷取到對象就修改對象

      1. 查詢先後條件

        first():傳回查詢集中的第一個對象

        last():傳回查詢集中的最後一個對象

        count():傳回目前查詢集中的對象個數

        exists():判斷查詢集中是否有資料,如果有資料傳回True,沒有傳回False

      1. 查詢或者條件/不等于條件

        并且:filter(條件1,條件2,條件3)

        或者:filter(Q(條件1) |Q(條件2))

        取反:filter(~Q(條件1) | Q(條件2))

      1. A字段和B字段進行算數運算

        F()

        filter(shuxue__gt = F(‘yuwen’) + 10)

例子:

大于等于2 的書籍 且不等于3 的書籍

[<Book: 西遊記>, <Book: 水浒傳>]
           
book = list(Book.objects.filter(id__gte=2).filter(~Q(id=3))) 
    book = list(Book.objects.filter(id__gte=2).exclude(id=3).values())
           

外鍵查詢

三國演義/黑龍江科技大學
西遊記/西安工業大學
紅樓夢/黑龍江科技
水浒傳/黑龍江
           

根據外鍵 查詢外鍵表,重新命名為‘publish_name’

books = Book.objects.annotate(publish_name=F('publish__name'))
for book in books:
      print('%s/%s' % (book.title, book.publish_name))
           
books = Book.objects.all()
 # <QuerySet [{'publish__name': '黑龍江科技大學', 'title': '三國演義'}]>
for book in books:
      print('%s/%s' % (book.title, book.publish.name))
           
books = Book.objects.filter().values('publish__name', 'title')
#<QuerySet [<Book: 三國演義>, <Book: 西遊記>, <Book: 紅樓夢>, <Book: 水浒傳>]>
for book in books:
      print('%s/%s' % (book['title'], book['publish__name']))
           

總結:

  1. 第一種直接就把外鍵的name查詢出,無需重新查詢
  2. 第二種 需要查詢
<QuerySet [{'id': 1, 'title': '三國演義', 'price': 100, 'pub_date': datetime.date(2019, 1, 8), 'publish_id': 1, 'publish_name': '黑龍江科技大學'}]>
<QuerySet [{'id': 1, 'title': '三國演義', 'price': 100, 'pub_date': datetime.date(2019, 1, 8), 'publish_id': 1}]>
           
  1. 排序 order_by
books = Book.objects.order_by('create_time')
class Meta:
  orderinf = ['create_time','price']
           

建立 Dajngo 超級管理者

首選建立一個新使用者,用來登入Django管理網站,進入manage.py目錄下,使用如下指令來進行建立:

python manage.py createsuperuser

接下來輸入使用者名稱:

Username(leave bkank to use ‘administrator’): root

然後是輸入郵箱(QQemail等都可以):

Email address:(輸入你的郵箱賬号)

輸入密碼(輸入密碼時不會顯示出來,并且長度必須超過八位才行):

Password:********

Password(again):********

當兩次密碼輸入相同且超過八位的時候,就會提示建立超級使用者成功:

Superuser created successfully.

再次運作你的服務,輸入賬号和密碼就可以成功登陸了:

python manage.py runserver

總結

關于django架構

  1. 首先,django在運作程式時,最開始當你輸入正确的網絡位址的時候,

    django會進入路由子產品(urls)中去尋找是否有符合其要求的路徑,

    auth後面跟的就是路由路徑了。我們在頁面位址欄中輸入“localhost:8000/index/”,

    django會自動的尋找路由表(urls)中符合要求的字尾為“index/”的路徑。

    找到後,如果有index/,将會去執行這個路由後面所指向的函數。而這個函數就是view中的函數,執行函數相應的響應過程以後,

  2. 必定會return傳回并跳轉相應頁面及攜帶資料。

    (django強制要求必須return傳回,強制傳回主要原因是每一次網頁操作,都會相應的跳轉頁面或互動)

    看到return語句後面是不是跟着“index.html”,這就是讓程式自動自行index的頁面。

    那麼來到templates檔案夾中打開這個頁面。恭喜你,打開index.html頁面。

  3. 經過上面的步驟,

    可以看出,我們程式的執行流程是:路由,視圖排程(V層),前端頁面(HTML)。

    是以我們在開發中,為了讓大腦清晰,友善執行,我們從最容易觀察到的前端頁面視圖層開始開發,這樣不斷能夠及時的看到很好的回報,

    若看不到頁面,我們還能及時的找到問題出在什麼地方,能夠及時的做出調整。