12.Django基礎十之Form和ModelForm組件

来源:https://www.cnblogs.com/changxin7/archive/2019/10/02/11616775.html
-Advertisement-
Play Games

一 Form介紹 我們之前在HTML頁面中利用form表單向後端提交數據時,都會寫一些獲取用戶輸入的標簽並且用form標簽把它們包起來。 與此同時我們在好多場景下都需要對用戶的輸入做校驗,比如校驗用戶是否輸入,輸入的長度和格式等正不正確。如果用戶輸入的內容有錯誤就需要在頁面上相應的位置顯示對應的錯誤 ...


一 Form介紹

  

  我們之前在HTML頁面中利用form表單向後端提交數據時,都會寫一些獲取用戶輸入的標簽並且用form標簽把它們包起來。

  與此同時我們在好多場景下都需要對用戶的輸入做校驗,比如校驗用戶是否輸入,輸入的長度和格式等正不正確。如果用戶輸入的內容有錯誤就需要在頁面上相應的位置顯示對應的錯誤信息.。

  Django form組件就實現了上面所述的功能。

  總結一下,其實form組件的主要功能如下:

    生成頁面可用的HTML標簽

    對用戶提交的數據進行校驗

    保留上次輸入內容

  

普通方式手寫註冊功能

views.py

# 註冊
def register(request):
    error_msg = ""
    if request.method == "POST":
        username = request.POST.get("name")
        pwd = request.POST.get("pwd")
        # 對註冊信息做校驗
        if len(username) < 6:
            # 用戶長度小於6位
            error_msg = "用戶名長度不能小於6位"
        else:
            # 將用戶名和密碼存到資料庫
            return HttpResponse("註冊成功")
    return render(request, "register.html", {"error_msg": error_msg})

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊頁面</title>
</head>
<body>
<form action="/reg/" method="post">
    {% csrf_token %}
    <p>
        用戶名:
        <input type="text" name="name">
    </p>
    <p>
        密碼:
        <input type="password" name="pwd">
    </p>
    <p>
        <input type="submit" value="註冊">
        <p style="color: red">{{ error_msg }}</p>
    </p>
</form>
</body>
</html>

使用form組件實現註冊功能

views.py

      先定義好一個RegForm類:

from django import forms

# 按照Django form組件的要求自己寫一個類
class RegForm(forms.Form):
    name = forms.CharField(label="用戶名")  #form欄位的名稱寫的是什麼,那麼前端生成input標簽的時候,input標簽的name屬性的值就是什麼
    pwd = forms.CharField(label="密碼")

      再寫一個視圖函數:

# 使用form組件實現註冊方式
def register2(request):
    form_obj = RegForm()
    if request.method == "POST":
        # 實例化form對象的時候,把post提交過來的數據直接傳進去
        form_obj = RegForm(data=request.POST)  #既然傳過來的input標簽的name屬性值和form類對應的欄位名是一樣的,所以接過來後,form就取出對應的form欄位名相同的數據進行form校驗
        # 調用form_obj校驗數據的方法
        if form_obj.is_valid():
            return HttpResponse("註冊成功")
    return render(request, "register2.html", {"form_obj": form_obj})

login2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊2</title>
</head>
<body>
    <form action="/reg2/" method="post" novalidate autocomplete="off">  #novalidate 告訴前端form表單,不要對輸入的內容做校驗
        {% csrf_token %}        #{{ form_obj.as_p }}  直接寫個這個,下麵的用戶名和密碼的標簽不自己寫,你看看效果
        <div>
            <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
            {{ form_obj.name }} {{ form_obj.name.errors.0 }}  #errors是這個欄位所有的錯誤,我就用其中一個錯誤提示就可以了,再錯了再提示,並且不是給你生成ul標簽了,單純的是錯誤文本           {{ form_obj.errors }} #這是全局的所有錯誤,找對應欄位的錯誤,就要form_obj.欄位名
        </div>
        <div>
            <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
            {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
        </div>
        <div>
            <input type="submit" class="btn btn-success" value="註冊">
        </div>
    </form>
</body>
</html>

    看網頁效果發現 也驗證了form的功能:
      前端頁面是form類的對象生成的 -->生成HTML標簽功能
      當用戶名和密碼輸入為空或輸錯之後 頁面都會提示 -->用戶提交校驗功能
      當用戶輸錯之後 再次輸入 上次的內容還保留在input框 -->保留上次輸入內容

二 Form常用欄位與插件

  

  創建Form類時,主要涉及到 【欄位】 和 【插件】,欄位用於對用戶請求數據的驗證,插件用於自動生成HTML;

initial

    初始值,input框裡面的初始值。

class LoginForm(forms.Form):
    username = forms.CharField(  
        min_length=8,
        label="用戶名",
        initial="張三"  # 設置預設值
    )
    pwd = forms.CharField(min_length=6, label="密碼")

error_messages

    重寫錯誤信息。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")

password

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密碼",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True) #這個密碼欄位和其他欄位不一樣,預設在前端輸入數據錯誤的時候,點擊提交之後,預設是不保存的原來數據的,但是可以通過這個render_value=True讓這個欄位在前端保留用戶輸入的數據
    )

radioSelect

    單radio值為字元串

