程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

[Django框架1]基礎知識概要

編輯:Python

Python調C 法力無邊

目前對於Python web來說,主流框架是Django和flask.有同學會問,什麼是框架呢?打一個比方,就是這個包已經幫你做好了整體的框架(類似於骨架的概念),而你就是在裡面縫縫補補,增加細節,一般也都是在settings.py上進行修改配置。
當然了,Python 畢竟是腳本語言,性能上面遠達不到我們所需要的要求,但是其用框架搭建網站是十分快捷的。對於學生來說或者一些小項目,可以考慮使用Python的上述兩種框架。
當然,對於前端的一些知識,可以在設計開發中慢慢增長,但是基礎概念需要掌握的,不過不用在這裡耗太久。
而本次的Django框架也僅僅從模版模型表單視圖等基本內容為主,後續再持續深入,特別是ORM數據庫實例等,倘若還有時間再進行簡單的管理系統進行開發。

本次環境 Python 3.10 Pycharm 2022 Django 3.2

目錄

  • 簡介與創建
  • Django模版
    • Django模版標簽
    • 列表
    • 過濾器
    • 標簽
    • 自定義標簽和過濾器
    • 配置靜態文件
    • 模版繼承
  • Django 模型
    • ORM
    • *數據庫配置
    • 定義模型
    • *數據庫操作
  • Django表單
    • GET方法
    • POST方法
    • get和post的區別
    • Request 對象
  • Django視圖
    • GET
    • POST
    • path
    • method
  • Django路由
    • 無名分組
    • 有名分組
    • 路由分發(include)
    • 反向解析
    • 命名空間

簡介與創建

django本身基於mvc模型,即model view controller 設計模式。是快速開發網站、設計、部署網站的最佳組合。
model:編寫程序應有的功能,負責業務對象與數據庫的映射
view:圖形界面,負責與用戶的交互
controller:負責轉發請求,對請求進行處理

使用pip 安裝django:

pip3 install Django -i https://pypi.tuna.tsinghua.edu.cn/simple

或者直接在pycharm中下載對應的模塊。

使用命令行創建項目


django-admin startproject helloworld
cd helloworld/

或者使用pycharm進行創建(個人推薦使用命令行)

見helloworld文件包,可以看到如上的目錄結構
HelloWorld: 項目的容器。
manage.py: 一個實用的命令行工具,可讓你以各種方式與該 Django 項目進行交互。
HelloWorld/init.py: 一個空文件,告訴 Python 該目錄是一個 Python 包。
HelloWorld/asgi.py: 一個 ASGI 兼容的 Web 服務器的入口,以便運行你的項目。
HelloWorld/settings.py: 該 Django 項目的設置/配置。
HelloWorld/urls.py: 該 Django 項目的 URL 聲明; 一份由 Django 驅動的網站"目錄"。
HelloWorld/wsgi.py: 一個 WSGI 兼容的 Web 服務器的入口,以便運行你的項目。

如何運行了呢?使用如下命令,啟動服務器,

python3 manage.py runserver 127.0.0.1:8000

進入到如下界面,就說明已經配置成功了。(說真的,這個比配置tomcat和springboot簡單多了,也不愧是快速開發的首選框架)

或者也可以在pycharm配置相應的設置方便快速。

由於創建的helloworld沒有views.py文件,所以需要在此目錄下創建views.py,並寫相應的請求,這裡以helloworld為例:

from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world!");

同時需要在urls.py綁定views.hello,注意views.hello不要加括號

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^$',views.hello),
# path('hello/', views.hello),
]

Django path()可以接收4個參數,分別是兩個必選參數:route 、view 和兩個可選參數kwargs、name。
route: 字符串,表示 URL 規則,與之匹配的 URL 會執行對應的第二個參數 view。
view: 用於執行與正則表達式匹配的 URL 請求。
kwargs: 視圖使用的字典類型的參數。
name: 用來反向獲取 URL。

Django模版

上述內容中將數據與視圖混合一起了,不符合MVC思想。而模版是一個文本,用於分離文檔的表現形式和內容。
在helloworld目錄下創建Templates目錄並建立runoob.html文件

