日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Django中的Form ModelForm

發(fā)布時(shí)間:2025/3/17 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Django中的Form ModelForm 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Django中的Form & ModelForm

在web開(kāi)發(fā)中,處理表單是家常便飯,我們當(dāng)然可以直接在模板中編寫原生的html表單,然后在后端進(jìn)行表單驗(yàn)證,這常常是一項(xiàng)繁瑣的工作。

Form

我們可以通過(guò)Django提供了表單功能,來(lái)方便表單的處理。下面看一下如何使用:

  • 自定義表單類

    from django import forms # 導(dǎo)入表單模塊 from django.core.exceptions import ValidationError class RegisterForm(forms.Form): # 自定義表單類,并繼承forms.Formemail = forms.EmailField(widget=forms.EmailInput( attrs={"class": "form-control"}))username = forms.CharField(min_length=4, max_length=12, widget=forms.TextInput(attrs={"class": "form-control"}))password = forms.CharField(min_length=6, widget=forms.PasswordInput(attrs={"class": "form-control"}))password2 = forms.CharField(min_length=6, widget=forms.PasswordInput(attrs={"class": "form-control"}))valid_code = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"}))def __init__(self, request, *args, **kwargs):# 如果需要額外接收參數(shù),要重寫構(gòu)造器函數(shù)# 這里額外接收一個(gè)參數(shù),用于從request.sesssion中提取之前保存的驗(yàn)證碼super(RegisterForm,self).__init__(*args, **kwargs) self.request = request# 自定義方法(局部鉤子),密碼必須包含字母和數(shù)字def clean_password(self):if self.cleaned_data.get('password').isdigit() or self.cleaned_data.get('password').isalpha():raise ValidationError('密碼必須包含數(shù)字和字母')else:return self.cleaned_data['password']def clean_valid_code(self): # 檢驗(yàn)驗(yàn)證碼正確;之前生成的驗(yàn)證碼保存在了了session中if self.cleaned_data.get('valid_code').upper() == self.request.session.get('valid_code'):return self.cleaned_data['valid_code']else:raise ValidationError('驗(yàn)證碼不正確')# 自定義方法(全局鉤子, 檢驗(yàn)兩個(gè)字段),檢驗(yàn)兩次密碼一致;def clean(self):if self.cleaned_data.get('password') != self.cleaned_data.get('password2'):raise ValidationError('密碼不一致')else:return self.cleaned_data# 注意,上面的字典取值用get, 因?yàn)榧偃缭赾lean_password中判斷失敗,那么沒(méi)有返回值,最下面的clean方法直接取值就會(huì)失敗

    說(shuō)明:

  • min_length=4, max_length=12定義字段字符長(zhǎng)度
  • error_messages={"required":["請(qǐng)輸入有效的......"]} 自定義錯(cuò)誤信息
  • widget參數(shù)用來(lái)指定字段的類型和屬性;
  • clean是驗(yàn)證函數(shù),分為局部鉤子和全局鉤子;局部鉤子clean_field用于驗(yàn)證單個(gè)字段,全局鉤子clean用于驗(yàn)證兩個(gè)字段;
  • clean驗(yàn)證函數(shù)必須有返回值;
  • 實(shí)例化表單對(duì)象,傳入模板渲染

    # 實(shí)例化表單對(duì)象; 因?yàn)橹貙懥薸nit方法,這里要額外接收requestform_obj = RegisterForm(request) <form action="{% url 'register' %}" method="post" id="register">{% csrf_token %}<div class="form-group"><label for="id_email">郵箱&nbsp;</label><span class="error-info"></span>{{ form_obj.email }} <!-- span 標(biāo)簽用于放置錯(cuò)誤信息 --></div>......<p class="reg-button"><button type="submit" class="btn btn-primary btn-block">注冊(cè)</button></p></form>

    說(shuō)明:

    <form>{{form_obj.as_p}}</form>也可以通過(guò)as_p方法直接生成整個(gè)表單,但是自定義性比較差。

    ?

  • 驗(yàn)證提交的表單

    # 傳入request.POST,實(shí)例化表單對(duì)象用于戶驗(yàn)證和提取數(shù)據(jù)form_obj = RegisterForm(request, request.POST) # 方法:form_obj.is_valid() # 根據(jù)字段屬性和驗(yàn)證函數(shù)進(jìn)行校驗(yàn) form.cleaned_data.get(field) # 校驗(yàn)OK,提取數(shù)據(jù) form.errors # 錯(cuò)誤信息:{field:[error_info], field:[],...}
  • 根據(jù)用戶提交,保存或修改數(shù)據(jù)庫(kù)

    略……

  • ModelForm

    用過(guò)Django Form功能的可能會(huì)覺(jué)得用起來(lái)很繁瑣,要寫一堆驗(yàn)證方法,驗(yàn)證通過(guò)后還是要一一提取數(shù)據(jù),最終的操作都是數(shù)據(jù)庫(kù)模型中進(jìn)行保存或修改操作。不難發(fā)現(xiàn)Form表單的字段和對(duì)應(yīng)的數(shù)據(jù)庫(kù)Model幾乎是一樣的,于是Django提供了ModelForm,極大的簡(jiǎn)化了表單的處理和驗(yàn)證。我們看下如何使用。

  • 自定義表單,繼承ModelForm

    from django.forms import ModelForm # 導(dǎo)入ModelForm from django.forms import fields from .models import UserInfo, Role, Permission, Menu # 導(dǎo)入Modelclass UserInfoModelForm(ModelForm):username = fields.CharField(required=True)"""可以在這里單獨(dú)定義字段的具體類型和屬性,同F(xiàn)orm如果定義的字段在model中存在,則會(huì)覆蓋;"""class Meta:model = UserInfofields = '__all__'labels = {'username': '用戶名','password': '密碼','nickname': '昵稱','email': '郵箱',}

    說(shuō)明:

  • model: 對(duì)應(yīng)的數(shù)據(jù)庫(kù)model

  • fields: 選擇字段列表;’all’是選擇所有字段

  • exclude: 排除字段列表

  • widgets: 插件字典

  • labels: 前端顯示字段名

  • error_messages: 自定義錯(cuò)誤提示

  • localized_fields: 本地化,如:根據(jù)不同時(shí)區(qū)顯示數(shù)據(jù)

    數(shù)據(jù)庫(kù)中2016-12-27 04:10:57 setting中的配置TIME_ZONE = 'Asia/Shanghai'USE_TZ = True 則顯示:2016-12-27 12:10:57

    ?

  • 實(shí)例化表單對(duì)象,傳入模板,同F(xiàn)orm

    model_form = UserInfoModelForm()
  • 驗(yàn)證提交的表單

    model_form = UserInfoModelForm(request.POST) if model_form.is_valid():model_form.save()

    is_valid()方法會(huì)根據(jù)model字段的類型以及自定義驗(yàn)證方法來(lái)驗(yàn)證提交的數(shù)據(jù);如果is_valid()驗(yàn)證通過(guò),直接save(),就可以完成向數(shù)據(jù)庫(kù)中插入一條記錄。

  • 如果是修改記錄,需要傳入記錄對(duì)象

    # 實(shí)例化表單對(duì)象,傳入模板model_form = UserInfoModelForm(instance=user_obj)# 驗(yàn)證提交model_form = UserInfoModelForm(request.POST, instance=user_obj) if model_form.is_valid():model_form.save()

  • ChoiceField字段

    用于外鍵字段

    例1:將外鍵字段定義為ChoiceField字段,這里以Form表單為例來(lái)說(shuō)明:

    class UserInfoForm(Form):name = fields.CharField(required=True, error_messages={'required': '用戶名不能為空'})password = fields.CharField(required=True, error_messages={'required': '密碼不能為空'})email = fields.EmailField(required=True)# depart為外鍵字段,那么我們可以將其變?yōu)橄吕x項(xiàng)(非外鍵字段也可以,只要給它提供[(m, n), (m, n)]這種結(jié)構(gòu)的數(shù)據(jù)源就可以)depart = fields.ChoiceField(choices=models.Department.objects.values_list('id', 'title'))

    depart字段的模板渲染結(jié)果:

    <select name="depart" id="id_depart"><option value="1">銷售</option><option value="2">公關(guān)</option><option value="3">技術(shù)</option><option value="4">后勤</option> </select>

    用于自定義字段

    例2:這里以ModelForm為例來(lái)進(jìn)行說(shuō)明:

    def func():return [(1, '北京'),(2, '上海'),(3, '武漢'),]class UserInfoModelForm(ModelForm):city = fields.ChoiceField(choices=func())"""可以在這里單獨(dú)定義字段的具體類型和屬性,同F(xiàn)orm如果定義的字段在model中存在,則會(huì)覆蓋;假設(shè),model中的city字段是CharField類型,默認(rèn)用ModelForm會(huì)生成input框,但是我們又不希望每次都手動(dòng)填入數(shù)據(jù)。那么,就可以單獨(dú)定義該字段為ChoiceField類型。只需要為其提供[(m, n), (m, n)]這種結(jié)構(gòu)的數(shù)據(jù)源就可以,比如這里選擇通過(guò)一個(gè)函數(shù)來(lái)實(shí)現(xiàn)。"""class Meta:model = UserInfofields = '__all__'labels = {'username': '用戶名','password': '密碼','email': '郵箱',}

    city字段的模板渲染結(jié)果:

    <select name="city" id="id_city"><option value="1">北京</option><option value="2">上海</option><option value="3">武漢</option> </select>

    用于靜態(tài)字段

    以上兩個(gè)栗子,分別用了外鍵的關(guān)聯(lián)表和函數(shù)返回值作為表單中ChoiceField字段的下拉選項(xiàng)數(shù)據(jù)。在實(shí)際使用中,常常在model中定義一個(gè)靜態(tài)字段,來(lái)作為數(shù)據(jù)來(lái)源,如下:

    from django.db import modelsclass Department(models.Model):passclass UserInfo(models.Model):city_choices = [(1, '北京'),(2, '上海'),(3, '武漢'),]username = models.CharField(verbose_name='用戶名', max_length=32, null=True, blank=True)password = models.CharField(verbose_name='密碼', max_length=64, null=True, blank=True)email = models.EmailField(verbose_name='郵箱', max_length=64, null=True, blank=True)# city以靜態(tài)字段city_choices作為數(shù)據(jù)來(lái)源city = models.IntegerField(verbose_name='城市', choices=city_choices, null=True, blank=True)depart = models.ForeignKey(verbose_name='部門', to="Department", null=True, blank=True)

    bug

    不論數(shù)據(jù)是來(lái)自靜態(tài)字段還是外鍵關(guān)聯(lián)表,ChoiceField字段的值都是是從數(shù)據(jù)庫(kù)獲取的。但是一旦數(shù)據(jù)源更新了,模板在渲染時(shí)無(wú)法顯示最新的數(shù)據(jù);除非重啟程序。這是因?yàn)?#xff0c;定義了Form或ModelForm后,ChoiceField會(huì)從數(shù)據(jù)庫(kù)取一次值,后面再使用時(shí)這個(gè)值就不更新了。因此,要?jiǎng)討B(tài)生成ChoiceField字段的數(shù)據(jù)。

    解決辦法:不在定義階段獲取數(shù)據(jù),在每次實(shí)例化表單時(shí)獲取數(shù)據(jù),重寫__init__方法:

    class UserInfoForm(Form):name = fields.CharField(required=True, error_messages={'required': '用戶名不能為空'})password = fields.CharField(required=True, error_messages={'required': '密碼不能為空'})email = fields.EmailField(required=True)# depart這里只定義字段類型depart = fields.ChoiceField()def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 實(shí)例化時(shí)才動(dòng)態(tài)獲取數(shù)據(jù)self.fields['depart'].choices = models.Department.objects.values_list('id', 'title')


    除了上面這種手動(dòng)的方式,我們也可以利用ModelChoiceField字段,達(dá)到動(dòng)態(tài)獲取數(shù)據(jù)的目的:

    class UserInfoForm(Form):name = fields.CharField(required=True, error_messages={'required': '用戶名不能為空'})password = fields.CharField(required=True, error_messages={'required': '密碼不能為空'})email = fields.EmailField(required=True)# ModelChoiceField字段動(dòng)態(tài)獲取數(shù)據(jù)depart = ModelChoiceField(queryset=models.Department.objects.all())

    depart模板渲染結(jié)果:

    <select name="depart" required="" id="id_depart"><option value="" selected="">---------</option><option value="1">銷售</option><option value="2">公關(guān)</option><option value="3">技術(shù)</option><option value="4">后勤</option> </select>


    不過(guò)這里還是推薦通過(guò)第一種,重寫__init__的方式,定制性更強(qiáng);

    第二種ModelChoiceField自動(dòng)獲取數(shù)據(jù),它接收QuerySet對(duì)象,因此,如果沒(méi)有在model中定義__str__方法,渲染出來(lái)的結(jié)果將是這樣子的。。。

    <select name="depart" required="" id="id_depart"><option value="" selected="">---------</option><option value="1">Department object</option><!-- 沒(méi)有可讀性。。。 --> </select>

    總結(jié)

    以上是生活随笔為你收集整理的Django中的Form ModelForm的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: a天堂中文网 | 正在播放超嫩在线播放 | 精品在线观看视频 | 午夜老湿机 | 色婷婷中文| 国产精品自拍99 | 亚洲熟妇色自偷自拍另类 | 性高潮久久久久久 | 国产一级二级毛片 | 欧美色一区二区三区在线观看 | 亚洲成人免费在线观看 | 激情五月网站 | 亚洲社区在线观看 | 国产麻豆xxxvideo实拍 | 人妻体内射精一区二区 | 蜜臀国产AV天堂久久无码蜜臀 | 久久国产精品免费视频 | 日韩国产在线一区 | 波多野结衣mp4 | 欧美视频一区二区 | 在线国产毛片 | 91麻豆精品国产理伦片在线观看 | 少妇免费视频 | 风流少妇一区二区三区91 | 国产东北真实交换多p免视频 | 欧美三日本三级少妇三级99观看视频 | 久久动态图 | 国产精品高潮呻吟久久久 | 懂色tv | 国产精品高潮呻吟久久av野狼 | 综合久久亚洲 | 97人妻精品一区二区三区免费 | 国产欧美日韩精品在线 | 国产乱码精品一区二区三区忘忧草 | 国产精品夜夜躁视频 | 91成人动漫 | 玉丸(双性调教) | 欧美激情视频在线播放 | 九九色视频 | 亚洲福利二区 | 伦乱天堂 | 黄色小说在线免费观看 | 国产精品国产三级国产专区51 | 国产成人无码一二三区视频 | 欧美成人一级视频 | 欧美变态口味重另类 | 免费观看成年人视频 | 日日摸日日添日日躁av | 国产精品久久久一区二区三区 | 国产视频九色蝌蚪 | 国内偷拍精品视频 | 免费啪视频在线观看 | 激情三级在线 | 亚洲综合色站 | 在线观看国产免费视频 | 欧美成本人视频 | 偷拍亚洲色图 | 97自拍偷拍| 狠狠爱天天干 | 国产成人8x视频一区二区 | 日本黄色视屏 | 久草成人在线视频 | 久久免费高清视频 | 精品乱子伦一区二区三区 | 欧美最猛黑人xxxx | 美女的奶胸大爽爽大片 | jvid在线 | 色五婷婷 | 豆花视频在线播放 | 色噜噜一区二区三区 | 欧美精品免费一区二区 | 毛片无遮挡 | 日韩经典在线观看 | 香蕉精品在线 | 日本一本二本三区免费 | 精品一区二区三区无码视频 | 少妇高潮一区二区三区99 | 国产伦精品一区二区三区四区视频 | 国产成人麻豆精品午夜在线 | 欧美精品一区二区在线观看 | av官网| a级片免费看 | 日本a级片视频 | 精品无码国产污污污在线观看 | 亚洲国产一区二区在线 | 国产91啪 | 爆乳2把你榨干哦ova在线观看 | 最新日韩中文字幕 | 成人激情四射 | a天堂v| 国产日韩一区二区 | aaa欧美| 性涩av | 爱爱的免费视频 | 性高潮久久久久久久 | 成人性生活毛片 | 日韩一区二区免费播放 | 一区二区日韩国产 | 香蕉久久一区二区三区 |