class LoginForm(forms.Form):
    username = forms.CharField(  #其他選擇框或者輸入框,基本都是在這個CharField的基礎上通過插件來搞的
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性別",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

單選Select

class LoginForm(forms.Form):
    ...
    hobby = forms.fields.ChoiceField(  #註意,單選框用的是ChoiceField,並且裡面的插件是Select,不然驗證的時候會報錯, Select a valid choice的錯誤。
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=3,
        widget=forms.widgets.Select()
    )

多選Select

class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField( #多選框的時候用MultipleChoiceField,並且裡面的插件用的是SelectMultiple,不然驗證的時候會報錯。
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

單選checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.fields.ChoiceField(
        label="是否記住密碼",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

  單選checkbox示例:

#單選的checkbox
    class TestForm2(forms.Form):
        keep = forms.ChoiceField(
            choices=(
                ('True',1),
                ('False',0),
            ),

            label="是否7天內自動登錄",
            initial="1",
            widget=forms.widgets.CheckboxInput(), 
        )
    選中:'True'   #form只是幫我們做校驗,校驗選擇內容的時候,就是看在沒在我們的choices裡面,裡面有這個值,表示合法,沒有就不合法
    沒選中:'False'
    ---保存到資料庫裡面  keep:'True'
    if keep == 'True':
        session 設置有效期7天
    else:
        pass

多選checkbox

class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

date類型

from django import forms
from django.forms import widgets
class BookForm(forms.Form):
    date = forms.DateField(widget=widgets.TextInput(attrs={'type':'date'}))  #必須指定type,不然不能渲染成選擇時間的input框

choice欄位註意事項

    在使用選擇標簽時,需要註意choices的選項可以配置從資料庫中獲取,但是由於是靜態欄位 獲取的值無法實時更新,需要重寫構造方法從而實現choice實時更新。

    方式一:

from django.forms import Form
from django.forms import widgets
from django.forms import fields

 
class MyForm(Form):
 
    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )
 
    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs) #註意重寫init方法的時候,*args和**kwargs一定要給人家寫上,不然會出問題,並且驗證總是不能通過,還不顯示報錯信息
        # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
        # 或
        self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')

    方式二:

from django import forms
from django.forms import fields
from django.forms import models as form_model

 
class FInfo(forms.Form):  
    authors = forms.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多選    #或者下麵這種方式,通過forms裡面的models中提供的方法也是一樣的。
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多選
    #authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 單選    #或者,forms.ModelChoiceField(queryset=models.Publisth.objects.all(),widget=forms.widgets.Select()) 單選    #
   authors = forms.ModelMultipleChoiceField(    queryset=models.Author.objects.all(),    widget = forms.widgets.Select(attrs={'class': 'form-control'}   ))
   #如果用這種方式,別忘了model表中,NNEWType的__str__方法要寫上,不然選擇框裡面是一個個的object對象

 

三 Form所有內置欄位

內置欄位:

Field
    required=True,               是否允許為空
    widget=None,                 HTML插件
    label=None,                  用於生成Label標簽或顯示內容
    initial=None,                初始值
    help_text='',                幫助信息(在標簽旁邊顯示)
    error_messages=None,         錯誤信息 {'required': '不能為空', 'invalid': '格式錯誤'}
    validators=[],               自定義驗證規則
    localize=False,              是否支持本地化
    disabled=False,              是否可以編輯
    label_suffix=None            Label內容尾碼
 
 
CharField(Field)
    max_length=None,             最大長度
    min_length=None,             最小長度
    strip=True                   是否移除用戶輸入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             總長度
    decimal_places=None,         小數位長度
 
BaseTemporalField(Field)
    input_formats=None          時間格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            時間間隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定製正則表達式
    max_length=None,            最大長度
    min_length=None,            最小長度
    error_message=None,         忽略,錯誤信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允許空文件
 
ImageField(FileField)      
    ...
    註:需要PIL模塊,pip3 install Pillow
    以上兩個字典使用時,需要註意兩點:
        - form表單中 enctype="multipart/form-data"
        - view函數中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                選項,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,預設select插件
    label=None,                Label內容
    initial=None,              初始值
    help_text='',              幫助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查詢資料庫中的數據
    empty_label="---------",   # 預設空顯示內容
    to_field_name=None,        # HTML中value的值對應的欄位
    limit_choices_to=None      # ModelForm中對queryset二次篩選
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   對選中的值進行一次轉換
    empty_value= ''            空值的預設值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   對選中的每一個值進行一次轉換
    empty_value= ''            空值的預設值
 
ComboField(Field)
    fields=()                  使用多個驗證,如下:即驗證最大長度20,又驗證郵箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象類,子類中可以實現聚合多個字典去匹配一個值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件選項,目錄下文件顯示在頁面中
    path,                      文件夾路徑
    match=None,                正則匹配
    recursive=False,           遞歸下麵的文件夾
    allow_files=True,          允許文件
    allow_folders=False,       允許文件夾
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1時候,可解析為192.0.2.1, PS:protocol必須為both才能啟用
 
SlugField(CharField)           數字,字母,下劃線,減號(連字元)
    ...
 
UUIDField(CharField)           uuid類型
複製代碼

四 欄位校驗

RegexValidator驗證器

from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')],
    )