<h1>{
{ hello world }}</h1>

接下來在settings.py導入位置 ‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)],
修改 views.py,增加一個新的對象,用於向模板提交數據:
其中render用來傳遞conText填充模版

from django.shortcuts import render
def runoob(request):
context = {
}
context['hello'] = 'hello world'
return render(request,'runoob.html',context)

修改urls.py:

from django.urls import path
from . import views
urlpatterns = [
path('runoob/', views.runoob),
]

再次訪問 http://127.0.0.1:8000/runoob即可訪問了。

Django模版標簽

變量
模版語法:

view: {
"html-name" : "views-name"}
HTML: {
 {
變量名} }
return render(request,"runoob.html",{
"name":views_name})
# runoob.html:
<p>{
 {
name} } </p>

列表

在html中,可以用 . 索引下標取出對應的元素

# views.py
def runoob(request):
view_list = ["123","456"]
return render(request,"runoob.html",{
"views_list":views_list})
# 列表
<p> {
{
view_list}}</p>
<p> {
{
view_list.0}} </p>

過濾器

過濾器有lower. upper. truncatewords. addslashes. date length

此處在runoob.html進行過濾
{
{
變量名 | 過濾器:可選參數 }}
{
{
name|lower}} # 模版過濾器可以在變量被顯示前修改它,過濾器使用管道字符
{
{
bio|truncatewords:"30"}} # 將顯示bio的前三十個詞

過濾器的目的就是過濾使得獲取到相應的字符內容
下面講一個safe:

{
{
 views_str | safe}}
標記為安全不需要轉義,保障絕對安全才能用safe
def runoob(request):
views_str = "<a href='https://www.runoob.com/'>點擊跳轉</a>"
return render(request,"runoob.html",{
"views_str":views_str})
# runoob.html:
{
{
 views_str |safe }}

標簽

if / else 標簽:

{
 % if condition %}
... display
{
% endif %}
或者
{
 % if condition1 %}
... display1
{
% elif condition2 %}
... display2
{
% else %}
{
 % endif % }
{
 % if athlist and coachlist %}
{
% endif %}

for標簽:
{ % for % }

<ul>
{
 % for athlete in athlete_list (reversed)%}
<li> {
{
 athlete.name }} </li>
{
% endfor %}
</ul>

遍歷字典:

# views.py:
def runoob(request):
views_dict={
"name":"cai","age":18}
return render(request,"runoob.html",{
"views_dict":views_dict})
# runoob.html:
{
 % for i ,j in views_dict.items %}
{
{
i}} --- {
{
j}}
{
% endfor% }

ifequal/ifnotequal標簽:
{ % ifequal %}比較兩個值,當他們相等的時候,顯示內容:

{
% ifequal user currentuser %}
<h1> welcome </h1>
{
% else % }
<h1> No </h1>
{
% endifequal %}

注釋

