Django入門

Fredette發表於2024-03-10

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')
]

image-20240227171030072

(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>

image-20240227171652726

【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
  • 資料庫生效

image-20240229145957825

【六】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)

相關文章