自定義驗證函數

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定義驗證規則
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 PublishForm(Form):
 
 
    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': '標題不能為空',
                                            'min_length': '標題最少為5個字元',
                                            'max_length': '標題最多為20個字元'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': '標題5-20個字元'}))
 
 
    # 使用自定義驗證規則
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={'required': '手機不能為空'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手機號碼'}))
 
    email = fields.EmailField(required=False,
                            error_messages={'required': u'郵箱不能為空','invalid': u'郵箱格式錯誤'},
                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'}))

五 Hook鉤子方法

  除了上面兩種方式,我們還可以在Form類中定義鉤子函數,來實現自定義的驗證功能。

局部鉤子

    我們在Fom類中定義 clean_欄位名() 方法,就能夠實現對特定欄位進行校驗。

    舉個例子:

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"})
    )
    ...
    # 定義局部鉤子,用來校驗username欄位,之前的校驗股則還在,給你提供了一個添加一些校驗功能的鉤子
    def clean_username(self):
        value = self.cleaned_data.get("username")
        if "666" in value:
            raise ValidationError("光喊666是不行的")
        else:
            return value

全局鉤子

    我們在Fom類中定義 clean() 方法,就能夠實現對欄位進行全局校驗,欄位全部驗證完,局部鉤子也全部執行完之後,執行這個全局鉤子校驗。

class LoginForm(forms.Form):
    ...
    password = forms.CharField(
        min_length=6,
        label="密碼",
        widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True)
    )
    re_password = forms.CharField(
        min_length=6,
        label="確認密碼",
        widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True)
    )
    ...
    # 定義全局的鉤子,用來校驗密碼和確認密碼欄位是否相同,執行全局鉤子的時候,cleaned_data裡面肯定是有了通過前面驗證的所有數據
    def clean(self):
        password_value = self.cleaned_data.get('password')
        re_password_value = self.cleaned_data.get('re_password')
        if password_value == re_password_value:
            return self.cleaned_data #全局鉤子要返回所有的數據
        else:
            self.add_error('re_password', '兩次密碼不一致') #在re_password這個欄位的錯誤列表中加上一個錯誤,並且clean_data裡面會自動清除這個re_password的值,所以列印clean_data的時候會看不到它
            raise ValidationError('兩次密碼不一致')

六 進階補充

應用Bootstrap樣式

    Django form應用Bootstrap樣式簡單示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
  <title>login</title>
</head>
<body>
<div class="container">
  <div class="row">
    <form action="/login2/" method="post" novalidate class="form-horizontal">
      {% csrf_token %}
      <div class="form-group">
        <label for="{{ form_obj.username.id_for_label }}"
               class="col-md-2 control-label">{{ form_obj.username.label }}</label>
        <div class="col-md-10">
          {{ form_obj.username }}
          <span class="help-block">{{ form_obj.username.errors.0 }}</span>
        </div>
      </div>
      <div class="form-group">
        <label for="{{ form_obj.pwd.id_for_label }}" class="col-md-2 control-label">{{ form_obj.pwd.label }}</label>
        <div class="col-md-10">
          {{ form_obj.pwd }}
          <span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
        </div>
      </div>
      <div class="form-group">
      <label class="col-md-2 control-label">{{ form_obj.gender.label }}</label>
        <div class="col-md-10">
          <div class="radio">
            {% for radio in form_obj.gender %}
              <label for="{{ radio.id_for_label }}">
                {{ radio.tag }}{{ radio.choice_label }}
              </label>
            {% endfor %}
          </div>
        </div>
      </div>
      <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
          <button type="submit" class="btn btn-default">註冊</button>
        </div>
      </div>
    </form>
  </div>
</div>

<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

批量添加樣式

    可通過重寫form類的init方法來實現。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    ...

    def __init__(self, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })

簡單寫一個小項目:book表的添加和數據展示

views.py內容如下:

from django.shortcuts import render,HttpResponse,redirect
from app01 import models
from django import forms
# Create your views here.

