01-新建一個名為“mall_backend”的Project
命令如下:
CD E:\Python_project\P_001\myshop-test
E:
django-admin startproject mall_backend
02-新建應(yīng)用并注冊應(yīng)用
執(zhí)行下面條命令依次創(chuàng)建需要的應(yīng)用:
CD E:\Python_project\P_001\myshop-test\mall_backend\
E:
python manage.py startapp users
名叫users的應(yīng)用創(chuàng)建好后,還需要在全局配置文件中對應(yīng)在用進行注冊,具體方法如下:
打開““E:\Python_project\P_001\myshop-test\mall_backend\mall_backend\settings.py””文件,找到名叫“INSTALLED_APPS”的列表(list),在其中加入應(yīng)用名,如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users', # 這是自己創(chuàng)建的應(yīng)用,需要手動注冊
]
03-實現(xiàn)“用戶注冊”模塊
“用戶注冊”模塊使用如下技術(shù)來開發(fā)。
使用Form表單方式進行表單數(shù)據(jù)的驗證。
通過繼承AbstractUser類來簡化用戶權(quán)限認證。
03-01-創(chuàng)建數(shù)據(jù)庫模型類
打開文件 E:\Python_project\P_001\myshop-test\mall_backend\users\models.py 寫入下面的代碼:
from django.db import models
from datetime import datetime
from django.contrib.auth.models import AbstractUser, Group, Permission
class MyUser(AbstractUser):
SEX = (
(0, '男'),
(1, '女'),
)
LEVEL = (
(1, '寂寞卡會員'),
(2, '鉆石卡會員'),
(3, '金卡會員'),
(4, '銀卡會員'),
)
STATUS = (
(0, '正常'),
(1, '異常'),
)
groups = models.ManyToManyField(
Group,
verbose_name='groups',
blank=True,
help_text='The groups this user belongs to.',
related_name='user_groups' # 設(shè)置不同的 related_name
)
user_permissions = models.ManyToManyField(
Permission,
verbose_name='user permissions',
blank=True,
help_text='Specific permissions for this user.',
related_name='user_permissions' # 設(shè)置不同的 related_name
)
nickname = models.CharField('qq', blank=True, max_length=50)
truename = models.CharField('真實姓名', blank=True, max_length=50)
mobile = models.CharField('手機號碼', max_length=11, default="")
sex = models.IntegerField(default=0, choices=SEX)
birthday = models.DateField(blank=True, null=True)
user_img = models.ImageField("頭像", upload_to="user_img", default="")
level = models.IntegerField(default=4, choices=LEVEL)
status = models.IntegerField(default=0, choices=STATUS)
create_time = models.DateTimeField(default=datetime.now, verbose_name='創(chuàng)建時間')
update_time = models.DateTimeField(default=datetime.now, verbose_name="更新時間")
def __str__(self):
return self.username
class Meta(AbstractUser.Meta):
permissions = (
['check_myuser', '審核用戶信息'],
)
問:在整個項目中,還用到了字段password、is_staff、is_superuser,那這些字段為什么不定義呢?原因是在基類AbstractUser中已經(jīng)定義了。詳情見:https://blog.csdn.net/wenhao_ir/article/details/131594115
03-02-創(chuàng)建表單類及表單類代碼詳解
在目錄 E:\Python_project\P_001\myshop-test\mall_backend\users 下新建文件 forms.py
然后寫入下面的代碼A:
from users.models import *
from django import forms
from django.core.exceptions import ValidationError
import re
def mobile_validate(value):
mobile_re = re.compile(
r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手機號碼格式錯誤')
class UserRegForm(forms.Form):
username = forms.CharField(label="用戶名", min_length=6,
widget=forms.widgets.TextInput(
# 其中class樣式為form-control,這是bootstrap的樣式
attrs={'class': 'form-control', 'placeholder': "請輸入用戶名"}),
error_messages={
'required': '用戶姓名不能為空',
'min_length': '長度最少6位',
})
password = forms.CharField(label="密碼", min_length=6, max_length=10,
widget=forms.widgets.PasswordInput(
# render_value=True,頁面校驗不通過后,頁面上該值還存在
attrs={"class": "form-control"}, render_value=True),
error_messages={
'max_length': '密碼最長10位',
'required': '密碼不能為空',
'min_length': '密碼最少6位'
})
re_password = forms.CharField(label="確認密碼", min_length=6, max_length=10,
widget=forms.widgets.PasswordInput(
# render_value=True,頁面校驗不通過后,頁面上該值還存在
attrs={"class": "form-control"}, render_value=True),
error_messages={
'max_length': '密碼最長10位',
'required': '密碼不能為空',
'min_length': '密碼最少6位'
})
nickname = forms.CharField(label="昵稱", max_length=20, required=False,
widget=forms.widgets.TextInput(
# 其中class樣式為form-control,這是bootstrap的樣式
attrs={'class': 'form-control', 'placeholder': "請輸入用戶昵稱"}),
error_messages={
'required': '用戶昵稱不能為空',
'max_length': '昵稱長度不能超過20位',
})
email = forms.EmailField(label="郵箱",
widget=forms.widgets.EmailInput(
attrs={'class': 'form-control', }),
error_messages={
'required': '郵箱不能為空',
'invalid': '郵箱格式不對',
})
mobile = forms.CharField(label="手機號碼", validators=[mobile_validate],
widget=forms.widgets.TextInput(
attrs={'class': 'form-control', }),
error_messages={
'required': '手機號碼不能為空',
})
user_img = forms.ImageField(label="用戶頭像", required=False, widget=forms.widgets.FileInput(
attrs={'class': 'form-control'}))
# 全局鉤子函數(shù)
def clean(self):
password = self.cleaned_data.get("password")
re_password = self.cleaned_data.get("re_password")
print(password)
if password != re_password:
# raise forms.ValidationError("二次密碼輸入不一致")
self.add_error("re_password", ValidationError("二次密碼輸入不一致"))
①類ValidationError有什么作用?
答:在Django中,ValidationError
類是一個異常類,它屬于django.core.exceptions
模塊。當(dāng)數(shù)據(jù)驗證失敗時,可以通過引發(fā)ValidationError
異常來表示驗證錯誤。
②-①re.compile()方法有什么用?
請參考博文:https://blog.csdn.net/wenhao_ir/article/details/132026895
②-2 有沒有關(guān)于正則表達式 r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
的詳細理解?
請參考博文 https://blog.csdn.net/wenhao_ir/article/details/132027668 的第4點、第5點和第6點。
③能不能介紹下Django中的表單(forms)模塊中的類forms.CharField?
請參考博文:https://blog.csdn.net/wenhao_ir/article/details/132029002
④能不能介紹下什么是Django表單中的全局鉤子函數(shù)?
在Django表單中,全局鉤子函數(shù)(Global Form Validation Hook)是指在表單類中定義的特殊方法,它允許開發(fā)者對表單中的多個字段進行綜合性的驗證和處理。全局鉤子函數(shù)會在表單的所有字段個別驗證完成后被調(diào)用,用于執(zhí)行那些需要考慮多個字段相互關(guān)系的驗證邏輯或處理邏輯。
通常情況下,Django表單中的字段驗證是在各個字段的 clean_<field_name>
方法中進行的。例如,對于一個字段名為 username
的表單字段,其驗證邏輯會放在 clean_username()
方法中。這樣的驗證方法稱為字段級別的驗證。
但是,有些情況下需要對多個字段的數(shù)據(jù)進行聯(lián)合驗證或驗證它們之間的關(guān)系。這時就可以使用全局鉤子函數(shù)來進行全局性的表單驗證。全局鉤子函數(shù)的名稱是 clean
,它沒有特定的字段名稱前綴,而是直接在表單類中定義。
全局鉤子函數(shù)的工作方式如下:
-
先執(zhí)行各個字段的單獨驗證方法(如
clean_username()
,clean_password()
等)來驗證各個字段的合法性。 -
在所有字段單獨驗證通過后,Django會自動調(diào)用全局鉤子函數(shù)
clean()
(如果表單類中有定義)。 -
在
clean()
方法中,您可以對多個字段的數(shù)據(jù)進行綜合驗證和處理。如果需要在多個字段之間執(zhí)行聯(lián)合驗證,這里是合適的位置。 -
如果全局鉤子函數(shù)
clean()
驗證失敗(即調(diào)用self.add_error()
方法添加了錯誤信息),則表單將被認為是無效的,驗證失敗的錯誤信息將在表單的非特定字段下方顯示。
總結(jié):全局鉤子函數(shù)是在Django表單中定義的用于對多個字段進行綜合性驗證和處理的特殊方法。它在所有字段個別驗證通過后被自動調(diào)用,允許開發(fā)者執(zhí)行聯(lián)合驗證或處理多個字段之間的關(guān)系。
⑤能不能介紹下代碼password = self.cleaned_data.get("password")
?
當(dāng)用戶提交表單后,self.cleaned_data
是一個字典,其中包含經(jīng)過表單字段驗證后的干凈數(shù)據(jù)。每個表單字段的值,如果有效,都會存儲在這個字典中,以其相應(yīng)的字段名為鍵。
在代碼中的這一行 password = self.cleaned_data.get("password")
,self.cleaned_data.get("password")
用于從字典中獲取經(jīng)過驗證的 “password” 字段的干凈值。
下面是對這一行代碼的詳細解釋:
-
self
:在 Django 表單的上下文中,self
是表單實例自身的引用。它是封裝表單數(shù)據(jù)和邏輯的對象。 -
cleaned_data
:cleaned_data
是表單實例(self
)的屬性,它保存用戶提交的經(jīng)過驗證和清理后的數(shù)據(jù)。這個字典中的數(shù)據(jù)根據(jù)表單類中定義的字段類型和驗證器進行了清理和格式化。 -
.get("password")
:Python 字典的get()
方法用于根據(jù)給定的鍵獲取與之關(guān)聯(lián)的值。在這里,鍵是 “password”,對應(yīng)著 “password” 表單字段的名字。
self.cleaned_data.get("password")
這一行代碼從表單的 cleaned_data
字典中獲取 “password” 字段的干凈值。如果表單有效且 “password” 字段存在并且通過了驗證,它會返回 “password” 字段的干凈值。如果 “password” 字段無效或未包含在提交的數(shù)據(jù)中,它將返回 None
。
通過使用這種方法來訪問清理后的數(shù)據(jù),表單的作者可以安全地獲取用戶的輸入,無需擔(dān)心潛在的驗證錯誤或缺失的字段。這是 Django 表單中常用的訪問經(jīng)過驗證數(shù)據(jù)的方式。
⑥能不能介紹下代碼 self.add_error("re_password", ValidationError("二次密碼輸入不一致"))
?
當(dāng)表單數(shù)據(jù)在全局鉤子函數(shù) clean
中進行綜合校驗時,如果發(fā)現(xiàn)特定的校驗規(guī)則未通過,開發(fā)者可以通過 self.add_error(field, error)
方法來向表單字段添加錯誤信息。
在代碼A中的這一行 self.add_error("re_password", ValidationError("二次密碼輸入不一致"))
,self.add_error()
方法用于向表單字段添加錯誤信息,以告知用戶二次密碼輸入不一致。
下面是對這行代碼的詳細解釋:
-
self
:在 Django 表單的上下文中,self
是表單實例自身的引用。它是封裝表單數(shù)據(jù)和邏輯的對象。 -
add_error()
:add_error()
是表單實例的方法,用于向表單字段添加錯誤信息。它接收兩個參數(shù):- 第一個參數(shù)是表單字段的名稱(field),這里是 “re_password”,即確認密碼字段的名稱。
- 第二個參數(shù)是一個 ValidationError 對象,它用于指定具體的錯誤信息。
-
“re_password”:這是表單字段的名稱,即確認密碼字段的名稱。表單字段的名稱是在定義表單類時給定的。
-
ValidationError("二次密碼輸入不一致")
:這是一個 ValidationError 對象,用于指定錯誤信息。在這里,它表示 “二次密碼輸入不一致” 是校驗失敗的原因。
在全局鉤子函數(shù) clean
中,當(dāng)表單數(shù)據(jù)不滿足某些特定的條件時(例如,密碼和確認密碼不一致),開發(fā)者可以使用 self.add_error()
方法來添加錯誤信息,然后這些錯誤信息將在渲染表單時顯示給用戶,幫助用戶找到并糾正表單中的錯誤。
問:為什么add_error()要有第一個參數(shù),即表單字段的名稱呢?我感覺沒有用呀。
您提出的疑問很合理。實際上,在全局鉤子函數(shù) clean
中使用 self.add_error()
方法時,第一個參數(shù),即表單字段的名稱,是非常有用的。它有兩個重要的作用:
-
指定出現(xiàn)錯誤的字段: 在一個表單中,可能有多個字段需要進行全局校驗,而不僅僅是一個確認密碼字段。通過指定字段的名稱作為第一個參數(shù),
self.add_error()
方法可以告訴 Django 哪個字段出現(xiàn)了錯誤,從而確保錯誤信息被添加到正確的字段中。 -
顯示錯誤信息: 表單字段的名稱不僅指定了出現(xiàn)錯誤的字段,還在渲染表單時用于顯示錯誤信息。當(dāng)
self.add_error()
方法被調(diào)用后,錯誤信息將與相應(yīng)字段一起傳遞給前端頁面。這樣,用戶在查看表單時可以清楚地看到哪些字段存在錯誤以及錯誤的具體信息。
例如,在代碼A中,self.add_error("re_password", ValidationError("二次密碼輸入不一致"))
會向 “re_password” 字段添加一個 “二次密碼輸入不一致” 的錯誤信息。如果用戶在確認密碼時輸入的密碼與之前輸入的密碼不一致,就會觸發(fā)這個錯誤,并在確認密碼字段下方顯示 “二次密碼輸入不一致” 的錯誤提示,幫助用戶及時糾正錯誤。
總結(jié):表單字段的名稱作為 self.add_error()
方法的第一個參數(shù)是為了將錯誤信息與相應(yīng)字段關(guān)聯(lián)起來,并在前端頁面上正確顯示錯誤信息,提高用戶體驗。
04-創(chuàng)建視圖函數(shù)并編寫視圖函數(shù)
04-1-視圖函數(shù)views.py里的代碼
打開文件 E:\Python_project\P_001\myshop-test\mall_backend\users\views.py 寫入下面的代碼B:
from django.shortcuts import render
from users.models import MyUser
from users.forms import *
# Create your views here.
def user_reg(request):
if request.method == "GET":
form_obj = UserRegForm()
return render(request, 'shop/user_reg.html', {"form_obj": form_obj})
if request.method == "POST":
form_obj = UserRegForm(request.POST, request.FILES)
if form_obj.is_valid():
uname = request.POST.get("username", '')
users = MyUser.objects.filter(username=uname)
if users:
for user in users:
user_img = user.user_img
info = '用戶已經(jīng)存在'
else:
form_obj.cleaned_data.pop("re_password")
form_obj.cleaned_data["is_staff"] = 1
form_obj.cleaned_data["is_superuser"] = 0 # 非管理員
# 接收頁面?zhèn)鬟f過來的參數(shù),進行用戶新增
user = MyUser.objects.create_user(**form_obj.cleaned_data)
user_img = user.user_img
info = '注冊成功,請登陸'
return render(request, 'shop/user_reg.html', {"form_obj": form_obj, "info": info, "user_img": user_img})
else:
errors = form_obj.errors
print(errors)
return render(request, "shop/user_reg.html", {'form_obj': form_obj, 'errors': errors})
return render(request, 'shop/user_reg.html', {"form_obj": form_obj})
04-2-視圖函數(shù)views.py代碼詳解
①注意:user_reg()并不是一個類,而是一個函數(shù)。
這個函數(shù)的參數(shù)為request,參數(shù)request代表了客戶端發(fā)起的請求。它包含了關(guān)于請求的各種信息,例如用戶提交的表單數(shù)據(jù)、HTTP方法等。
②語句 form_obj = forms.UserRegForm() 是什么意思?
注意:UserRegForm是一個類,這個類是在自己前面新建的文件 “E:\Python_project\P_001\myshop-test\mall_backend\users\forms.py” 中自定義的類,這個類繼承自Django的forms.Form類。
所以這句代碼是創(chuàng)建類UserRegForm的實例化對象form_obj 。
③詳細解釋下語句: return render(request, ‘shop/user_reg.html’, {“form_obj”: form_obj}。
答:當(dāng)你調(diào)用render
函數(shù)時,它用于將一個模板渲染成HTML響應(yīng)并返回給客戶端。這個函數(shù)的第一個參數(shù)是request
對象,第二個參數(shù)是模板的路徑,第三個參數(shù)是一個字典,用于向模板傳遞上下文變量。在這里,第三個參數(shù)不太好理解,詳情見我的另一篇博文,鏈接:https://blog.csdn.net/wenhao_ir/article/details/132501337
在代碼中,render
函數(shù)的目的是渲染名為 'shop/user_reg.html'
的模板,同時傳遞一個名為 form_obj
的變量給模板。讓我詳細解釋一下這段代碼:
-
request
: 這是視圖函數(shù)的第一個參數(shù),代表了客戶端發(fā)起的請求。它包含了關(guān)于請求的各種信息,例如用戶提交的表單數(shù)據(jù)、HTTP方法等。 -
'shop/user_reg.html'
: 這是模板的路徑,告訴Django要使用哪個模板來生成HTML響應(yīng)。 -
{"form_obj": form_obj}
: 這是一個字典,用于傳遞變量給模板。在這里,form_obj
是一個表單實例,通過這個字典將這個表單實例傳遞給了模板。在模板中,你可以通過鍵名form_obj
來訪問這個表單實例,以便在模板中渲染表單的各個字段、錯誤信息等。
總之,render
函數(shù)的第三個參數(shù)是用于向模板傳遞上下文變量的,讓模板能夠使用這些變量來動態(tài)生成HTML內(nèi)容。在這里,你傳遞了一個名為 form_obj
的變量,這個變量在模板中可以被用來渲染注冊表單的各個部分和數(shù)據(jù)。
④能否詳細解釋下代碼B中的代碼:
form_obj = forms.UserRegForm(request.POST, request.FILES)
咱們把03-02中的表單類的代碼記為代碼A,把視圖函數(shù)里的代碼記為代碼B。
當(dāng)你在Django中使用表單時,你需要在視圖函數(shù)中處理用戶提交的數(shù)據(jù)。這個數(shù)據(jù)通常包含在HTTP請求中的POST數(shù)據(jù)中,可能包含用戶在表單中輸入的文本、上傳的文件等。為了處理這些數(shù)據(jù),你需要實例化一個表單對象,并將這些數(shù)據(jù)傳遞給它進行驗證和處理。
在你提到的代碼中,form_obj = forms.UserRegForm(request.POST, request.FILES)
這一行代碼完成了以下操作:
-
forms.UserRegForm
: 這是代碼A中定義的注冊表單的類。通過調(diào)用這個類,你可以創(chuàng)建一個用于處理用戶提交數(shù)據(jù)的表單對象。 -
request.POST
: 這是一個包含用戶在表單中提交的文本數(shù)據(jù)的字典。當(dāng)用戶通過POST方法提交表單時,表單中的文本字段的數(shù)據(jù)會包含在這個字典中。這個參數(shù)將這些POST數(shù)據(jù)傳遞給表單對象。 -
request.FILES
: 這是一個包含用戶在表單中上傳的文件的字典。當(dāng)用戶通過POST方法提交包含文件上傳的表單時,上傳的文件數(shù)據(jù)會包含在這個字典中。這個參數(shù)將這些文件數(shù)據(jù)傳遞給表單對象。request.FILES
中包含的是用戶通過表單上傳的文件的數(shù)據(jù),但這些文件并沒有直接保存在這個字典中。實際上,這些上傳的文件數(shù)據(jù)會被保存在服務(wù)器的臨時文件夾中,然后在需要的時候通過文件句柄進行訪問和處理。
當(dāng)用戶通過表單上傳文件時,這些文件數(shù)據(jù)會被存儲在服務(wù)器上的一個臨時目錄中,通常位于 Django 項目的根目錄下的media
文件夾或者根據(jù)你在 Django 設(shè)置中配置的MEDIA_ROOT
設(shè)置的路徑。臨時文件會在請求處理完成后自動被清理掉。
在你的代碼中,通過request.FILES
參數(shù)傳遞給表單對象后,你可以在表單類中的對應(yīng)字段中訪問這些文件數(shù)據(jù)。比如,在你的UserRegForm
類中,user_img
字段是一個forms.ImageField
類型的字段,它會處理用戶上傳的頭像文件數(shù)據(jù)。
總之,request.FILES
中包含的是上傳文件的數(shù)據(jù)的引用,而文件本身會被存儲在服務(wù)器的臨時目錄中,可以在表單處理過程中進行訪問和處理,然后根據(jù)需要進行持久化保存。
所以,form_obj = forms.UserRegForm(request.POST, request.FILES)
這行代碼創(chuàng)建了一個 UserRegForm
類的實例,用于處理用戶通過POST方法提交的數(shù)據(jù),包括文本字段數(shù)據(jù)和上傳的文件數(shù)據(jù)。這個實例可以用于驗證用戶提交的數(shù)據(jù),并執(zhí)行相關(guān)的處理操作,比如將數(shù)據(jù)保存到數(shù)據(jù)庫中。
⑤能否詳細解釋下代碼B中的代碼: if form_obj.is_valid():
當(dāng)你處理用戶提交的表單數(shù)據(jù)時,其中一個關(guān)鍵的步驟是驗證這些數(shù)據(jù)是否合法和有效。在Django中,你可以使用 is_valid()
方法來檢查表單數(shù)據(jù)是否通過了驗證規(guī)則,以及是否符合字段定義和自定義驗證邏輯。
在你提到的代碼中,form_obj.is_valid()
這一行代碼的含義是檢查用戶提交的數(shù)據(jù)是否有效。這個方法會運行表單類中的所有驗證規(guī)則,包括字段的定義驗證(比如最小長度、最大長度等)、自定義驗證方法以及其他內(nèi)置的驗證規(guī)則。
如果所有的驗證規(guī)則都通過了,is_valid()
方法會返回 True
,表示用戶提交的數(shù)據(jù)是有效的。如果任何一個驗證規(guī)則失敗,is_valid()
方法會返回 False
,并且表單對象會保存驗證失敗的信息,包括錯誤消息和錯誤類型。
因此,在你的代碼中,這個條件 if form_obj.is_valid():
意味著如果用戶提交的數(shù)據(jù)經(jīng)過驗證是有效的,就執(zhí)行接下來的邏輯,比如保存數(shù)據(jù)到數(shù)據(jù)庫。如果驗證失敗,則可以根據(jù)表單對象中的錯誤信息,回顯錯誤消息給用戶,讓用戶進行修正。
總之,form_obj.is_valid()
是用來判斷用戶提交的表單數(shù)據(jù)是否合法的關(guān)鍵方法,它決定了是否繼續(xù)處理表單數(shù)據(jù)或者顯示錯誤消息給用戶。
問:is_valid()方法是怎么知道哪些函數(shù)或方法是驗證規(guī)則的呢?
在Django中,is_valid()
方法通過以下方式來確定哪些函數(shù)或方法是驗證規(guī)則:
-
字段類型和屬性:每個字段在表單類中都有相應(yīng)的字段類型,比如
CharField
、EmailField
、IntegerField
等。這些字段類型定義了默認的驗證規(guī)則,例如長度限制、數(shù)據(jù)類型等。你可以在字段的構(gòu)造函數(shù)中傳遞參數(shù)來自定義這些規(guī)則。 -
內(nèi)置驗證器:Django 提供了一些內(nèi)置的驗證器,你可以在字段的構(gòu)造函數(shù)中使用
validators
參數(shù)來添加。這些驗證器可以是函數(shù)、類方法或自定義的驗證函數(shù),它們會在is_valid()
方法執(zhí)行時被調(diào)用。 -
自定義驗證方法:你可以在表單類中定義自己的驗證方法,這些方法的命名規(guī)則為
clean_<field_name>
,例如clean_username()
。這些方法會在is_valid()
方法執(zhí)行時被自動調(diào)用。 -
clean()
方法:你可以在表單類中定義一個全局的clean()
方法,用于對整個表單的數(shù)據(jù)進行自定義的綜合性驗證。這個方法會在is_valid()
方法執(zhí)行時被調(diào)用。
當(dāng)你調(diào)用 is_valid()
方法時,Django 會遍歷表單類中的所有字段,執(zhí)行這些字段類型定義的默認驗證規(guī)則,調(diào)用與字段相關(guān)的內(nèi)置驗證器,以及執(zhí)行自定義的驗證方法和全局的 clean()
方法。如果任何一個驗證規(guī)則失敗,is_valid()
方法會設(shè)置表單對象的 errors
屬性,記錄錯誤信息。
總之,Django 使用一系列約定和機制來確定驗證規(guī)則,包括字段類型、內(nèi)置驗證器、自定義驗證方法和全局的 clean()
方法。在調(diào)用 is_valid()
方法時,這些規(guī)則會被按順序執(zhí)行,以判斷表單數(shù)據(jù)的有效性。
⑥代碼:uname = request.POST.get(“username”, ‘’),為什么第2個參數(shù)要填一個空字符串?
在代碼B中,uname = request.POST.get("username", '')
這行代碼的作用是從request.POST
字典中獲取鍵為 "username"
的值。如果這個鍵存在,就返回對應(yīng)的值;如果這個鍵不存在,就返回一個默認值,這里是空字符串 ''
。
這種做法的目的是為了防止在訪問字典中不存在的鍵時出現(xiàn)錯誤。如果使用request.POST["username"]
來獲取值,當(dāng) "username"
這個鍵不存在時,會拋出 KeyError
異常,導(dǎo)致程序終止執(zhí)行。而使用 .get()
方法,并且傳遞一個默認值作為第二個參數(shù),可以在鍵不存在時提供一個安全的默認值,避免程序崩潰。
在這個具體情境中,uname
變量用于存儲從用戶提交的表單數(shù)據(jù)中獲取的用戶名。如果用戶在表單中沒有輸入用戶名,那么通過 request.POST.get("username", '')
可以確保 uname
變量始終有一個值,即空字符串,而不會引發(fā)異常。
總之,使用 .get()
方法并提供一個默認值是一種良好的編程習(xí)慣,可以保證在處理字典時不會因為鍵不存在而導(dǎo)致程序崩潰。
⑦代碼:users = MyUser.objects.filter(username=uname) 是什么意思?
在代碼B中,users = MyUser.objects.filter(username=uname)
這行代碼的作用是從數(shù)據(jù)庫中查詢滿足特定條件的用戶數(shù)據(jù)。
具體解釋如下:
-
MyUser
是在數(shù)據(jù)庫模型文件中定義的一個類,它對應(yīng)著數(shù)據(jù)庫中的一張表。這個類包含了與用戶相關(guān)的字段(比如用戶名、密碼、郵箱等)以及方法。 -
MyUser.objects
是一個與數(shù)據(jù)庫交互的管理器(Manager)對象。通過這個管理器,你可以執(zhí)行數(shù)據(jù)庫查詢操作。 -
.filter(username=uname)
是一個查詢過濾條件,它的意思是從MyUser
表中篩選出字段username
值等于uname
變量值的記錄。 -
將查詢結(jié)果賦值給變量
users
。這個變量將包含所有滿足條件的用戶記錄,以查詢集(QuerySet)的形式返回。
所以,users = MyUser.objects.filter(username=uname)
這行代碼的目的是從數(shù)據(jù)庫中檢索所有用戶名等于 uname
變量值的用戶記錄,并將這些記錄存儲在 users
變量中,以供后續(xù)處理和使用。
⑧代碼:form_obj.cleaned_data.pop(“re_password”)是什么意思?
在代碼B中,form_obj.cleaned_data.pop("re_password")
這行代碼的作用是從表單的清理數(shù)據(jù)(cleaned_data)中移除一個特定的字段。
解釋如下:
-
form_obj
: 這是一個表單對象,它包含了用戶提交的數(shù)據(jù),并經(jīng)過了驗證和清理處理。 -
.cleaned_data
: 這是一個字典,包含了已經(jīng)通過了驗證并被清理過的數(shù)據(jù)。這些數(shù)據(jù)可以用于后續(xù)的處理,比如保存到數(shù)據(jù)庫。 -
.pop("re_password")
: 這是對字典的操作,用于從字典中移除一個特定的鍵(key)及其對應(yīng)的值(value)。在這里,"re_password"
是一個鍵,表示確認密碼字段,這行代碼的目的是將確認密碼字段從cleaned_data
字典中移除。
通常情況下,確認密碼字段不會被保存到數(shù)據(jù)庫,所以在將表單數(shù)據(jù)保存到數(shù)據(jù)庫之前,可能會需要將確認密碼字段從 cleaned_data
中移除,以避免將這個字段保存到數(shù)據(jù)庫中。
總之,form_obj.cleaned_data.pop("re_password")
這行代碼的作用是從表單的清理數(shù)據(jù)中移除確認密碼字段,以準(zhǔn)備將其余數(shù)據(jù)保存到數(shù)據(jù)庫中。
⑨代碼:user = MyUser.objects.create_user(**form_obj.cleaned_data)
中的參數(shù)form_obj.cleaned_data前面的兩個“**”是什么意思?
在Python中,**
是一種特殊的語法,用于將一個字典的內(nèi)容解包(unpack)并作為關(guān)鍵字參數(shù)傳遞給函數(shù)。在這行代碼中,**form_obj.cleaned_data
的作用是將 form_obj.cleaned_data
這個字典中的內(nèi)容解包,并作為關(guān)鍵字參數(shù)傳遞給 MyUser.objects.create_user
函數(shù)。
具體解釋如下:
-
form_obj.cleaned_data
: 這是一個字典,包含了經(jīng)過驗證和清理處理后的表單數(shù)據(jù)。每個字段的名稱都是鍵,對應(yīng)的用戶輸入數(shù)據(jù)是值。 -
**
: 這是解包操作符,用于將字典中的內(nèi)容解包并作為關(guān)鍵字參數(shù)傳遞給函數(shù)。 -
MyUser.objects.create_user
: 這是一個用于創(chuàng)建用戶的方法。它通常是在Django的用戶認證系統(tǒng)中的用戶模型(例如User
或MyUser
)中定義的一個方法,用于創(chuàng)建新的用戶記錄。
所以,MyUser.objects.create_user(**form_obj.cleaned_data)
這行代碼的意思是,將經(jīng)過驗證和清理的表單數(shù)據(jù)作為關(guān)鍵字參數(shù)傳遞給 create_user
方法,以便用這些數(shù)據(jù)來創(chuàng)建一個新的用戶記錄。
總之,**form_obj.cleaned_data
是一種用于將字典內(nèi)容解包的語法,用于方便地將字典的鍵值對作為關(guān)鍵字參數(shù)傳遞給函數(shù)。
⑩能否詳細解釋下代碼:user = MyUser.objects.create_user(**form_obj.cleaned_data)
。
,user = MyUser.objects.create_user(**form_obj.cleaned_data)
這行代碼的含義是創(chuàng)建一個新的 MyUser
記錄,并使用從表單中清理過的數(shù)據(jù)填充各個字段。
讓我詳細解釋這段代碼的邏輯:
-
MyUser.objects
: 這是與MyUser
模型(數(shù)據(jù)庫表)進行交互的管理器(Manager)對象。 -
.create_user
: 這是一個自定義的方法,它通常在 Django 的用戶認證系統(tǒng)中的用戶模型類中定義,用于創(chuàng)建新的用戶記錄。在你提供的代碼中,MyUser
類繼承了AbstractUser
,所以它繼承了create_user
方法。 -
**form_obj.cleaned_data
: 這部分使用了解包操作符**
,將經(jīng)過驗證和清理的表單數(shù)據(jù)解包并作為關(guān)鍵字參數(shù)傳遞給create_user
方法。因為form_obj.cleaned_data
是一個字典,它包含了經(jīng)過驗證的表單字段及其對應(yīng)的值。
所以,user = MyUser.objects.create_user(**form_obj.cleaned_data)
的意思是:使用從表單中清理過的數(shù)據(jù)創(chuàng)建一個新的 MyUser
記錄。這將把用戶提交的表單數(shù)據(jù)填充到 MyUser
模型的各個字段中,并創(chuàng)建一個新的用戶記錄。
總之,這行代碼是在數(shù)據(jù)庫中創(chuàng)建一個新的用戶記錄,并將表單中的數(shù)據(jù)應(yīng)用于相應(yīng)的字段。
11 代碼 user_img = user.user_img 的user_img是用戶頭像路徑嗎?
答:不是,user_img只是數(shù)據(jù)庫模型MyUser的頭像字段ImageFieldFile的一個對象,它代表數(shù)據(jù)庫查詢的QuerySet,如果要獲取用戶的頭像的上傳路徑,要用下面的代碼:
user_img_path = user.user_img.url
即通過 .url 屬性可以獲取頭像上傳路徑。
所以這句代碼是存疑的。
12 最后一個return語句: return render(request, 'shop/user_reg.html', {"form_obj": form_obj})
是什么意思?
答:在POST請求方法中,不管哪種情況,最終都要再次顯示顯示表單填寫頁面。
05-模板文件user_reg.html
05-01-注冊模板目錄
打開文件:
E:\Python_project\P_001\myshop-test\mall_backend\mall_backend\settings.py
找到配置選項“TEMPLATES”,然后將代碼
'DIRS': [],
修改為:
'DIRS': [os.path.join(BASE_DIR, 'templates')],
由于上面這句代碼用到了os庫,所以還需要在 settings.py 中導(dǎo)入該庫:
import os
05-02-配置模板文件user_reg.html需要的Bootstrap靜態(tài)文件
01-創(chuàng)建路徑 E:\Python_project\P_001\myshop-test\mall_backend\static\other\css\ 所需的相關(guān)目錄。
02-然后下載Bootstrap的包“bootstrap-4.5.3-dist.zip”,
官網(wǎng)下載方法請參考博文: https://blog.csdn.net/wenhao_ir/article/details/132089650
百度網(wǎng)盤下載鏈接:https://pan.baidu.com/s/14BM9gpC3K-LKxhyLGh4J9Q?pwd=m02m
下載完成后解壓,把css文件夾下的文件“bootstrap.min.css”和文件“bootstrap.min.css.map”都復(fù)制到目錄:E:\Python_project\P_001\myshop-test\mall_backend\static\other\css\ 中。
關(guān)于映射文件“bootstrap.min.css.map”有什么用,請參考下面兩篇文章:
文章01 https://blog.csdn.net/wenhao_ir/article/details/132090746
文章02 https://blog.csdn.net/wenhao_ir/article/details/132152980
05-03-注冊靜態(tài)文件目錄
打開文件:
E:\Python_project\P_001\myshop-test\mall_backend\mall_backend\settings.py
找到代碼:
STATIC_URL = '/static/'
將其替換為下面三句代碼:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '/static')
問:
代碼:
STATICFILES_DIRS = [os.path.join(BASE_DIR, ‘static’)]
與代碼:
STATIC_ROOT = os.path.join(BASE_DIR, ‘/static’)
有什么區(qū)別?
答:這兩行代碼有不同的目的和用途,它們分別用于不同情況下的靜態(tài)文件配置。
-
STATICFILES_DIRS:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
這行代碼配置了一個列表,其中包含了其他應(yīng)用或項目級別的靜態(tài)文件目錄。
os.path.join(BASE_DIR, 'static')
表示將項目根目錄下的static
文件夾加入到靜態(tài)文件查找路徑中。這個配置用于指定除了應(yīng)用內(nèi)部的靜態(tài)文件目錄之外的其他靜態(tài)文件目錄。在這個列表中的目錄會被用于開發(fā)環(huán)境中的靜態(tài)文件查找,而不會被用于生產(chǎn)環(huán)境的靜態(tài)文件收集(即不會被collectstatic
命令收集到STATIC_ROOT
目錄中)。 -
STATIC_ROOT:
STATIC_ROOT = os.path.join(BASE_DIR, '/static')
這行代碼定義了一個目錄,用于在生產(chǎn)環(huán)境中收集所有靜態(tài)文件。
STATIC_ROOT
是一個絕對路徑,指定了一個位置,collectstatic
命令會將所有應(yīng)用和項目中的靜態(tài)文件收集到這個目錄中,以便在生產(chǎn)環(huán)境中統(tǒng)一提供靜態(tài)文件的服務(wù)。這個目錄應(yīng)該是你部署服務(wù)器上的一個真實路徑。
在總體架構(gòu)上,STATICFILES_DIRS
用于開發(fā)環(huán)境中的靜態(tài)文件查找,而 STATIC_ROOT
用于生產(chǎn)環(huán)境中的靜態(tài)文件收集。這兩個設(shè)置在功能上是不同的,它們的目標(biāo)是為了在不同的環(huán)境中處理靜態(tài)文件。
問:代碼STATIC_URL = '/static/'
有什么用?
在Django的settings.py
文件中,STATIC_URL
是一個用于設(shè)置靜態(tài)文件的URL前綴的配置項。它定義了瀏覽器訪問靜態(tài)文件的基本URL路徑。在你的代碼中,STATIC_URL
被設(shè)置為'/static/'
。
這意味著當(dāng)你在HTML模板或Django視圖中引用靜態(tài)文件(例如CSS、JavaScript、圖像等),Django將使用這個URL前綴來構(gòu)建靜態(tài)文件的URL。例如,如果你有一個名為style.css
的CSS文件,并且STATIC_URL
被設(shè)置為'/static/'
,那么在模板中引用這個文件時,你可以這樣做:
<link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
Django會將{% static 'style.css' %}
轉(zhuǎn)換為/static/style.css
,這是瀏覽器請求靜態(tài)文件的URL。所以,STATIC_URL
定義了靜態(tài)文件的基本URL路徑,讓你可以方便地引用這些文件,而不需要硬編碼整個URL。這使得你的應(yīng)用更加靈活和可維護,因為你可以輕松地更改STATIC_URL
而不必修改所有靜態(tài)文件的引用。
05-02-創(chuàng)建模板文件user_reg.html,并寫入代碼
創(chuàng)建文件 E:\Python_project\P_001\myshop-test\mall_backend\templates\shop\user_reg.html
然后寫入下面的代碼:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>頁面標(biāo)題:用戶注冊</title>
<link rel="stylesheet" href="{% static 'other/css/bootstrap.min.css' %}">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-2">
<div class="page-header">
<h2>用戶注冊</h2>
</div>
<form novalidate action="" method="post" enctype="multipart/form-data" class="form-horizontal">
{% csrf_token %}
<div class="form-group">
<label for="{{form_obj.username.id_for_label}}" class="col-sm-2">{{form_obj.username.label}}</label>
<div class="col-sm-8">{{form_obj.username}}
<span class="help-block">{{ form_obj.errors.username.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{form_obj.password.id_for_label}}" class="col-sm-2">{{form_obj.password.label}}</label>
<div class="col-sm-8">{{form_obj.password}}
<span class="help-block">{{ form_obj.errors.password.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{form_obj.re_password.id_for_label}}" class="col-sm-2">{{form_obj.re_password.label}}</label>
<div class="col-sm-8">{{form_obj.re_password}}
<span class="help-block">{{ form_obj.errors.re_password.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{form_obj.nickname.id_for_label}}" class="col-sm-2">{{form_obj.nickname.label}}</label>
<div class="col-sm-8">{{form_obj.nickname}}
<span class="help-block">{{ form_obj.errors.nickname.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{form_obj.nickname.id_for_label}}" class="col-sm-2">{{form_obj.email.label}}</label>
<div class="col-sm-8">{{form_obj.email}}
<span class="help-block">{{ form_obj.errors.email.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{form_obj.nickname.id_for_label}}" class="col-sm-2">{{form_obj.mobile.label}}</label>
<div class="col-sm-8">{{form_obj.mobile}}
<span class="help-block">{{ form_obj.errors.mobile.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{form_obj.nickname.id_for_label}}" class="col-sm-2">{{form_obj.user_img.label}}</label>
<div class="col-sm-8">{{form_obj.user_img}}
<span class="help-block"></span>
</div>
<img src="/media/{{ user_img }}">
</div>
<div class="col-8">
<label for="agreeTerms">
{{ info }}
</label>
</div>
<div class="form-group">
<div class="col-sm-10">
<input type="submit" class="btn btn-success" value="用戶注冊">
<a href="/users/login/" class="btn btn-success">用戶登錄</a>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
05-03-模板文件user_reg.html代碼詳解
01 {% load static %}是什么意思?{% load static %}
是 Django 模板語言的標(biāo)簽,用于加載靜態(tài)文件(如樣式表、JavaScript 文件等)。它告訴 Django 模板引擎在當(dāng)前模板中啟用靜態(tài)文件的處理,以便能夠正確地引用靜態(tài)文件路徑。
當(dāng)你在Django模板中使用 {% load static %}
標(biāo)簽時,它會通知Django模板引擎去處理與靜態(tài)文件相關(guān)的操作。這包括了為靜態(tài)文件生成正確的URL路徑,以便在模板中正確引用這些文件。
有了上面這句模板語言的聲明后,當(dāng)模板引擎看到 {% static %}
標(biāo)簽時,它會根據(jù)對靜態(tài)文件的設(shè)置生成一個完整的路徑,使你能夠在HTML代碼中引用靜態(tài)文件。
在上面的靜態(tài)文件路徑設(shè)置中,用了下面三條語句:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '/static')
設(shè)置了上面三條語句后,如果在你的代碼片段中有下面這一行:
<link rel="stylesheet" href="{% static 'other/css/bootstrap.min.css' %}">
那么{% static 'other/css/bootstrap.min.css' %}
會根據(jù)在settting.py中設(shè)置的靜態(tài)目錄的路徑分兩步
進行路徑:
第1步:根據(jù)STATIC_URL = '/static/'
將路徑解析為:/static/other/css/bootstrap.min.css
第2步:根據(jù)STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
【這一句用于調(diào)試開發(fā)環(huán)境】或STATIC_ROOT = os.path.join(BASE_DIR, '/static')
【這一句用于生產(chǎn)部署環(huán)境】,將路徑中的/static/
替換為E:\Python_project\P_001\myshop-test\mall_backend\static\
,最終得到完整的E:\Python_project\P_001\myshop-test\mall_backend\static\other\css\bootstrap.min.css
總之,通過在模板中使用 {% load static %}
標(biāo)簽和 {% static %}
標(biāo)簽,你可以確保在Django項目中正確處理和引用靜態(tài)文件,使你的網(wǎng)頁可以正確加載樣式、腳本和其他靜態(tài)資源。
02 為什么通過語句 將語言設(shè)置為英文,但是仍然可以有中文字符?
答:在代碼中,通過語句 <html lang="en">
設(shè)置了頁面的主要語言為英文,但是仍然可以在頁面中包含中文字符,這是因為 <html lang="en">
標(biāo)簽只是一種聲明,它向瀏覽器和搜索引擎指示頁面的主要語言是英文,以便它們能夠正確地對頁面進行處理和顯示。
然而,這并不意味著頁面只能包含英文內(nèi)容。HTML 中的語言設(shè)置主要是為了支持瀏覽器和搜索引擎的語言處理、搜索和優(yōu)化。你仍然可以在頁面中包含其他語言(如中文)的內(nèi)容,而不會影響頁面的顯示。
實際上,在網(wǎng)頁中,你可以同時使用多種語言,這對于國際化和多語言支持的網(wǎng)站是很常見的。瀏覽器可以根據(jù)內(nèi)容自動調(diào)整顯示的語言,同時搜索引擎也能夠正確地處理多種語言的內(nèi)容。
所以,盡管你在代碼中設(shè)置了 <html lang="en">
,但是這并不妨礙你在頁面中使用中文字符或其他語言的內(nèi)容。這個設(shè)置更多地是為了提供一種指示,以幫助瀏覽器和搜索引擎更好地處理你的網(wǎng)頁。
值得注意的是,雖然在網(wǎng)頁中設(shè)置 <html lang="en">
可以幫助瀏覽器和搜索引擎更好地理解和處理網(wǎng)頁內(nèi)容的語言,但并不是必需的。許多網(wǎng)頁在實際開發(fā)中可能會省略 <html lang>
設(shè)置,特別是當(dāng)網(wǎng)頁內(nèi)容包含多種語言時。
在現(xiàn)代的網(wǎng)頁開發(fā)中,瀏覽器和搜索引擎已經(jīng)變得足夠智能,能夠自動識別和適應(yīng)多種語言的內(nèi)容。這意味著,即使你不設(shè)置 <html lang>
,瀏覽器仍然可以正確地顯示多語言內(nèi)容,并且搜索引擎也可以適當(dāng)?shù)靥幚砟愕木W(wǎng)頁。
03-代碼<link rel="stylesheet" href="{% static 'other/css/bootstrap.min.css' %}">
中的參數(shù)rel是什么英文的縮寫?代表什么意思?
詳情和答案見博文:https://blog.csdn.net/wenhao_ir/article/details/132091300
04-如何徹底理解模板文件user_reg.html中的各種Bootstrap的前端樣式?
答:沒有捷徑,只有認真系統(tǒng)的學(xué)習(xí)一次bootstrap,所以本篇博文對于模板文件user_reg.htm中的各種Bootstrap前端樣式不作展開介紹。
04-Bootstrap的類col-md-offset-2是什么效果?
在 Bootstrap 3 中,col-md-offset-2
是用來創(chuàng)建柵格偏移(grid offset)的類。它的作用是在大屏幕(medium-sized devices)上將列(column)向右偏移兩個列寬的位置。這個偏移可以用來調(diào)整列的位置,以實現(xiàn)更復(fù)雜的布局。
具體來說,Bootstrap 使用一個12列的柵格系統(tǒng),其中 col-md-
類用于定義列的寬度,而 col-md-offset-
類用于定義列的偏移量。所以,col-md-offset-2
將列向右偏移兩個列的寬度,等于 16.6667% * 2 * 100% = 33.3334% 的寬度。
以下是一個示例,展示了如何在 Bootstrap 3 中使用 col-md-offset-2
:
<div class="container">
<div class="row">
<div class="col-md-2">左側(cè)內(nèi)容</div>
<div class="col-md-offset-2 col-md-8">這個列向右偏移了兩個列的寬度,然后占據(jù)了8個列的寬度</div>
</div>
</div>
在上面的示例中,第一個列占據(jù)了兩個列的寬度,而第二個列使用 col-md-offset-2
偏移了兩個列的寬度,然后占據(jù)了剩余的八個列的寬度,實現(xiàn)了一個復(fù)雜的布局效果。
05-代碼 <form novalidate action="" method="post" enctype="multipart/form-data" class="form-horizontal">
詳解。
問: 關(guān)鍵詞 novalidate 是什么意思?
詳見博文 https://blog.csdn.net/wenhao_ir/article/details/132488987
問:action=""是什么意思?
詳見博文 https://blog.csdn.net/wenhao_ir/article/details/132488987
問:enctype=“multipart/form-data” 是什么意思?
詳見博文 https://blog.csdn.net/wenhao_ir/article/details/132488987
06-代碼 <label for="{{form_obj.username.id_for_label}}" class="col-sm-2">{{form_obj.username.label}}</label>
詳解一下。
要理解這句代碼,關(guān)鍵是理解label標(biāo)簽和對象form_obj,關(guān)于label標(biāo)簽,請參考博文 https://blog.csdn.net/wenhao_ir/article/details/132500712
當(dāng)然,實際上上面這句代碼實際上并不需要設(shè)置這個for屬性,因為并無別的HTML元素與其聯(lián)系。
而對象form_obj,請參閱視圖函數(shù)代碼中關(guān)于函數(shù)render()的代碼,而關(guān)于函數(shù)函數(shù)render()的詳解,請參閱博文:https://blog.csdn.net/wenhao_ir/article/details/132501337
另外還要問“在HTML板模中的“{{form_obj.username.id_for_label}}”和“{{form_obj.username.label}}”得到的結(jié)果有什么不同?”
回答:在Django中,{{ form_obj.username.id_for_label }}
和 {{ form_obj.username.label }}
都用于獲取表單字段 username
的標(biāo)簽信息,但它們有一些不同之處:
-
{{ form_obj.username.id_for_label }}
:
這將生成一個用于關(guān)聯(lián)標(biāo)簽和表單字段的 HTMLid
屬性的值。通常情況下,這個值會與表單字段的id
屬性相同,用于確保標(biāo)簽與相應(yīng)的輸入字段建立關(guān)聯(lián)。在你的示例中,你定義了一個自定義的表單字段username
,但沒有顯式指定id
屬性,所以Django會自動生成一個唯一的id
值。這個值可以用于在HTML中編寫自定義的標(biāo)簽,以及用于與輸入字段建立關(guān)聯(lián)。示例用法:
<label for="{{ form_obj.username.id_for_label }}">Username:</label>
-
{{ form_obj.username.label }}
:
這將返回字段的標(biāo)簽文本,即"用戶名"。這是你在表單類中通過label
參數(shù)指定的標(biāo)簽文本。這通常用于直接輸出標(biāo)簽文本,而不需要手動指定關(guān)聯(lián)的id
屬性。示例用法:
<label>{{ form_obj.username.label }}</label>
總的來說,{{ form_obj.username.id_for_label }}
主要用于關(guān)聯(lián)標(biāo)簽和輸入字段,而 {{ form_obj.username.label }}
用于直接獲取標(biāo)簽文本。具體的用法取決于你在HTML模板中的需求。如果你需要在HTML中自定義標(biāo)簽,并且需要關(guān)聯(lián)標(biāo)簽和輸入字段,那么你可以使用 {{ form_obj.username.id_for_label }}
。如果你只需要顯示標(biāo)簽文本,那么 {{ form_obj.username.label }}
就足夠了。
07-代碼<span class="help-block">{{ form_obj.errors.username.0 }}</span>
解釋一下吧。
關(guān)于span標(biāo)簽的介紹,請參見博文:https://blog.csdn.net/wenhao_ir/article/details/132502816
form_obj.errors.username.0
的介紹,如下:
關(guān)于對象form_obj,請參閱視圖函數(shù)代碼中關(guān)于函數(shù)render()的代碼,而關(guān)于函數(shù)函數(shù)render()的詳解,請參閱博文:https://blog.csdn.net/wenhao_ir/article/details/132501337
在 Django 的表單處理中,form_obj.errors
是一個包含表單驗證錯誤信息的字典。這個字典以表單字段為鍵,對應(yīng)的值是一個列表,列表中包含了與該字段相關(guān)的所有錯誤。這些錯誤通常會在用戶提交表單時進行驗證,例如,如果用戶名字段為空,那么就會產(chǎn)生一個與用戶名字段相關(guān)的錯誤。
在你的代碼A中,{{ form_obj.errors.username.0 }}
這部分的含義是:
-
form_obj.errors
: 表示獲取表單對象form_obj
中的錯誤信息字典。 -
.username
: 表示從錯誤字典中獲取與用戶名字段相關(guān)的錯誤列表。 -
.0
: 表示獲取該錯誤列表的第一個元素。
所以,{{ form_obj.errors.username.0 }}
的意思是從表單對象的錯誤字典中獲取用戶名字段的第一個錯誤信息。如果你的表單驗證中出現(xiàn)了多個關(guān)于用戶名字段的錯誤,這將會獲取第一個錯誤。如果沒有錯誤,它將不會顯示任何內(nèi)容。
例如,假設(shè)用戶沒有填寫用戶名字段,那么在驗證表單時會產(chǎn)生一個錯誤,該錯誤信息會被存儲在 form_obj.errors.username
列表中的第一個位置。你可以使用 {{ form_obj.errors.username.0 }}
來在模板中顯示這個錯誤信息,以便向用戶指出出現(xiàn)的問題。
06-配置URL請求路徑(配置路由)
打開文件"E:\Python_project\P_001\myshop-test\mall_backend\mall_backend\urls.py"
寫入下面的代碼:
from django.contrib import admin
from django.urls import path
from users import views
urlpatterns = [
path('user_reg/', views.user_reg),
]
07-配置數(shù)據(jù)庫
第01步:在文件:"E:\Python_project\P_001\myshop-test\mall_backend\mall_backend\settings.py"中寫入以下數(shù)據(jù)庫的配置信息:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mall-backend',
'USER': 'mall-backend',
'PASSWORD': 'swh123456',
'HOST': 'localhost',
'PORT': '3306',
# 取消外鍵約束,否則多對多模型遷移報django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')
'OPTIONS': {
"init_command": "SET foreign_key_checks = 0;",
'charset': 'utf8'
},
}
}
第02步:在mysql中按上面的信息創(chuàng)建數(shù)據(jù)庫 mall-backend:
第03步:生成數(shù)據(jù)庫的遷移執(zhí)行文件
CD E:\Python_project\P_001\myshop-test\mall_backend
E:
manage.py makemigrations
第04步:執(zhí)行數(shù)據(jù)庫遷移模型
CD E:\Python_project\P_001\myshop-test\mall_backend
E:
manage.py migrate
此時,可以查看下數(shù)據(jù)庫中是否有相關(guān)的表了:
08-運行應(yīng)用
CD E:\Python_project\P_001\myshop-test\mall_backend
E:
python manage.py runserver 127.0.0.1:8010
09-訪問URL路徑測試有無問題
根據(jù):“E:\My_Data\0072-Django教材源碼\myshop-back\apps\users\urls.py” 設(shè)置的URL。
應(yīng)該訪問下面這個URL:
http://127.0.0.1:8010/user_reg/
運行效果如下:
注冊一個用戶試下:
點用注冊后數(shù)據(jù)庫中出現(xiàn)了下面這條記錄:文章來源:http://www.zghlxwxcb.cn/news/detail-736403.html
10-項目打包源文件
鏈接:https://pan.baidu.com/s/1BgQ3aH3OQs2vALgq7wd67w?pwd=rubw 文章來源地址http://www.zghlxwxcb.cn/news/detail-736403.html
到了這里,關(guān)于用前端框架Bootstrap和Django實現(xiàn)用戶注冊頁面的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!