{
 # 這是一個注釋 #}

include 標簽 允許在模版中包含其他的模版內容

{
 % include "nav.html" % }

csrf_token
用於form表單中,作用是跨站請求偽造保護。如果不用的話,再次跳轉會抱403權限錯誤。

自定義標簽和過濾器

在應用目錄下,建一個templatetags (和templates同級)
在該目錄下建一個任意Py文件。

# my_tag.py:
from django import template
register = template.Library() #register名字固定不可改變

其中在settings.py templates下添加libraries配置:

TEMPLATES = [
{

'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR, "/templates",],
'APP_DIRS': True,
'OPTIONS': {

'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
"libraries":{
 # 添加這邊三行配置
'my_tags':'templatetags.my_tags' # 添加這邊三行配置 
} # 添加這邊三行配置
},
},
]

在my_tag.py中建立過濾器與自定義標簽
注意 {% 沒有空格!!!

@register.filter
def my_filter(v1, v2):
return v1 * v2
@register.simple_tag
def my_tag1(v1, v2, v3):
return v1 * v2 * v3
# 在html文件頭部導入py文件
{
% load my_tag %}
{
{
 11|my_filter:22 }}

配置靜態文件

在根目錄下創建statics目錄,在settings最下方配置:

STATIC_URL = '/static/' # 別名 
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"),
]

在statics目錄下創建css目錄 js目錄 images目錄 plugins目錄 分別放css文件 js文件,圖片,插件
把bootstrap框架放入插件目錄 plugins
在html文件的head標簽中引入bootstrap,注意引用路徑的配置文件是別名static

<link rel="stylesheet". href="/static/plugins/bootstrap-3.3.7/dist/css/bootstrap.css">
# html:
{
% load static %}
{
{
name}} <img src="{% static 'images/runoob-logo.png'%}" alt="runoob-logo">

模版繼承

用繼承實現復用,減少冗余內容
父模版 block … endblock 父模版中的預留區域

{
% block name %}
預留給子模版的區域,可以設置默認內容
{
% endblock name %}

子模版 使用extends 繼承父模版

{
 % extends "父模版路徑" %}

在templates目錄下添加 base.html文件:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
<h1>Hello World!</h1>
<p>菜鳥教程 Django 測試。</p>
{
% block mainbody %}
<p>original</p>
{
% endblock %}
</body>
</html>

使runoob.html對其繼承

{
%extends "base.html" %}
{
% block mainbody %}
<p>繼承了 base.html 文件</p>
{
% endblock %}

Django 模型

Django對數據庫提供了很好的支持,提供了統一的調用API,先安裝pymysql模塊,本次使用的數據庫為mysql,同時使用的是阿裡雲服務器主機ip.

ORM

ORM:對象關系映射,用於實現數據之間的轉換。在業務邏輯層和數據庫之間充當了橋梁的作用,通過使用描述對象和數據庫之間的映射的元數據,將程序中的對象自動持久化到數據庫中。
好處:提高了開發效率,不同數據庫可以切換,但是需要轉換sql語句時,執行效率低。
其中 models:數據表 對象實例:一條記錄 屬性:字段

*數據庫配置

在settings.py文件中找到databases配置項,將信息修改為:

DATABASES = {

'default':
{

'ENGINE': 'django.db.backends.mysql', # 數據庫引擎
'NAME': 'runoob', # 數據庫名稱
'HOST': '127.0.0.1', # 數據庫地址,本機 ip 地址 127.0.0.1 ;有服務器就設置自己的服務器
# 服務器記得關閉防火牆,嫌麻煩端口全部打開
'PORT': 3306, # 端口 
'USER': 'root', # 數據庫用戶名
'PASSWORD': '123456', # 數據庫密碼
}
}

在settings中的__init__.py中引入模塊並進行配置:

import pymysql
pymysql.install_as_MySQLdb()

定義模型

使用命令創建app

django-admin startapp TestModel

在TestModel/models.py文件夾下附以下代碼:
類名代表數據庫表名,繼承Model,字段(name),數據類型(CharField) maxlength參數限定長度

from django.db import models
class Test(models.Model):
name = models.CharField(max_length=20)

同時子啊settings.py中找到INSTALLED_APPS這一項,如下:

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'TestModel', # 添加此項
)

在命令行運行,當然也可以使用數據庫工具,創建表TestModel_test

use runoob
create table TestModel_test (
name varchar(20)
)
$ python3 manage.py migrate # 創建表結構
$ python3 manage.py makemigrations TestModel # 讓 Django 知道我們在我們的模型有一些變更
$ python3 manage.py migrate TestModel # 創建表結構

*數據庫操作

在django框架中,統一都是繼承Models,為了兼顧眾多數據庫不同的語言特性,特此開發出的功能。
下面都是一些常規的增刪改查操作,不用特意去記憶,平時敲敲也就記住了,當然重點是前面的步驟沒有出現差錯。
回到helloworld/urls.py

from django.urls import path
from . import views, testdb
urlpatterns = [
path('runoob/', views.runoob),
path('testdb/', testdb.testdb),
]

/helloworld/testdb 增加數據

from django.http import HttpResponse
from TestModel.models import Test
# 添加數據 (由於我這裡在models.py中只設置了name一列)
def testdb(request):
test1 = Test(name='runoob')
test1.save()
return HttpResponse("<p>數據添加成功!</p>")