class BookForm(forms.Form):
    title = forms.CharField(
        max_length=16,
        label='書名:',
        initial='zhang',
        # widget = forms.widgets.PasswordInput(attrs={'class': 'form-control'},render_value=True),
        widget = forms.widgets.TextInput(attrs={'class': 'form-control'},),

    )
    # title2 = forms.CharField(
    #     max_length=16,
    #     label='書名:',
    #     initial='zhang',
    #     # widget = forms.widgets.PasswordInput(attrs={'class': 'form-control'},render_value=True),
    #     widget=forms.widgets.TextInput(attrs={'class': 'form-control'}, ),
    #
    # )
    sex = forms.ChoiceField(
        choices=(
            ('1','男'),
            ('2','女'),
        )
        ,
        label='性別:',
        # widget=forms.widgets.RadioSelect(),
        # widget=forms.widgets.RadioSelect(),
        # widget=forms.widgets.SelectMultiple(attrs={'class':'form-control'}),
        widget=forms.widgets.Select(attrs={'class':'form-control'}),
        # widget=forms.widgets.CheckboxInput(),
        # widget=forms.widgets.CheckboxSelectMultiple(),
    )
    publishDate = forms.DateField(
        label='出版日期:',
        widget=forms.widgets.TextInput(attrs={'type':'date','class':'form-control'}),
    )
    price=forms.DecimalField(
        max_digits=5,
        decimal_places=2,
        label='書籍的價格:',
        widget=forms.widgets.NumberInput(attrs={'class': 'form-control'}
    ))

    # publish = forms.ModelChoiceField(
    #     label='出版社:',
    #     queryset=models.Publish.objects.all(),
    #     widget=forms.widgets.Select(attrs={'class': 'form-control'}
    # ))
    publish_id = forms.ChoiceField(
        label='出版社:',
        widget=forms.widgets.Select(attrs={'class': 'form-control'}
    ))
    authors = forms.ModelMultipleChoiceField(

        queryset=models.Author.objects.all(),
        widget = forms.widgets.SelectMultiple(attrs={'class': 'form-control'}
    ))

    def __init__(self,*args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['publish_id'].choices = models.Publish.objects.values_list('pk','name')


def index(request):
    if request.method == 'GET':
        form_obj = BookForm()

        return render(request,'index.html',{'form_obj':form_obj})

    else:
        print(request.POST)
        form_obj = BookForm(request.POST)
        print(form_obj.is_valid())
        print(form_obj.errors)
        if form_obj.is_valid():
            print(form_obj.cleaned_data)
            authors_obj = form_obj.cleaned_data.pop('authors')
            new_book_obj = models.Book.objects.create(**form_obj.cleaned_data)
            new_book_obj.authors.add(*authors_obj)
            return redirect('show')

        else:
            print(form_obj.errors)
            return render(request,'index.html',{'form_obj':form_obj})


def show(request):

    book_objs = models.Book.objects.all()

    return render(request,'show.html',{'book_objs':book_objs})

def edit_book(request,n):


    return HttpResponse('歡迎來到編輯頁面')


def delete_book(request,n):
    return HttpResponse('歡迎來到刪除頁面')

  urls.py內容如下

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index,name='index'),
    url(r'^show/', views.show,name='show'),
    url(r'^edit_book/(\d+)/', views.edit_book,name='edit_book'),
    url(r'^delete_book/(\d+)/', views.delete_book,name='delete_book'),
]

  index.html內容如下:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.0-dist/dist/css/bootstrap.min.css' %}">
</head>
<body>

