平台:Pycharm Django
使用 Pycharm 進行開發,需要提前在 Pycharm 中(File > Settings > Project: Python > Project Interpreter)下載 Django ,安裝過程會自動把 Django 路徑加載到系統的環境變量中。
進入 cmd 查詢 Django 是否安裝成功。出現以下一系列命令,說明已安裝成功。
創建第一個項目 guest ,可在 Pycharm 的 Terminal 中使用命令行創建
G:\Python>django-admin startproject guest
創建完成,Django 自動生成以下目錄結構
guest/ manage.py guest/ __init__.py settings.py urls.py wsgi.py
guest/manage.py : Django 項目的命令行工具,三種命令模式可選:
$ django-admin <command> [options] $ manage.py <command> [options] $ python -m django <command> [options]
guest/guest/__init__.py : 空文件夾,表示 guest 目錄是 python 的標准包
guest/guest/settings.py : 項目的配置文件,包含Django 模塊應用配置、數據庫配置、模板配置等
guest/guest/urls.py : 關於項目的 URL 聲明,定義 URLconf
guest/guest/wsgi.py : 提供服務的入口,暫未知 wsgi 有何用
guest/manage.py : 一個命令行工具,通過 命令 python manage.py 可以查看 manage 所提供的命令
創建第一個應用
G:\Python\guest>python mangage.py startapp sign
在 Terminal 中使用以上命令創建 sign 應用后,會自動生成一些文件(templates 目錄不是自動生成),如下面目錄結構:
目錄文件說明:
migrations/ : 用於記錄models 中數據的變更
admin.py : 映射 models 中的數據到 Django 自帶的后台
apps.py : 用於應用程序配置
models.py : 創建數據表模型,與數據庫相關操作對應
views.py : 視圖文件,控制向前端輸送內容
啟動項目,使用 runserver 命令
G:\Python\guest>python manage.py runserver
Django 默認在127.0.0.1:8000 進行監聽,在瀏覽器輸入 http://127.0.0.1:8000 , 若可見 It worked! 提示,說明 Django 已經可以工作。
PS: Django 在 settings.py 中默認開啟 DEBUG = True,若改為 False ,則無法正常打開網頁。 127.0.0.1 指向本機(本電腦)
使用模板
創建模板使用 templates 目錄,Django 會默認去查找該目錄下面的 HTML 文件,在上面已創建的 sign 應用下面,創建了一個
templates/index.html 文件
簡述 Django 工作流(以默認訪問的地址為例):
向瀏覽器發送一個請求,如 http://127.0.0.1:8000/index/ ,Django 默認在127.0.0.1地址,端口8000 上進行監聽,根據 URL 的路徑 /index/,
到 urls.py 文件中對 /index/ 路徑進行匹配(前提:在 urls.py 中對該路徑已進行配置),匹配到該路徑,則調用相應的視圖函數,匹配不到,則提示網頁找不到(404)。
url 路徑匹配模式如下:
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index), #添加index/ 路徑配置
]
上面/index/ 路徑已經提前配置好,下一步根據路徑,去調用相應的視圖函數 views.index (請求指向 sign 應用下的 views.py 文件中的 index 函數)。該函數定義如下:
def index(request):
return render(request, "index.html")
該函數使用 render 模板,返回一個已經寫好的 HTML 頁面。該模板放在 templates 目錄下,使用render() 函數進行調用,瀏覽器最終呈現 index.html 頁面的內容(返回響應)。
各模塊要點
Django MTV 開發模式
M(Models): 代表模型,進行數據存取。處理與數據相關的事物,既如何存取,如何驗證有效。
T(Template): 代表模板,表現層。處理如何展示相關頁面或其它類型文檔。
V(View): 代表視圖,業務邏輯層。處理如何存取模型及調用恰當的模板展現數據,可看做是模型與模板之間的橋梁。
URLconf模塊 urls.py
1、URLconf 模塊包含了 URL 模式(簡單的正則表達式)到視圖函數(views.py)的簡單映射。URLconf的值通過 ROOT_URLCONF 進行設置, 在 /settings.py 中
'''python ROOT_URLCONF = 'guest.urls' ''' Django 會加載 urls.py 文件,並在 urlpatterns 中依次匹配每個 URL 模式,匹配到就指向對應的視圖函數處理。
2、使用正則表達式定義URL模式,使用 re_path() 方法而不是 path() ,命名正則表達式組的語法是(?P <name> pattern),其中name是參數變量的名稱,pattern是要匹配的模式。
例子:
from django.urls import path, re_path from sign import views urlpatterns = [ re_path('sign_index/(?P<eid>[0-9]+)/', views.sign_index), # 簽到 ]
URL調度器使用參考:https://docs.djangoproject.com/zh-hans/2.0/topics/http/urls/
3、在 guest/url.py 文件的 urlpatterns的
path() 中插入 include() 方法,在當包括其它 URL 模式時你應該使用 include()。函數 include() 允許引用其它 URLconfs。每當 Django
遇到 :func:~django.urls.include 時,它會截斷與此項匹配的 URL 的部分,並將剩余的字符串發送到 URLconf 以供進一步處理。
例子:
from django.urls import path, re_path, include # 導入 sign 應用 views 文件 from sign import views urlpatterns = [ path('api/', include('sign.urls', namespace="sign")), # 接口根路徑 ]
sign.urls 有自己的路徑,任意一個都可以放在 /api/ 后面,形成完成的路徑。例如其中某一個匹配例子(在 sign.urls 中的 urlpatterns):
from django.urls import path from sign import views_if app_name = "sign" urlpatterns = [ # sign system interface: # ex : /api/add_event/ path('add_event/', views_if.add_event, name='add_event'), ]
include() 使用 參考:https://docs.djangoproject.com/zh-hans/2.0/intro/tutorial01/
views.py
(Django 中的視圖的概念是「一類具有相同功能和模板的網頁的集合」)
1、 index() 視圖函數,接受 Web 請求並且返回 Web 響應。(Django 只要求視圖返回的是一個 HttpResponse
,或者拋出一個異常)
2、 login_action(request) 處理登錄請求,客戶端發送的請求信息都包含在 request 中。request.POST 通過 .get() 方法獲取“username”和“password”所獲取的用戶名和密碼
3、 HttpResponseRedirect() 對路徑進行重定向,將登錄成功后的請求指向了 /event_manage/ 目錄
4、 render()方法:render(request, template_name, context=None, content_type=None, status=None, using=None)
作用:把 context(一個給定的上下文字典)的內容, 加載進 templates(一個給定的模板)中定義的文件, 並通過瀏覽器渲染呈現. 參數講解: request: 是一個固定參數.
template_name: templates 目錄下定義的文件, 要注意路徑名. 比如'templates\polls\index.html', 參數就要寫‘polls\index.html’
context: 要傳入文件中用於渲染呈現的數據, 默認是字典格式
content_type: 生成的文檔要使用的MIME 類型。默認為DEFAULT_CONTENT_TYPE 設置的值。
status: http的響應代碼,默認是200.
using: 用於加載模板使用的模板引擎的名稱。
5、auth.authenticate() 方法,用於登錄認證。它接受兩個參數,用戶名 username 和 密碼 password ,並在用戶名和密碼正確的情況下返回一個 User 對象。 否則 authenticate() 返回None。
6、auth.login() 方法,用於用戶登錄。該函數接受一個 HttpRequest 對象和一個 User 對象作為參數並使用Django的會話(session)框架把用戶的ID保存在該會話中。
7、user.is_active 判斷用戶名和密碼是否有效。
8、 @login_required 此裝飾器顯限制某個視圖函數必須登錄才能訪問,默認跳轉的 URL 中會包含“/accounts/login/”,需要在 urls.py 中添加新的路徑配置。
9、Django 中 objects.all()、objects.get()、objects.filter() 的區別
· all 返回的是QuerySet(查詢集)對象,程序並沒有真的在數據庫中執行SQL語句查詢數據,但支持迭代,使用for循環可以獲取數據。
· get(** kwargs) 返回的是Model對象,類型為列表,說明使用get方法會直接執行sql語句獲取數據。
· filter(** kwargs) 和get類似,但支持更強大的查詢功能,查詢到的值唯一且不變。
10、request.session.get('user') 為了獲取 sessionid ,用於認證用戶
11、Paginator(guest_list, 2),Django提供了一個分頁器類Paginator(django.core.paginator.Paginator),可以很容易的實現分頁的功能。該類有兩個構造參數,一個是數據的集合,另一個是每頁放多少條數據
分頁器相關源碼參考
https://docs.djangoproject.com/zh-hans/2.2/_modules/django/core/paginator/
12、table.objects.get()返回一個對象,而table.objects.filter()返回一個對象列表
13、get_object_or_404(klass, *args, **kwargs) 用特定查詢條件獲取某個對象,成功則返回該對象,否則引發一個 Http404
參數: · klass 接受一個 Model 類,Manager 或 QuerySet 實例,表示你要對該對象進行查詢
· **kwargs 查詢條件,格式需要被 get() 和 filter() 接受
Django 文檔解釋
為什么我們使用輔助函數 get_object_or_404() 而不是自己捕獲 ObjectDoesNotExist 異常呢?還有,為什么模型 API 不直接拋出 ObjectDoesNotExist 而是拋出 Http404 呢?
因為這樣做會增加模型層和視圖層的耦合性。指導 Django 設計的最重要的思想之一就是要保證松散耦合。一些受控的耦合將會被包含在 django.shortcuts 模塊中。
14、
templates 模板
1、使用模板動態的生成 HTML
2、簡單了解兩個方法:GET 和 POST
GET: 從指定的資源請求數據,一般用於查詢數據;
POST: 向指定的資源提交要被處理的數據,一般用於更新數據,提交表單。
3、GET 方法將用戶提交的數據添加到 URL 中,路徑后面跟問號 “?”,用於區分路徑和參數(問號后面是參數),多個參數之間用“&”隔開。
4、 index.html 中{% csrf_token %},是CSRF令牌(跨站請求偽造),通過該令牌判斷POST請求是否來自同一個網站
5、 form 表單中的 action="/login_action" 指定了提交的路徑,根據該路徑去 urls.py 中匹配 URL 模式,再去 views.py 中執行相應的視圖。
models.py
1、模型基礎知識
· 每一個 model 都是 Python 類,都要繼承 django.db.models.Model 類 · 模型的每個屬性表示數據庫的表字段 · Django 把這一些已經給了一個自動生成的訪問數據庫的 API · 創建模型時,后台會在數據庫自動生成一個 id 作為主鍵,這個主鍵可以被覆蓋
2、str()是被 print 函數調用的,str()返回的內容以字符串形式輸出,該方法告訴 Python 如何將對象以 str 的方式顯示出來。
3、類 Meta 的作用:
模型元數據是“任何不是字段的數據”,比如排序選項(ordering),數據庫表名(db_table)或者人類可讀的單復數名稱(verbose_name 和verbose_name_plural)。在模型中添加class Meta是完全可選的,所有選項都不是必須的。
更多 Django 元數據選項
4、makemigrations 與 migrate 命令的作用
在 models.py 中設計好模型后,需要將模型中的各個屬性(或改動)映射到數據庫中,首先通過 makemigrations 命令操作\guest> python manage.py makemigrations sign
相當於在該 sign 應用中的 migrations 目錄,記錄了所有的關於 modes.py 的改動(比如添加字段,刪除模型等),會自動生成 0001_initial.py 記錄操作, 但是這個改動還沒有作用到數據庫文件\guest> python manage.py migrate
將對模型的改動作用到數據庫文件,比如產生 table ,修改字段的類型等
注意:若更換數據庫,數據庫遷移前要保證在建模階段,把相關字段都填寫正確和規划完整,不然遷移過程會暴露許多問題。這里說的是數據庫遷移,遷移執行的是同步表字段,在 MySQL 數據庫中生成表,而數據是無法復制過去的,可能遷移后需要重新造數據,不然就提前導出數據,遷移完后再導入。
數據庫
1、在 django 中配置 mysql,在 setting.py 修改 DATABASES 就好
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'PORT': '3306', 'NAME': 'test', 'USER': 'root', 'PASSWORD': '', 'OPTIONS': { 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", }, } }
test.py
(該部分編寫單元測試代碼,對發布會、嘉賓管理、嘉賓搜索等進行測試)
Django shell
1、進入 Django shell 模式\guest> python manage.py shell
在 Ipython 模式下編輯
2、獲得某個 table 中的所有對象
table.objects.all()
In [3]: Event.objects.all()
Out[3]: <QuerySet [<Event: 榮耀發布會>]> In [4]: Guest.objects.all() Out[4]: <QuerySet []>
2、插入數據的兩種方式
In [7]: e1 = Event(id=2, name='紅米發布會', limit=20, status=True, address='北京', start_time=datetime(2016,8,10,14,0,0)) ...: e1.save()
Event.objects.create(id=1, name='榮耀發布會', limit=200, status=True, address='深圳會展中心', start_time=datetime(2018,9,22,14,0,0))
3、查詢數據
table.objects.get()
In [14]: e1 = Event.objects.get(name='紅米 MAX 發布會') In [15]: e1 Out[15]: <Event: 紅米 MAX 發布會> In [16]: e1.address Out[16]: '北京會展中心'
4、過濾數據
table.objects.filter() 相當於 SQL 語句中的 LIKE 語句
In [18]: e2 = Event.objects.filter (name__contains='發布會') In [19]: e2 Out[19]: <QuerySet [<Event: 榮耀發布會>, <Event: 紅米發布會>, <Event: 紅米 MAX 發布會>]>
5、刪除數據
table.objects.get().delete()
In [20]: Guest.objects.get(phone='13423454334').delete() Out[20]: (1, {'sign.Guest': 1})
6、更新數據
In [21]: g3 = Guest.objects.get(phone='13012345690') In [22]: g3.realname = 'andy2' In [23]: g3.save()
In [24]: Guest.objects.select_for_update().filter(phone='13012345690').update(realname='andy') Out[24]: 1
其它
1、創建 django_session 表,存放用戶 sessionid 對應的信息
命令:\guest> python manage.py migrate 使用 “migrate” 進行數據遷移,Django 會同時生成 auth_user 表
2、Django 自帶 Admin 管理后台,創建登錄 Admin 后台的管理員賬號
命令:\guest> python manage.py createusperuser
Admin 管理后台登錄地址: http:127.0.0.1:8000/admin/
問題
1、當對手機號進行查詢,若將手機號進行 encode ,則無法正常進行查詢,且分頁器按每頁2條記錄進行划分。
原因:查詢手機號時,輸入的數字,網頁按照默認的編碼格式將參數進行提交。后台獲取該參數后,在進行一次 encode ,則無法與正確的手機號進行匹配,故
無法使用手機號成功查詢,且分頁器因為手機號無法正常匹配,也無法顯示分頁。
2、在 sign_index() 方法 和 sign_index_action() 方法中,傳入的第二個參數無法更換為其它值,如 event_id ,否則報錯,
sign_index() got an unexpected keyword argument 'eid 將 event_id 換為 eid 后,傳參變得正常。
在谷歌看了挺多資料,也看了相關源碼,仍未找到該問題原因。猜測, eid 在這里作為一個位置參數,且名字不可更改。