運行程序,可以看到網頁顯示數據添加成功,同時可以回到數據工具台,使用select語句 ,看是否成功添加。

獲取數據(查找),注意獲取的時候需要循環循環for var in list 讀取想要的格式,否則會報can only concatenate str (not “QuerySet”) to str錯誤。

# testdb.py
from django.http import HttpResponse
from TestModel.models import Test
# 數據庫操作
def testdb(request):
# 初始化
response = ""
response1 = ""
# 通過objects這個模型管理器的all()獲得所有數據行,相當於SQL中的SELECT * FROM
list = Test.objects.all()
# filter相當於SQL中的WHERE,可設置條件過濾結果
response2 = Test.objects.filter(name="jacin")
# 獲取單個對象
response3 = Test.objects.get(id=1)
# 限制返回的數據 相當於 SQL 中的 OFFSET 0 LIMIT 2;
Test.objects.order_by('name')[0:2]
# 數據排序
Test.objects.order_by("id")
# 上面的方法可以連鎖使用
Test.objects.filter(name="runoob").order_by("id")
# 輸出所有數據
for var in list:
response1 += var.name + " "
# response = response1
for var in response2:
response += var.name + " "
return HttpResponse("<p>" + response + "</p>")

更新數據(改),使用save() 或者 update()

# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from TestModel.models import Test
# 數據庫操作
def testdb(request):
# 修改其中一個id=1的name字段,再save,相當於SQL中的UPDATE
test1 = Test.objects.get(id=1)
test1.name = 'Google'
test1.save()
# 另外一種方式
# Test.objects.filter(id=1).update(name='Google')
# 修改所有的列
# Test.objects.all().update(name='Google')
re=Test.objects.filter(id=1)
str=""
for var in re:
str += var.name
return HttpResponse("<p>"+str+" 修改成功</p>")

刪除數據

from django.http import HttpResponse
from TestModel.models import Test
# 數據庫操作
def testdb(request):
# 刪除id=1的數據
test1 = Test.objects.get(id=1)
test1.delete()
# 另外一種方式
# Test.objects.filter(id=1).delete()
# 刪除所有數據
# Test.objects.all().delete()
return HttpResponse("<p>刪除成功</p>")

Django表單

html表單是網站交互性的經典方式。可以查看此處鏈接點擊此處
http協議以請求-回復 方式工作的,發送請求的時候可以附加數據,服務器通過解析請求,可以獲得傳來的數據,並根據url來提供特定的服務。

GET方法

helloworld/helloworld/search.py

from django.http import HttpResponse
from django.shortcuts import render
# 表單
def search_form(request):
return render(request, 'search_form.html')
# 接收請求數據
def search(request):
request.encoding='utf-8'
if 'q' in request.GET and request.GET['q']:
message = '你搜索的內容為: ' + request.GET['q']
else:
message = '你提交了空表單'
return HttpResponse(message)

/helloworld/templates/search_form.html
注意action 屬性是提交的位置,這裡的search下面url跳轉的地址

 <form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="搜索">
</form>

/urls.py

from django.conf.urls import url
from . import views,testdb,search
urlpatterns = [
url(r'^hello/$', views.runoob),
url(r'^testdb/$', testdb.testdb),
url(r'^search-form/$', search.search_form),
url(r'^search/$', search.search),
]

POST方法

get:視圖顯示和請求處理分成兩個函數處理
其實提交數據更常使用post,使用url+處理函數
/helloworld/templates/post.html:
csrf_token:django提供的防止偽裝提交的功能,post方法提交的表格,必須有此標簽

<form action="/search-post/" method="post">
{
% csrf_token %}
<input type="text" name="q">
<input type="submit" value="搜索">
</form>
<p>{
{
 rlt }}</p> <!--預留位置,為表格處理結果預留-->

/helloworld/helloworld/search2.py

# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.views.decorators import csrf
# 接收POST請求數據
def search_post(request):
ctx = {
}
if request.POST:
ctx['rlt'] = request.POST['q']
return render(request, "post.html", ctx)

強調一下,需要加上search-post後面的斜槓,否則讀取不到