<h1>展示頁面</h1>
{#<div>#}
{#    {{ form_obj.as_p }}#}
{##}
{#</div>#}

{#{% for field in form_obj %}#}
{#    <div>#}
{#        {{ field }}#}
{#    </div>#}
{##}
{#{% endfor %}#}

<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="" novalidate method="post">
                {% for field in form_obj %}
                    <div class="form-group {% if field.errors.0 %}has-error{% endif %}">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        {{ field }}
                        <span class="text-danger">{{ field.errors.0 }}</span>
                    </div>
                {% endfor %}


                {#                <div class="form-group">#}
                {#                    <label for="{{ form_obj.sex.id_for_label }}">{{ form_obj.sex.label }}</label>#}
                {#                    {{ form_obj.sex }}#}
                {#                    {{ form_obj.sex.errors.0 }}#}
                {#                </div>#}
                {#            <div class="form-group">#}
                {#                    <label for="{{ form_obj.publishDate.id_for_label }}">{{ form_obj.publishDate.label }}</label>#}
                {#                    {{ form_obj.publishDate }}#}
                {#                    {{ form_obj.publishDate.errors.0 }}#}
                {#                </div>#}
                {#                <div class="form-group">#}
                {#                    <label for="{{ form_obj.price.id_for_label }}">{{ form_obj.price.label }}</label>#}
                {#                    {{ form_obj.price }}#}
                {#                    <span class="text-danger">{{ form_obj.price.errors.0 }}</span>#}
                {#                </div>#}
                {#            <div class="form-group">#}
                {#                    <label for="{{ form_obj.publish.id_for_label }}">{{ form_obj.publish.label }}</label>#}
                {#                    {{ form_obj.publish }}#}
                {#                    <span class="text-danger">{{ form_obj.publish.errors.0 }}</span>#}
                {#                </div>#}
                {#            <div class="form-group">#}
                {#                    <label for="{{ form_obj.authors.id_for_label }}">{{ form_obj.authors.label }}</label>#}
                {#                    {{ form_obj.authors }}#}
                {#                    <span class="text-danger">{{ form_obj.authors.errors.0 }}</span>#}
                {#                </div>#}
                <input type="submit">
            </form>
        </div>
    </div>
</div>


<div>


</div>


</body>
<script src="{% static 'bootstrap-3.3.0-dist/dist/jQuery/jquery-3.1.1.js' %}"></script>
<script src="{% static 'bootstrap-3.3.0-dist/dist/js/bootstrap.min.js' %}"></script>
</html>

  show.html內容如下

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.0-dist/dist/css/bootstrap.min.css' %}">
</head>
<body>

<h1>數據展示</h1>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table">
                <thead>
                    <tr>
                        <th>id</th>
                        <th>title</th>
                        <th>性別</th>
                        <th>出版日期</th>
                        <th>出版社</th>
                        <th>作者</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for book_obj in book_objs %}
                         <tr>
                            <td>{{ book_obj.pk }}</td>
                            <td>{{ book_obj.title }}</td>
                            <td>{{ book_obj.get_sex_display }}</td>
                            <td>{{ book_obj.publishDate|date:'Y-d-m' }}</td>
                            <td>{{ book_obj.publish.name }}</td>
                            <td>
                                {% for author in book_obj.authors.all %}
                                    {{ author.name }}
                                {% endfor %}

                            </td>
                            <td>
                                <a class="btn btn-warning" href="{% url 'edit_book' book_obj.pk  %}">編輯</a>
                                <a class="btn btn-danger" href="{% url 'delete_book' book_obj.pk  %}">刪除</a>
                            </td>
                         </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>

</div>

</body>
<script src="{% static 'bootstrap-3.3.0-dist/dist/jQuery/jquery-3.1.1.js' %}"></script>
<script src="{% static 'bootstrap-3.3.0-dist/dist/js/bootstrap.min.js' %}"></script>
</html>

  別忘了在settings.py中配置靜態文件

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

  別忘了去下載一個bootstrap和jquery然後在上面的html文件中引入一下。

  models.py文件內容如下:

from django.db import models

# Create your models here.


from django.db import models

# Create your models here.


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid")
    def __str__(self):
        return self.name
class AuthorDetail(models.Model):

    nid = models.AutoField(primary_key=True)
    birthday=models.DateField()
    telephone=models.BigIntegerField()
    addr=models.CharField( max_length=64)

class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Book(models.Model):

    nid = models.AutoField(primary_key=True)
    title = models.CharField( max_length=32)
    sex_choice = (
        (1,'男'),
        (2,'女'),
    )
    sex = models.IntegerField(choices=sex_choice,default=1)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publish=models.ForeignKey(to="Publish",to_field="nid")
    authors=models.ManyToManyField(to='Author',)
    def __str__(self):
        return self.title

  別忘了給每個表添加一些數據。

七 ModelForm

  通常在Django項目中,我們編寫的大部分都是與Django 的模型緊密映射的表單。 舉個例子,你也許會有個Book 模型,並且你還想創建一個form表單用來添加和編輯書籍信息到這個模型中。 在這種情況下,在form表單中定義欄位將是冗餘的,因為我們已經在模型中定義了那些欄位。

  基於這個原因,Django 提供一個輔助類來讓我們可以從Django 的模型創建Form,這就是ModelForm。

modelForm定義

    form與model的終極結合,會根據你model中的欄位轉換成對應的form欄位,並且並你生成標簽等操作。

    比如你的models中的表是下麵的內容:

class Book(models.Model):

    nid = models.AutoField(primary_key=True)
    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)
    publish=models.ForeignKey(to="Publish",to_field="nid")
    authors=models.ManyToManyField(to='Author',)
    def __str__(self):
        return self.title

  

    modelform類的寫法。

class BookForm(forms.ModelForm):

    class Meta:
        model = models.Book
        fields = "__all__"
        labels = {
            "title": "書名",
            "price": "價格"
        }
        widgets = {
            "password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
            "publishDate": forms.widgets.DateInput(attrs={"type": "date"}),
        }

class Meta下常用參數:

model = models.Book  # 對應的Model中的類
fields = "__all__"  # 欄位,如果是__all__,就是表示列出所有的欄位
exclude = None  # 排除的欄位
labels = None  # 提示信息
help_texts = None  # 幫助提示信息
widgets = None  # 自定義插件
error_messages = None  # 自定義錯誤信息
error_messages = {    'title':{'required':'不能為空',...} #每個欄位的所有的錯誤都可以寫,...是省略的意思,複製黏貼我代碼的時候別忘了刪了...}
 

  

  批量添加樣式:和form的一樣

class BookForm(forms.ModelForm):    #password = forms.CharField(min_length=10) #可以重寫欄位,會覆蓋modelform中的這個欄位,那麼modelform下麵關於這個欄位的設置就會被覆蓋,比如果設置插件啊,error_messages啊等等,
    r_password = forms.CharField() #想多驗證一些欄位可以單獨拿出來寫,按照form的寫法,寫在Meta的上面或者下麵都可以
    class Meta:
        model = models.Book
        # fields = ['title','price']
        fields = "__all__" #['title,'price'] 指定欄位生成form
        # exclude=['title',] #排除欄位
        labels = {
            "title": "書名",
            "price": "價格"
        }
        error_messages = {
            'title':{'required':'不能為空',} #每個欄位的錯誤都可以寫
        }
    #如果models中的欄位和咱們需要驗證的欄位對不齊的是,比如註冊時,咱們需要驗證密碼和確認密碼兩個欄位數據,但是後端資料庫就保存一個數據就行,那麼驗證是兩個,數據保存是一個,就可以再接著寫form欄位
    r_password = forms.CharField()。    #同樣的,如果想做一些特殊的驗證定製,那麼和form一昂,也是那兩個鉤子(全局和局部),寫法也是form那個的寫法,直接在咱們的類裡面寫:    #局部鉤子:    def clean_title(self):        pass  #全局鉤子    def clean(self):        pass
    def __init__(self,*args,**kwargs): #批量操作
        super().__init__(*args,**kwargs)
        for field in self.fields:            #field.error_messages = {'required':'不能為空'} #批量添加錯誤信息,這是都一樣的錯誤,不一樣的還是要單獨寫。
            self.fields[field].widget.attrs.update({'class':'form-control'})

ModelForm的驗證

    與普通的Form表單驗證類型類似,ModelForm表單的驗證在調用is_valid() 或訪問errors 屬性時隱式調用。

    我們可以像使用Form類一樣自定義局部鉤子方法和全局鉤子方法來實現自定義的校驗規則。

    如果我們不重寫具體欄位並設置validators屬性的話,ModelForm是按照模型中欄位的validators來校驗的。

save()方法

    每個ModelForm還具有一個save()方法。 這個方法根據表單綁定的數據創建並保存資料庫對象。 ModelForm的子類可以接受現有的模型實例作為關鍵字參數instance;如果提供此功能,則save()將更新該實例。 如果沒有提供,save() 將創建模型的一個新實例:

>>> from myapp.models import Book
>>> from myapp.forms import BookForm

# 根據POST數據創建一個新的form對象
>>> form_obj = BookForm(request.POST)

# 創建書籍對象
>>> new_ book = form_obj.save()

# 基於一個書籍對象創建form對象
>>> edit_obj = Book.objects.get(id=1)
# 使用POST提交的數據更新書籍對象
>>> form_obj = BookForm(request.POST, instance=edit_obj)
>>> form_obj.save()

  之前我們通過form組件來保存書籍表數據的時候的寫法:

def index(request):
    if request.method == 'GET':
        form_obj = BookForm()

        return render(request,'index.html',{'form_obj':form_obj})

    else:
        form_obj = BookForm(request.POST)
        if form_obj.is_valid():
            # authors_obj = form_obj.cleaned_data.pop('authors')
            # new_book_obj = models.Book.objects.create(**form_obj.cleaned_data)
            # new_book_obj.authors.add(*authors_obj)
            form_obj.save()  #因為我們再Meta中指定了是哪張表,所以它會自動識別,不管是外鍵還是多對多等,都會自行處理保存,它完成的就是上面三句話做的事情,並且還有就是如果你驗證的數據比你後端數據表中的欄位多,那麼他自會自動剔除多餘的不需要保存的欄位,比如那個重覆確認密碼就不要保存
            return redirect('show')

        else:
            print(form_obj.errors)
            return render(request,'index.html',{'form_obj':form_obj})

比如說我們圖書管理系統頁面之前是這樣寫的

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.0-dist/dist/css/bootstrap.min.css' %}">
</head>
<body>

<h1>編輯頁面</h1>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="">
                <div class="form-group">
                    <label for="title">書名</label>
                    <input type="text" class="form-control" id="title" placeholder="title" value="{{ book_obj.title }}">

                </div>
                <div class="form-group">
                    <label for="publishDate">出版日期</label>
                    <input type="text" class="form-control" id="publishDate" placeholder="publishDate" value="{{ book_obj.publishDate|date:'Y-m-d' }}">

                </div>
                <div class="form-group">
                    <label for="price">價格</label>
                    <input type="number" class="form-control" id="price" placeholder="price" value="{{ book_obj.price }}">

                </div>
                <div class="form-group">
                    <label for="publish">書名</label>
                    <select name="publish" id="publish" class="form-control">
                        {% for publish in all_publish %}
                                {% if publish == book_obj.publish %}
                                    <option value="{{ publish.id }}" selected>{{ publish.name }}</option>
                                {% else %}
                                    <option value="{{ publish.id }}">{{ publish.name }}</option>
                                {% endif %}
                        {% endfor %}

                    </select>

                </div>
                <div class="form-group">
                    <label for="authors">書名</label>
                    <select name="authors" id="authors" multiple class="form-control">
                        {% for author in all_authors %}
                            {% if author in book_obj.authors.all %}
                                <option value="{{ author.id }}" selected>{{ author.name }}</option>
                            {% else %}
                                 <option value="{{ author.id }}" >{{ author.name }}</option>
                            {% endif %}
                        {% endfor %}

                    </select>

                </div>
            </form>

        </div>
    </div>
</div>


</body>
<script src="{% static 'bootstrap-3.3.0-dist/dist/jQuery/jquery-3.1.1.js' %}"></script>
<script src="{% static 'bootstrap-3.3.0-dist/dist/js/bootstrap.min.js' %}"></script>
</html>

views.py是這樣寫的:

def edit_book(request,n):

    book_obj = models.Book.objects.filter(pk=n).first()
    if request.method == 'GET':
        all_authors = models.Author.objects.all() #
        all_publish = models.Publish.objects.all()

        return render(request,'edit_book.html',{'book_obj':book_obj,'all_authors':all_authors,'all_publish':all_publish})

改成使用modelform之後,我們這樣寫:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.0-dist/dist/css/bootstrap.min.css' %}">
</head>
<body>

<h1>編輯頁面</h1>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="{% url 'edit_book' n %}" novalidate method="post">
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        {{ field }}
                        <span class="text-danger">{{ field.errors.0 }}</span>
                    </div>
                {% endfor %}

                <div class="form-group">
                    <input type="submit" class="btn btn-primary pull-right">
                </div>

            </form>

        </div>
    </div>
</div>


</body>
<script src="{% static 'bootstrap-3.3.0-dist/dist/jQuery/jquery-3.1.1.js' %}"></script>
<script src="{% static 'bootstrap-3.3.0-dist/dist/js/bootstrap.min.js' %}"></script>
</html>

views.py這樣寫:

def edit_book(request,n):

    book_obj = models.Book.objects.filter(pk=n).first()
    if request.method == 'GET':
        # all_authors = models.Author.objects.all() #
        # all_publish = models.Publish.objects.all()

        form = BookForm(instance=book_obj)

        return render(request,'edit_book.html',{'form':form,'n':n}) #傳遞的這個n參數是給form表單提交數據的是的action的url用的,因為它需要一個參數來識別是更新的哪條記錄

    else:
        form = BookForm(request.POST,instance=book_obj) #必須指定instance,不然我們調用save方法的是又變成了添加操作
        if form.is_valid():
            form.save()
            return redirect('show')
        else:
            return render(request,'edit_book.html',{'form':form,'n':n})

創建modelform

  這是一個神奇的組件,通過名字我們可以看出來,這個組件的功能就是把model和form組合起來,先來一個簡單的例子來看一下這個東西怎麼用:比如我們的資料庫中有這樣一張學生表,欄位有姓名,年齡,愛好,郵箱,電話,住址,註冊時間等等一大堆信息,現在讓你寫一個創建學生的頁面,你的後臺應該怎麼寫呢?首先我們會在前端一個一個羅列出這些欄位,讓用戶去填寫,然後我們從後天一個一個接收用戶的輸入,創建一個新的學生對象,保存其實,重點不是這些,而是合法性驗證,我們需要在前端判斷用戶輸入是否合法,比如姓名必須在多少字元以內,電話號碼必須是多少位的數字,郵箱必須是郵箱的格式這些當然可以一點一點手動寫限制,各種判斷,這毫無問題,除了麻煩我們現在有個更優雅(以後在Python相關的內容里,要多用“優雅”這個詞,並且養成習慣)的方法:ModelForm先來簡單的,生硬的把它用上,再來加驗證條件。

#首先導入ModelForm

from django.forms import ModelForm
#在視圖函數中,定義一個類,比如就叫StudentList,這個類要繼承ModelForm,在這個類中再寫一個原類Meta(規定寫法,並註意首字母是大寫的)
#在這個原類中,有以下屬性(部分):

class StudentList(ModelForm):
    class Meta:
        model =Student #對應的Model中的類
        fields = "__all__" #欄位,如果是__all__,就是表示列出所有的欄位
        exclude = None #排除的欄位
        #error_messages用法:
        error_messages = {
        'name':{'required':"用戶名不能為空",},
        'age':{'required':"年齡不能為空",},
        }
        #widgets用法,比如把輸入用戶名的input框給為Textarea
        #首先得導入模塊
        from django.forms import widgets as wid #因為重名,所以起個別名
        widgets = {
        "name":wid.Textarea(attrs={"class":"c1"}) #還可以自定義屬性
        }
        #labels,自定義在前端顯示的名字
        labels= {
        "name":"用戶名"
        }

    然後在url對應的視圖函數中實例化這個類,把這個對象傳給前端

def student(request):

    if request.method == 'GET':
        student_list = StudentList()
        return render(request,'student.html',{'student_list':student_list})
        

    然後前端只需要 {{ student_list.as_p }} 一下,所有的欄位就都出來了,可以用as_p顯示全部,也可以通過for迴圈這
    student_list,拿到的是一個個input框,現在我們就不用as_p,手動把這些input框搞出來,as_p拿到的頁面太醜。
    首先 for迴圈這個student_list,拿到student對象,直接在前端列印這個student,是個input框student.label ,拿到資料庫中每個欄位的verbose_name ,如果沒有設置這個屬性,拿到的預設就是欄位名,還可以通過student.errors.0 拿到錯誤信息有了這些,我們就可以通過bootstrap,自己拼出來想要的樣式了,比如:

<body>
<div class="container">
    <h1>student</h1>
    <form method="POST" novalidate>
        {% csrf_token %}
        {# {{ student_list.as_p }}#}
        {% for student in student_list %}
            <div class="form-group col-md-6">
                {# 拿到數據欄位的verbose_name,沒有就預設顯示欄位名 #}
                <label class="col-md-3 control-label">{{ student.label }}</label>
                <div class="col-md-9" style="position: relative;">{{ student }}</div>
            </div>
        {% endfor %}
        <div class="col-md-2 col-md-offset-10">
            <input type="submit" value="提交" class="btn-primary">
        </div>
    </form>
</div>
</body>

    現在還缺一個input框的form-contral樣式,可以考慮在後臺的widget裡面添加
    比如這樣:

from django.forms import widgets as wid #因為重名,所以起個別名
widgets = {
"name":wid.TextInput(attrs={'class':'form-control'}),
"age":wid.NumberInput(attrs={'class':'form-control'}),
"email":wid.EmailInput(attrs={'class':'form-control'})
}

    當然也可以在js中,找到所有的input框,加上這個樣式,也行。

添加紀錄

    保存數據的時候,不用挨個取數據了,只需要save一下

def student(request):

    if request.method == 'GET':
         student_list = StudentList()
         return render(request,'student.html',{'student_list':student_list})
    else:
         student_list = StudentList(request.POST)
         if student_list.is_valid():
         student_list.save()
         return redirect(request,'student_list.html',{'student_list':student_list})

編輯數據

    如果不用ModelForm,編輯的時候得顯示之前的數據吧,還得挨個取一遍值,如果ModelForm,只需要加一個instance=obj(obj是要修改的資料庫的一條數據的對象)就可以得到同樣的效果
    保存的時候要註意,一定要註意有這個對象(instance=obj),否則不知道更新哪一個數據
    代碼示例:

from django.shortcuts import render,HttpResponse,redirect
from django.forms import ModelForm
# Create your views here.
from app01 import models
def test(request):
    # model_form = models.Student
    model_form = models.Student.objects.all()
    return render(request,'test.html',{'model_form':model_form})

class StudentList(ModelForm):
    class Meta:
        model = models.Student #對應的Model中的類
        fields = "__all__" #欄位,如果是__all__,就是表示列出所有的欄位
        exclude = None #排除的欄位
        labels = None #提示信息
        help_texts = None #幫助提示信息
        widgets = None #自定義插件
        error_messages = None #自定義錯誤信息
        #error_messages用法:
        error_messages = {
        'name':{'required':"用戶名不能為空",},
        'age':{'required':"年齡不能為空",},
        }
        #widgets用法,比如把輸入用戶名的input框給為Textarea
        #首先得導入模塊
        from django.forms import widgets as wid #因為重名,所以起個別名
        widgets = {
        "name":wid.Textarea
        }
        #labels,自定義在前端顯示的名字
        labels= {
        "name":"用戶名"
        }
def student(request):
    if request.method == 'GET':
        student_list = StudentList()
        return render(request,'student.html',{'student_list':student_list})
    else:
        student_list = StudentList(request.POST)
        if student_list.is_valid():
            student_list.save()
            return render(request,'student.html',{'student_list':student_list})

def student_edit(request,pk):
    obj = models.Student.objects.filter(pk=pk).first()
    if not obj:
        return redirect('test')
    if request.method == "GET":
        student_list = StudentList(instance=obj)
        return render(request,'student_edit.html',{'student_list':student_list})
    else:
        student_list = StudentList(request.POST,instance=obj)
        if student_list.is_valid():
            student_list.save()
            return render(request,'student_edit.html',{'student_list':student_list})

  總結: 從上邊可以看到ModelForm用起來是非常方便的,比如增加修改之類的操作。但是也帶來額外不好的地方,model和form之間耦合了。如果不耦合的話,mf.save()方法也無法直接提交保存。 但是耦合的話使用場景通常局限用於小程式,寫大程式就最好不用了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、路由的配置 路由 vue-router 1. 什麼是路由? 路由相當於一個配置對象 路由:就是我們通過不同的url訪問不同的內容,通過angular.js 可以實現多視圖的單頁,現在流行的單頁面開發模式。 2. 路由在web 有兩種: 第一種 hash hash值前面帶 # " https: / ...
  • js中scroll滾動相關 一.元素相關 | 屬性/方法 | 解釋 | | | | | element.scrollHeight | 返回元素的整體高度。 | | element.scrollWidth | 返回元素的整體寬度。 | | element.scrollLeft | 返回元素左邊緣與視圖 ...
  • Vue 提供了一些不同的過度效果,主要根 v-if v-show 動態組件 1. Vue給動畫分了6個過程,在css中,扮演6個類, 1. .v-enter定義動畫的開始狀態 2. .v-enter-active 定義動畫生效時的狀態 3. .v-enter-to 定義動畫的結束狀態 4. .v-l ...
  • Slot v-slot 插槽元素 瀏覽器在解析時候首先把它當作標簽來解析,只有遇到不認識的就不管了,直接跳過,當你發現是組件,在以組件形式解析。 使用插槽的好處? 比如一個網站 分佈頂部都是一樣的,如果使用組件,要寫好幾個導航組件。我只寫一個導航組件,然後讓插值裡面東西去覆蓋內容 就可以了。 * 在 ...
  • 前兩天遇到的問題,經過很多網友的深刻討論,終於有一個相對可以解釋的通的邏輯了,然後我仔細研究了一下相關的點,順帶研究了一下js中的隱式變數。 以下文章中提到的隱式變數都是指沒有用var,let,const等關鍵字定義的變數。 以下文章中提到的var變數都是指用var聲明定義的變數。 一遇到隱式變數, ...
  • 1.Form標簽:用來將表單外的內容與表單進行關聯。其主要元素有input,button,select。 action屬性:指定表單的發送地址。 Novalidate屬性:數據提交時不校驗。 Target屬性:指定在何處打開指定的url。 method屬性:表單數據發送至伺服器的方法,預設屬性就是g ...
  • 在 HTML 中,JavaScript 語句是由 web 瀏覽器“執行”的“指令”。 實例 var x, y, z; // 語句 1 x = 22; // 語句 2 y = 11; // 語句 3 z = x + y; // 語句 4 JavaScript 程式 電腦程式是由電腦“執行”的一系列 ...
  • 策略模式(Strategy): 策略模式是對演算法的包裝,是把使用演算法的責任和演算法本身分割開來,委派給不同的對象管理。策略模式通常把一個系列的演算法包裝到一系列的策略類裡面,作為一個抽象策略類的子類。用一句話來說,就是:“準備一組演算法,並將每一個演算法封裝起來,使得它們可以互換”。 策略模式的角色: 1) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...