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
- 下載下傳好Django 的安裝包:
,Django-2.2.7.tar.gz
- 解壓安裝包:
tar -zxvf Django-2.2.7.tar.gz
- 進入安裝包:
cd Djang-2.2.7
- 安裝Django:
sudo python setup.py install
- 檢視Django版本:
django-admin.py -- version
建立Django項目
無建立虛拟環境的情況下
- 找到想安裝的檔案下:
django-admin startproject mydjango
- 進入Django項目下:
cd mydjango
- 建立app:
python manage.py startapp django
- 運作項目:
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
有建立虛拟環境的情況下
- 建立檔案夾 :
mkdir wgt
- 進入檔案夾:
cd wgt
- wgt 建立虛拟環境 venv:
python3 -m venv venv
- 啟動虛拟環境:
source wgt/venv/bin/activate
- 虛拟環境下安裝Django:
pip install django
- 退出虛拟機 :
deactivate
Django檔案含義
- settings.py : Django 如何與你的系統互動以及如何管理項目,修改一些設定,或者添加一些配置,中間鍵。
- urls.py: 告訴Django應該建立哪些頁面來響應浏覽請求
- wsgi.py : 幫助Django提供他建立的檔案(web server gateway interface)
- init.py : 配置資料庫導入包
Django連接配接資料庫并建立表的操作步驟
- settings檔案的DATABASES中配置資料庫
- makemgirations建立資料庫變更檔案
+ 檔案名python manage.py makemigrations
- migrate将變更檔案應用到資料庫中
+ 檔案名python manage.py migrate
- 建立app,并将app添加到settings中的INSTALLED_APPS中
- 在app的models檔案中建立資料模型
- makegirations建立資料庫變更檔案
-
migrate将變更檔案應用到資料庫注意:
隻要對資料模型做了更改或者添加了新的資料模型,
-
資料庫介紹:Django項目預設 sqlite3 資料庫, 生成的資料庫名為 db.sqlite3
sqlite3 僅供測試使用,可以通過配置修改為使用 mysql
- 手動建立建立資料庫 :
create database db_django charest=utf-8
- 初始化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 資料事務性
資料庫結構的特點
- 資料結構化 資料之間具有聯系,面向整個系統。
- 資料的共享性高,備援度低,易擴充
- 資料獨立性高
- 資料由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
性能損耗少
設計靈活,可以輕松實作複雜查詢
移植性好
- 模型查詢
- 模型成員objects
Django預設通過模型的objects對象實作資料查詢
- 過濾器
Django有兩種過濾器用于篩選記錄
filter : 傳回符合篩選條件的資料集 exclude : 傳回不符合篩選條件的資料集
-
all() 傳回所有資料
filter() 傳回符合條件的資料
filter(條件1,條件2,條件3)
filter(條件1).filter(條件2).filter(條件3)
exclude() 查詢不滿足條件的資料
-
order_by() 排序
升序:模型名.objects.all().order_by(‘id’)
降序:模型名.objects.all().order_by(’-id’)
-
運算符
icontains:大小寫不敏感
contains:大小寫敏感
模型名.objects.filter(s_name__icontains=‘小’)
startswith:以什麼開始
endswith:以什麼結束
-
範圍查詢
gt gte:大于、大于等于 —>greater than greater than equal
lt lte:小于、小于等于
in:在範圍之内
-
values 擷取
values方法可以擷取number字段的字典清單。
values_list可以擷取number的元組清單。
values_list方法加個參數flat=True可以擷取number的值清單。
-
查詢單個資料
get():傳回一個滿足條件的對象
擷取不到資料會報錯
get隻能傳回一個對象,如果找到多個會引發模型類MultiObjectsReturned異常
get_or_create():擷取不到對象就建立對象
get_or_update();擷取到對象就修改對象
-
查詢先後條件
first():傳回查詢集中的第一個對象
last():傳回查詢集中的最後一個對象
count():傳回目前查詢集中的對象個數
exists():判斷查詢集中是否有資料,如果有資料傳回True,沒有傳回False
-
查詢或者條件/不等于條件
并且:filter(條件1,條件2,條件3)
或者:filter(Q(條件1) |Q(條件2))
取反:filter(~Q(條件1) | Q(條件2))
-
A字段和B字段進行算數運算
F()
filter(shuxue__gt = F(‘yuwen’) + 10)
-
- 模型成員objects
例子:
大于等于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']))
總結:
- 第一種直接就把外鍵的name查詢出,無需重新查詢
- 第二種 需要查詢
<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}]>
- 排序 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架構
-
首先,django在運作程式時,最開始當你輸入正确的網絡位址的時候,
django會進入路由子產品(urls)中去尋找是否有符合其要求的路徑,
auth後面跟的就是路由路徑了。我們在頁面位址欄中輸入“localhost:8000/index/”,
django會自動的尋找路由表(urls)中符合要求的字尾為“index/”的路徑。
找到後,如果有index/,将會去執行這個路由後面所指向的函數。而這個函數就是view中的函數,執行函數相應的響應過程以後,
-
必定會return傳回并跳轉相應頁面及攜帶資料。
(django強制要求必須return傳回,強制傳回主要原因是每一次網頁操作,都會相應的跳轉頁面或互動)
看到return語句後面是不是跟着“index.html”,這就是讓程式自動自行index的頁面。
那麼來到templates檔案夾中打開這個頁面。恭喜你,打開index.html頁面。
-
經過上面的步驟,
可以看出,我們程式的執行流程是:路由,視圖排程(V層),前端頁面(HTML)。
是以我們在開發中,為了讓大腦清晰,友善執行,我們從最容易觀察到的前端頁面視圖層開始開發,這樣不斷能夠及時的看到很好的回報,
若看不到頁面,我們還能及時的找到問題出在什麼地方,能夠及時的做出調整。