# urls.py +
path('search-post/',search2.search_post),

get和post的區別

get: 提交的數據小於1024字節,表單提交時表單數據將在地址欄顯示
post:傳遞數量不限制,提交數據會隱藏,安全性能較高,對信息也做了隱藏。

Request 對象

每個視圖第一個參數是一個HttpRequest對象

from django.http import HttpResponse
def runoob(request):
return HttpResponse("hello world")

path : 請求頁面的全路徑,不包括域名
method : repuest.method == ‘GET’ ‘POST’
cookies: 包含所有cookies的標准python字典對象
meta:包含所有http頭部信息的字典
session:唯一可讀寫的屬性

Django視圖

視圖函數,接受web請求並返回web響應。響應可以是html頁面等。
視圖有兩個重要的對象,分別是請求對象 request 與 HttpResponse
請求對象 (HttpRequest對象)

GET

數據類型是QuerDict,類似於字典的對象,取值格式: 對象.方法,get()

def runoob(request):
name = request.GET.get("name")
return HttpResponse('name:{}'.format(name))

POST

數據類型和GET一致

def runoob(request):
name = request.POST.get("name")
return HttpResponse('name:{}'.format(name))

path

獲取URL的路徑,數據類型是字符串

def runoob(request):
name=request.path
print(name)
return HttpResponse("name")

method

獲取當前請求的方式,數據類型為字符串,結果大寫

def runoob(request):
name = request.method
print(name)
return HttpResponse("name")

Django路由

路由就是根據用戶請求的URL來判斷對應的處理程序,並返回處理結果,即URL與Django的視圖建立映射關系
path:普通路徑,不需要自己手動添加正則首位限制符號,底層添加
re_path: 正則路徑 ,需要手動添加正則首位限制符號

關於正則表達式,我將單獨出一期筆記

無名分組

正則路徑的無名分組,按位置傳參,一一對應
views除了request ,其他行參數量與urls中的分組數量一致
下面的路徑就是index/year(具體的日期)

# views.py
from django.shortcuts import HttpResponse
def index(request,year):
print(year)
return HttpResponse("name")
# urls.py
urlpatterns = [
path('admin/',admin.site.urls),
re_path("^index/[0-9]{4}/$",view.index),
]

有名分組

故名思義,有名分組按照關鍵字傳參,與順序無關

(?P<組名> 正則表達式)
# views.py
from django.shortcuts import HttpResponse
def index(request, year, month):
print(year,month) # 一個形參代表路徑中一個分組的內容,按關鍵字對應匹配 
return HttpResponse('name')
# urls.py
re_path("^index/(?P[0-9]{4}/(?P[0-9]{2}/$",views.index)

路由分發(include)

問題:django 項目多個app目錄使用一個urls會造成混淆,後期維護也不方便
解決:使用路由轉發,每個app目錄都有urls

from app01 import views
# urls.py
path("app01/",include("app01.urls"))

反向解析

隨著功能的增加,路由層的url發生變化,需要修改對應的視圖層和模版層的url,比較麻煩
可以利用反向解析,當url發生變化可以反向解析,一般用在模版中的超鏈接及視圖中的重定向

普通連接

# 
path("login1/",view.login,name="login")
# 在views.py ,從urls 引入reverse
return redirect(reverse("login"))
#templates/ .html
<form action="{% url 'login' %}" method="post">

正則路徑(無名分組)

# urls.py
re_path(r"^login/([0-9]{2})/$",views.login,name="login")
# views.py
# 引入reverse 利用reverse("路由別名“,args=(符合正則匹配的參數,))
return redirect(reverse("login",args=(10,)))
#/templates/ .html
<form action={
% url 'login' 10 %}" method="post">

正則路徑(有名分組)

# urls.py
re_path(r"^login/(?<year>[0-9]{4}/$",views.login,name="login")
# views.py
return redirect(reverse("login",kwargs={
"year":3333}))
# html
<form action="{% url 'login' year=3333 %}" method="post">

命名空間

故名思義,和其他的編程語言類似。是標識符空間定義
普通路徑

include(("app名稱:urls","app名稱"))

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved