zoukankan      html  css  js  c++  java
  • django中的form modelform formset modelformset

    首先上结论:

      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=" 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>                  
  • 相关阅读:
    tyvj1463 智商问题
    P1070 道路游戏
    P1862 输油管道问题
    P1875 佳佳的魔法药水
    P1498 南蛮图腾
    P1489 猫狗大战
    P1395 会议(求树的重心)
    P2285 [HNOI2004]打鼹鼠
    P3819 松江1843路(洛谷月赛)
    P3818 小A和uim之大逃离 II(洛谷月赛)
  • 原文地址:https://www.cnblogs.com/chenxi67/p/10008451.html
Copyright © 2011-2022 走看看