Django入門
- 啟動django專案之後 如何新增更多的功能
- 回想自己編寫的web框架 如果要新增功能 就去urls.py和views.py
【1】新增URL對映
- 在專案的
urls.py
檔案中,透過匯入相應的應用(app)及其檢視函式,並使用path()
或include()
函式來定義 URL 對映規則。 - 例如,如果要在名為 "myapp" 的應用中新增一個用於顯示部落格文章列表的 URL,則可以在
urlpatterns
中新增如下配置
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.blog_list, name='blog_list'),
]
- 這將把 "/blog/" 對映到
views.blog_list
檢視函式。
【2】新增檢視函式
- 然後,在對應的 "myapp/views.py" 檔案中,建立檢視函式以處理 HTTP 請求。
- 例如,
blog_list
可能如下實現:
from django.shortcuts import render
from .models import BlogPost
def blog_list(request):
posts = BlogPost.objects.all()
return render(request, 'myapp/blog_list.html', {'posts': posts})
- 這裡假設有一個名為 "BlogPost" 的模型,並有一個包含模板
blog_list.html
的對應 HTML 模板檔案。
【一】Django小白必會三板斧
【1】HttpResponse
HttpResponse
: 這是 Django 自帶的類,用於構建基本的 HTTP 響應。- 例如,當需要返回純文字或 JSON 資料時,可以這樣建立響應:
# 給一個位置引數 request
def index(request):
print(request)
# 返回文字和JSON資料時
return HttpResponse("OK")
【2】render
- 主要用於返回html檔案 並且支援模板語法(django自己寫的)
render()
: 這個函式用於從給定的模板載入內容,並將其插入到 HTTP 響應中作為 HTML 內容傳送給客戶端。- 例如,在上面的
blog_list
檢視中,我們使用了它來返回帶有部落格文章列表的 HTML:
from django.http import HttpResponse
from django.shortcuts import render, redirect
# Create your views here.
# 給一個位置引數 request
def index(request):
print(request)
# request: 當前request物件
# template_name: 當前APP下面有一個template資料夾
# render負責返回前端頁面
return render(request, "index.html")
【3】redirect
- 主要用於重定向 括號內可以寫其他網站的全稱 也可以自己網站的字尾
redirect()
: 該函式用於向使用者返回一個 HTTP "Redirect" 響應,使瀏覽器跳轉至指定的 URL。
from django.http import HttpResponse
from django.shortcuts import render, redirect
# Create your views here.
# 給一個位置引數 request
def index(request):
print(request)
# request: 當前request物件
# template_name: 當前APP下面有一個template資料夾
# render負責返回前端頁面
return redirect('/home/')
def home(request):
print(request)
return render(request, "index.html")
- urls.py
from django.contrib import admin
from django.urls import path
from app01.views import index, home
urlpatterns = [
path('admin/', admin.site.urls),
# 註冊路由和檢視函式的對映關係
path("index/", index),
path("home/", home, name="home")
]
【補充】django自帶重啟功能
- 當識別到專案中程式碼有變化之後 隔段時間會自動重啟 但是有時候較慢
【二】靜態檔案配置說明
【1】模版檔案
- 我們將html檔案預設都放在templates資料夾下
【2】資原始檔
-
我們將網站所使用的靜態檔案預設都放在static資料夾下
靜態檔案:前段已經寫好,能直接使用的檔案 網站寫好的JS檔案 網站寫好的CSS檔案 網站用到的圖片檔案 第三方框架 ... 拿來直接就可以使用的檔案
-
一般情況我們再static資料夾下還會對檔案進行劃分
- js資料夾
- css資料夾
- img資料夾
- plugins資料夾
-
在瀏覽器中輸入url能夠看到對應的資源
-
是因為後端提前開設了相關的介面
-
如果訪問不到資源,說明後端沒有開設相關資源的埠
【3】靜態檔案配置
- Django靜態檔案配置官網:https://docs.djangoproject.com/en/3.2/howto/static-files/
【1】配置檔案增加配置
(1)後端
settings.py
配置檔案中增加如下配置
# 靜態檔案配置
# 預設查詢位置是當前APP的目錄下
# 這個配置定義了靜態檔案應用在啟用 FileSystemFinder 查詢器時將穿越的額外位置
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
(2)前端
- 在前端頁面中增加如下配置,即可使用靜態檔案模版語法
# 第一步
# 在前端頁面中的第一行
# {% load static %}
# 第二步:使用靜態檔案
# {% static 'avatar/1.jpg' %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>當前是index頁面</h1>
<img src="{% static 'avatar/1.jpg' %}" alt="">
</body>
</html>
【2】配置檔案說明
- 如果想要訪問static靜態檔案,就必須以static開頭
- 如:
/static/plugins/Bootstrap/js/bootstrap.js/bootstrap.min.js
- 如:
【三】request物件方法
【1】提交GET請求
(1)前端
-
form表單中action屬性,不寫預設是當前路由地址
-
form表單中的method屬性,不寫預設是GET請求
-
前端頁面
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
{# <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>#}
{# <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">#}
{# <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>#}
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<h1 class="text-center">註冊頁面</h1>
<form action="" method="get"></form>
<form action="" method="post">
{# action : 指定提交資料的路由地址 ,如果不寫預設是當前路由地址 #}
<div>username:<input type="text" class="form-control" name="username"></div>
<div>password:<input type="text" class="form-control" name="password"></div>
<div>
hobby :
<input type="checkbox" name="hobby" value="music">音樂
<input type="checkbox" name="hobby" value="sport">運動
<input type="checkbox" name="hobby" value="swim">游泳
</div>
<div><input type="submit" class="btn btn-success" id="btn_submit"></div>
</form>
</div>
</div>
</div>
</body>
</html>
(2)後端
- app01/views.py
def register(request):
print(request)
print(request.method)
return render(request, "register.html")
- urls.py
from django.contrib import admin
from django.urls import path
from app01.views import index, home, register
urlpatterns = [
path('admin/', admin.site.urls),
# 註冊路由和檢視函式的對映關係
path("index/", index),
path("home/", home, name="home"),
path("register/", register)
]
前端路由地址訪問
- http://127.0.0.1:8000/register
【2】提交POST請求
- 修改上述前端程式碼的get就可以了,改成post
- 如果post請求報錯修改settings檔案裡的其中一條進行註釋,後續會繼續學習解決辦法
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
【3】request物件屬性和方法
【1】request.method
- 獲取發起請求的請求方式
- get請求攜帶的資料是由大小限制的
- post請求攜帶的請求引數沒有限制
【2】request.post
- 獲取使用者輸入的請求資料,但不包含檔案
- 返回的是:大寫字串
【3】get/getlist
get
只會獲取列表最後一個元素getlist
直接將列表取出(多選項)
示例:
(1)register.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
{# <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>#}
{# <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">#}
{# <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>#}
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<h1 class="text-center">註冊頁面</h1>
<form action="" method="get"></form>
<form action="" method="post">
{# action : 指定提交資料的路由地址 ,如果不寫預設是當前路由地址 #}
<div>username:<input type="text" class="form-control" name="username"></div>
<div>password:<input type="text" class="form-control" name="password"></div>
<div>
hobby :
<input type="checkbox" name="hobby" value="music">音樂
<input type="checkbox" name="hobby" value="sport">運動
<input type="checkbox" name="hobby" value="swim">游泳
</div>
<div><input type="submit" class="btn btn-success" id="btn_submit"></div>
</form>
</div>
</div>
</div>
</body>
</html>
(2)後端
- app01/views.py
def register(request):
# 【1】第一個方法 request.method : 獲取到當前請求的請求方式
print(request.method) # GET / POST
# 如果是 POST 請求 會報錯 CSRF verification failed. Request aborted.
# 解決辦法:註釋掉settings.py檔案中的一個配置項 django.middleware.csrf.CsrfViewMiddleware 註釋掉
# 【2】第二個方法 : request.GET : 獲取到GET請求攜帶的引數
if request.method == "GET":
data = request.GET
print(data) # <QueryDict: {'username': ['dream'], 'password': ['22'], 'hobby': ['music', 'sport']}>
# (1)如果是普通的鍵值對資料,直接get(key)
username = data.get("username")
password = data.get("password")
# 雖然後端看到的資料是一個列表,但是發現前端頁面上的路由不是三個
# http://127.0.0.1:8000/register/?username=&password=&hobby=music&shobby=port&hobby=swim
# 只能取到最後一個
# (2)如果是列表形式的資料 getlist(key)
hobby = data.getlist("hobby")
print(username)
print(password)
print(hobby)
# 【3】第三個方法:如果是POST請求,需要 request.POST 獲取請求體資料
elif request.method == "POST":
data = request.POST
print(data) # <QueryDict: {'username': ['dream'], 'password': ['521'], 'hobby': ['music', 'sport', 'swim']}>
username = data.get("username")
password = data.get("password")
hobby = data.get("hobby")
print(username)
print(password)
print(hobby)
return render(request, "register.html")
(3)urls.py
from django.contrib import admin
from django.urls import path
from app01.views import index, home, register
urlpatterns = [
path('admin/', admin.site.urls),
# 註冊路由和檢視函式的對映關係
path("index/", index),
path("home/", home, name="home"),
path("register/", register)
]
【四】Django連線資料庫
【1】Django自帶一個資料
- 自帶一個資料庫sqlite3
# 在settings.py檔案中
# 資料庫的配置項
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
【2】Django連線MySQL資料庫
(1)配置mysql引數
DATABASES = {
'default': {
# ENGINE :預設的引擎 mysql
'ENGINE': 'django.db.backends.mysql',
# HOST : 主機地址127.0.0.1/localhost
"HOST": "127.0.0.1",
# "PORT": 3306,
"PORT": 3306,
# USER: 使用者名稱
"USER": "root",
# PASSWORD: 資料庫密碼
"PASSWORD":"123456",
# NAME : 資料庫名字
"NAME" : "django_02",
# CHARSET: 預設編碼集
"CHARSET" : "utf8mb4"
}
}
(2)啟動Django報錯
Did you install mysqlclient?
【3】啟動mysql報錯
(1)解決辦法一
- 猴子補丁
- 可以放在任意位置的
__init__.py
檔案中
import pymysql
pymysql.install_as_MySQLdb()
(2)下載第三方模組
- 3.x版本以後建議你使用 mysqlclient
pip install mysqlclient
- 運氣
- win 電腦給力一點,安裝就不會報錯
- mac系統安裝 mysqlclient 費勁
(3)win報錯解決辦法
- 訪問 whl檔案的官網
- https://pypi.org/project/mysqlclient/#files
pip install mysqlclient-2.2.4-cp310-cp310-win_amd64.whl
【五】Django中的ORM框架
【1】什麼是ORM
- ORM是一種將物件與關係型資料庫之間的對映的技術,主要實現了以下三個方面的功能:
- 資料庫中的表對映為Python中的類
- 資料庫中的欄位對映為Python中的屬性
- 資料庫中的記錄對映為Python中的例項
- ORM的主要優點是可以減少開發人員編寫重複的SQL語句的時間和工作量,並且可以減少由於SQL語句的調整和更改所帶來的錯誤。
【2】DjangoORM框架的優點
- 與其他ORM框架相比,Django ORM擁有以下優點:
- 簡單易用:Django ORM的API非常簡單,易於掌握和使用。
- 豐富的API:Django ORM提供了豐富的API來完成常見的資料庫操作,如增刪改查等,同時也支援高階查詢和聚合查詢等操作。
- 具有良好的擴充套件性:Django ORM可以與其他第三方庫進行無縫整合,如Django REST framework、Django-Oscar等。
- 自動對映:Django ORM支援自動對映,開發者只需要定義資料庫表的結構,就可以自動生成相應的Python類,從而減少開發過程中的重複程式碼量。
【3】ORM之建表操作
(1)在app下面的models.py檔案中定義模型表
from djaogo.db import models
# Create your models here.
class User(models.Model):
# 資料庫中的欄位對映為Python中的屬性
# 定義一個使用者名稱: 字串型別 長度
# Mysql中字串型別的欄位:char varchar(32)
# CharField: 字串型別的欄位
# max_LENGTH: 最大長度
# verbose_name: 註釋
# help_text : 解釋
username = models.CharField(max_length=32,verbose_name="使用者名稱",help_text="這是一個使用者名稱欄位")
password = models.CharField(max_length=32)
# IntergerField:相當於Mysql中的int欄位
age = models.IntegerField()
# FloatField: 相當於Mysql資料庫中的float 欄位
salary = models.FloatField()
(2)遷移檔案
- 生成遷移檔案
- 將操作記錄記錄在migrations資料夾
- 雖然資料夾內有相關檔案,但是此時並沒有同步到資料庫中,所以資料庫是沒有資料的
- manage.py 執行相關命令
- 方式有兩種
- 一種是 task 任務裡面
- 一種是命令列
E:\PycharmProjects\djangoProject>python manage.py makemigrations
Migrations for 'app01':
app01\migrations\0001_initial.py
- Create model User
-
遷移檔案生效
-
將操作同步到真正的資料庫
-
只要修改了models中有關資料庫相關的程式碼,就必須執行上面的資料庫遷移命令
migrate 動詞 migrations 名詞
python manage.py migrate
- 資料庫生效
【六】ORM操作之欄位操作
【1】欄位屬性
(1)允許為空
- 在定義模型類的相應欄位時,可以為該欄位新增
null=True
屬性以允許其值為None
或空字串。
class MyModel(models.Model):
name = models.CharField(max_length=50, null=True) # 允許name欄位為空
(2)指定預設值
- 設定欄位的預設值可透過在欄位定義時附加
default
引數實現。例如,給欄位age
設定預設值為 18
class MyModel(models.Model):
age = models.IntegerField(default=18) # 預設年齡為18歲
【2】欄位增加
- 要在 Django 模型表中增加新的欄位,只需在相應的 Model 類中新增新欄位及其型別和所需屬性。
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True) # 新增一個自動記錄建立時間的datetime欄位
is_active = models.BooleanField(default=True) # 新增一個布林型別欄位,預設啟用狀態為True
【3】欄位刪除
- 要從模型表中刪除欄位,請直接在 Model 類中註釋掉該欄位或者將其完全移除。
- 不過,在生產環境中刪除欄位前請確保不會影響現有資料,因為這可能導致資料丟失或結構不一致。
class MyModel(models.Model):
name = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True) # 移除is_removed欄位
【補充】
- 每次修改關於資料庫欄位的操作時,都要執行資料庫的遷移相關操作
python manage.py makemigrations
python manage.py migrate
【七】ORM操作之資料操作
【1】增加
(1)語法
模型表名:object.create(欄位名=欄位值)
(2)示例
new_interface = MyModel.objects.create(
name="zhangsan",
age=25,
email="zhangsan@example.com"
)
【2】查詢
(1)語法
- 獲取到當前表中的全部資料
模型表名.object.all()
- 根據指定條件篩選資料
# 方式一
模型表名.objects.get(篩選欄位名=篩選欄位值)
# 方式二
模型表名.objects.filter(篩選欄位名=篩選欄位值)
- 去除指定條件的資料
模型表名.object.exclude(篩選欄位名=篩選欄位值)
(2)示例
# 獲取表中所有資料
all_records = MyModel.objects.all()
# 根據特定條件篩選資料(方式一)
filtered_records = MyModel.objects.get(name="張三")
# 根據特定條件篩選資料(方式二)
# 查詢包含"張"的所有name
filtered_records = MyModel.objects.filter(name__contains="張")
# 去除滿足指定條件的資料
# 過濾掉所有年齡小於18歲的記錄
excluded_records = MyModel.objects.exclude(age__lt=18)
【3】更改
(1)語法
# 方式一:先查詢直接修改
模型表名.objects.filter(篩選欄位名=篩選欄位值).update(修改欄位名=修改欄位值)
# 方式二:先查詢後修改
obj = 模型表名.objects.get(篩選欄位名=篩選欄位值)
obj.修改欄位名=修改欄位值
obj.save()
(2)示例
# 可以使用.filter() 和 .update() 方法批次更新符合條件的資料
# 所有年齡為25的記錄年齡改為26
MyModel.objects.filter(age=25).update(age=26)
# 更新已有記錄的值,可先透過查詢獲取物件例項後呼叫 .save() 方法
instance_to_update = MyModel.objects.get(name="張三")
instance_to_update.age = 26
instance_to_update.save()
【4】刪除
(1)語法
# 方式一:刪除需要先查詢直接刪除
模型表名.objects.filter(篩選欄位名=篩選欄位值).delete()
# 方式二:刪除需要先查詢再刪除
instance_to_delete = MyModel.objects.get(篩選欄位名=篩選欄位值)
instance_to_delete.delete()
(2)示例
# 刪除滿足特定條件的記錄,通常先透過查詢獲取物件例項再呼叫 .delete() 方法
instance_to_delete = MyModel.objects.get(name="張三")
instance_to_delete.delete()
# 可以使用 .filter() 方法批次刪除
MyModel.objects.filter(name="李四").delete() # 刪除所有名字為"李四"的記錄
- 整理
from django.test import TestCase
# from app01.models import User
import os
# Create your tests here.
if __name__ == '__main__':
# 先匯入一句話
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject.settings')
# 啟動django
import django
django.setup()
from app01 import models
# 建表語句
# user_obj = models.User.objects.create(username="zhangsan", age=18, salary=1000, password="123")
# user_obj = models.User.objects.create(username="lisi", age=24, salary=1000, password="12")
# print(user_obj)
# 查詢資料
# user_data = models.User.objects.all().values_list()
# print(user_data)
user_obj = models.User.objects.filter(username="zhangsan").first()
print(user_obj.username)
print(user_obj.age)