django中的form modelform formset modelformset
阿新 • • 發佈:2018-11-23
首先上結論:
form適用於對單個表單的操作,並且需要對每個欄位的驗證規則自定義。
modelform:適用於對使用者提交的單個表單操作,欄位可以用model中的表的欄位來作為驗證規則,適用於快速的進行增加、修改。
formset:適用於對多個表單進行操作,欄位需要也可以用model中的表的欄位來作為驗證規則。
modelfoemset:適用於對多個表單進行操作,欄位需要也可以用model中的表的欄位來作為驗證規則,速度可能快一些(有待考證)
form用法
後端程式碼
from django.forms import widgets wid_01=widgets.TextInput(attrs={"class":"form-control"}) wid_02=widgets.PasswordInput(attrs={"class":"form-control"}) class UserForm(forms.Form): name=forms.CharField(max_length=32, widget=wid_01 ) pwd=forms.CharField(max_length=32,widget=wid_02) r_pwd=forms.CharField(max_length=32,widget=wid_02) email=forms.EmailField(widget=wid_01) tel=forms.CharField(max_length=32,widget=wid_01) def register(request): if request.method=="POST": form=UserForm(request.POST) if form.is_valid(): print(form.cleaned_data) # 所有乾淨的欄位以及對應的值 else: print(form.cleaned_data) # print(form.errors) # ErrorDict : {"校驗錯誤的欄位":["錯誤資訊",]} print(form.errors.get("name")) # ErrorList ["錯誤資訊",] return HttpResponse("OK") form=UserForm() return render(request,"register.html",locals())
<form action="" method="post"> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {{ field }} </div> {% endfor %} <input type="submit" class="btn btn-default pull-right"> </form>
modelform用法
class MenuModelForm(forms.ModelForm): class Meta: model = models.Menu fields = '__all__' widgets = { 'title': forms.TextInput(attrs={'placeholder': '請輸入角色名稱', 'class': 'form-control'}), 'icon': forms.RadioSelect( choices=ICON_LIST ) } error_messages = { 'title': { 'required': '選單名稱不能為空', }, 'icon': { 'required': '請選擇圖示', } } def menu_add(request): """ 新增選單 :param request: :return: """ if request.method == 'GET': form = MenuModelForm() else: form = MenuModelForm(request.POST) if form.is_valid(): print(form.data) form.save() return redirect(reverse('rbac:menu_list')) return render(request, 'rbac/menu_change.html', {'form': form}) def menu_edit(request, pk): """ 編輯選單 :param request: :return: """ obj = models.Menu.objects.filter(id=pk).first() if not obj: return HttpResponse('選單不存在') if request.method == 'GET': form = MenuModelForm(instance=obj) return render(request, 'rbac/menu_change.html', {'form': form}) form = MenuModelForm(request.POST, instance=obj) if form.is_valid(): form.save() return redirect(reverse('rbac:menu_list'))
<div class="luffy-container"> <form class="form-horizontal" method="post" novalidate> {% csrf_token %} <div class="form-group"> <label class="col-sm-2 control-label">選單名稱:</label> <div class="col-sm-6"> {{ form.title }} </div> <div class="col-sm-offset-1 col-sm-2"> <input type="submit" value="保 存" class="btn btn-primary"> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">圖示:</label> <div class="col-sm-7 icon-area"> {{ form.icon }} </div> <div class="col-sm-3"> <div>{{ form.title.errors.0 }}</div> <div>{{ form.icon.errors.0 }}</div> </div> </div> </form> </div>
formset用法
class MultiPermissionForm(forms.Form): id = forms.IntegerField( widget=forms.HiddenInput(), required=False ) title = forms.CharField( widget=forms.TextInput(attrs={'class': "form-control"}) ) url = forms.CharField( widget=forms.TextInput(attrs={'class': "form-control"}) ) name = forms.CharField( widget=forms.TextInput(attrs={'class': "form-control"}) ) menu_id = forms.ChoiceField( choices=[(None, '-----')], widget=forms.Select(attrs={'class': "form-control"}), required=False, ) pid_id = forms.ChoiceField( choices=[(None, '-----')], widget=forms.Select(attrs={'class': "form-control"}), required=False, ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['menu_id'].choices += models.Menu.objects.values_list('id', 'title') self.fields['pid_id'].choices += models.Permission.objects.filter(pid__isnull=True).exclude( menu__isnull=True).values_list('id', 'title') def clean_pid_id(self): menu = self.cleaned_data.get('menu_id') pid = self.cleaned_data.get('pid_id') if menu and pid: raise forms.ValidationError('選單和根許可權同時只能選擇一個') return pid def add(request): """ 增加 :param request: :return: """ MultiPermissionFormSet = formset_factory(MultiPermissionForm, extra=0) if request.method == 'GET': form = MultiPermissionFormSet() return render(request,'list.html',{'form':form} form = MultiPermissionFormSet(request.post) if form.is_valid(): return redict('url') else: ......... def edit(request): """ 修改 :param request: :return: """ MultiPermissionFormSet = formset_factory(MultiPermissionForm, extra=0) if request.method == 'GET': form = MultiPermissionFormSet('資料') # formset是支援批量修改的所以 這裡傳入的資料一定要是可迭代物件,並且裡面的 資料型別是字典或者物件 return render(request,'list.html',{'form':form} form = MultiPermissionFormSet(request.post) if form.is_valid(): return redict('url') else: .........
<div class="luffy-container"> <form method="post" action="?type=generate"> {% csrf_token %} {{ form.management_form }} # 這裡一定要記得寫這一步 <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"> <i class="fa fa-binoculars" aria-hidden="true"></i> 待新建許可權列表 <button class="right btn btn-primary btn-xs" style="padding: 2px 8px;margin: -3px;"> <i class="fa fa-save" aria-hidden="true"></i> 新建 </button> </div> <div class="panel-body" style="color: #9d9d9d;"> 注意:路由系統中自動發現且資料庫中不存在的路由。 </div> <table class="table table-bordered"> <thead> <tr> <th>序號</th> <th>名稱</th> <th>URL</th> <th>別名</th> <th>所屬選單</th> <th>根許可權</th> </tr> </thead> <tbody> {% for form in generate_formset %} <tr> <td style="vertical-align: middle;">{{ forloop.counter }}</td> {% for field in form %} # 這裡在渲染標籤的時候一定要渲染 id這個標籤 這個很重要不然會報錯 這裡是寫了兩個fou迴圈 所以自動渲染了id標籤 {% if forloop.first %} <td class="hide"> {% else %} <td> {% endif %} {{ field }}<span style="color: firebrick;">{{ field.errors.0 }}</span> </td> {% endfor %} {% endfor %} </tbody> </table> </div> </form>
modelformset用法
class StudyRecordModelForm(forms.ModelForm): class Meta: model = models.StudyRecord fields = ['student','record','score','homework_note'] def changelist_view(self,request): ccid = request.GET.get('ccid') model_formset_cls = modelformset_factory(models.StudyRecord,StudyRecordModelForm,extra=0) queryset = models.StudyRecord.objects.filter(course_record_id=ccid) if request.method == "GET": formset = model_formset_cls(queryset=queryset)
# 這裡UI定是個可迭代物件,因為modelformset是操作多表的,裡面的資料型別可以為字典或者物件 return render(request,'study_record.html',{'formset':formset}) formset = model_formset_cls(data=request.POST) print(request.POST) if formset.is_valid(): formset.save() return redirect('/stark/crm/studyrecord/list/?ccid=%s' %ccid ) return render(request, 'study_record.html', {'formset': formset})
<div class="panel panel-default"> <div class="panel-heading">學習記錄</div> <div class="panel-body"> <div style="width: 680px;margin: 0 auto;"> <form method="post"> {% csrf_token %} {{ formset.management_form }} # 這裡一定要加這句程式碼 <table class="table table-bordered"> <thead> <tr> <th>姓名</th> <th>考勤</th> <th>作業成績</th> <th>作業評語</th> </tr> </thead> <tbody> {% for form in formset %} <tr> {{ form.id }} # 這裡只寫了一層for迴圈,所以手動寫欄位,必須把id欄位寫上 <td>{{ form.instance.student }}</td> <td>{{ form.record }} {{ form.record.errors.0 }}</td> <td>{{ form.score }} {{ form.score.errors.0 }}</td> <td>{{ form.homework_note }} {{ form.homework_note.errors.0 }}</td> </tr> {% endfor %} </tbody> </table> <input type="submit" value="儲存"> </form> </div> </div> </div>