15 forms和modelForm

1 forms组件

1-1 创建Django项目

  • 创建项目

    django-admin startproject formsdemo
    
  • 创建app

    python manage.py startapp app01
    
  • 配置settings

    INSTALLED_APPS = [
    	...
        'app01'
    ]
    
  • 表创建

    from django.db import models
    
    class UserInfo(models.Model):
        name=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        email=models.EmailField()
        tel=models.CharField(max_length=32)
    
  • 数据库迁移

    # python manage.py makemigrations
    # python manage.py migrate
    

1-2 注册接口

  • urls.py

    from django.contrib import admin
    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('reg/', views.reg),
    ]
    

1-3 forms校验字段值

  • app01\views.py

    from django.shortcuts import render, HttpResponse
    from django import forms
    
    
    class UserForm(forms.Form):
        """
        注意:
        1.校验的字段名,必须要与前端的的name属性值一致
        2.CharField默认都有一个不为空的约束
        """
        user = forms.CharField(min_length=3)
        pwd = forms.CharField(min_length=3)
        r_pwd = forms.CharField(min_length=3)
        email = forms.EmailField()
        tel = forms.CharField()
    
    
    def reg(request):
        if request.method == "POST":
            # print(request.POST)  # 返回字典类型
            form = UserForm(request.POST)
            """
            # 返回True或False
            校验字段,如果校验的字段全部通过则返回True,反之一个不通过返回False。
            前端传入多余的字段,在forms中没有对应字段匹配则不做校验。
            forms只匹配自定义的字段。
            """
            print(form.is_valid())  # 返回bool值
            if form.is_valid():
                print(form.cleaned_data)  # 返回校验成功的值
            else:
                print(form.cleaned_data)  # 存放部分校验成功的值
                print(form.errors)  # 返回所有校验错误的值,ErrorDict类型
                print(form.errors.get('name')[0])  # 打印name字段的错误信息
    
            return HttpResponse("ok")
    
        return render(request, 'reg.html')
    
  • templates/reg.html

    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:<input type="text" name="user" id=""></p>
        <p>密码:<input type="text" name="pwd" id=""></p>
        <p>确认密码:<input type="text" name="r_pwd" id=""></p>
        <p>邮箱:<input type="text" name="email" id=""></p>
        <p>手机号:<input type="text" name="tel" id=""></p>
        <input type="submit">
    </form>
    

1-4 forms渲染标签

1-4.1 方式一

  • app01\views.py

    from django.shortcuts import render, HttpResponse
    from django import forms
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3)
        pwd = forms.CharField(min_length=3)
        r_pwd = forms.CharField(min_length=3)
        email = forms.EmailField()
        tel = forms.CharField()
        """
        CharField 渲染出input标签 text类型
        EmailField 渲染出input标签 email类型
        """
    
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)
            print(form.is_valid()) 
            if form.is_valid():
                print(form.cleaned_data)  
            else:
                print(form.errors) 
            return HttpResponse("ok")
    
        form = UserForm()
        return render(request, 'reg.html', {'form': form})
    
  • templates/reg.html

    <h1>渲染方式1</h1>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        <p>用户名:{{ form.user }}</p>
        <p>密码:{{ form.pwd }}</p>
        <p>确认密码:{{ form.r_pwd }}</p>
        <p>邮箱:{{ form.email }}</p>
        <p>手机号:{{ form.tel }}</p>
        <input type="submit">
    </form>
    

image

1-4.1 方式二

  • app01\views.py

    from django.shortcuts import render, HttpResponse
    from django import forms
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3, label='用户名:')
        pwd = forms.CharField(min_length=3, label='密码:')
        r_pwd = forms.CharField(min_length=3, label='确认密码:')
        email = forms.EmailField(label='邮箱:')
        tel = forms.CharField(label='手机号:')
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)
            print(form.is_valid()) 
            if form.is_valid():
                print(form.cleaned_data)  
            else:
                print(form.errors) 
            return HttpResponse("ok")
    
        form = UserForm()
        return render(request, 'reg.html', {'form': form})
    
  • templates/reg.html

    <hr>
    <h1>渲染方式2</h1>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        {% for field in form %}
            <p><label for="">{{ field.label }}</label>{{ field }}</p>
        {% endfor %}
        <input type="submit">
    </form>
    

image

1-4.1 方式三

  • app01\views.py

    from django.shortcuts import render, HttpResponse
    from django import forms
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3, label='用户名:')
        pwd = forms.CharField(min_length=3, label='密码:')
        r_pwd = forms.CharField(min_length=3, label='确认密码:')
        email = forms.EmailField(label='邮箱:')
        tel = forms.CharField(label='手机号:')
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)
            print(form.is_valid()) 
            if form.is_valid():
                print(form.cleaned_data)  
            else:
                print(form.errors) 
            return HttpResponse("ok")
    
        form = UserForm()
        return render(request, 'reg.html', {'form': form})
    
  • templates/reg.html

    <hr>
    <h1>渲染方式3</h1>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit">
    </form>
    
    // {{form.as_ul}}
    // {{form.as_table}}
    

image

1-5 forms渲染错误信息

  • app01\views.py

    from django.shortcuts import render
    from django import forms
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3, label='用户名:')
        pwd = forms.CharField(min_length=3, label='密码:')
        r_pwd = forms.CharField(min_length=3, label='确认密码:')
        email = forms.EmailField(label='邮箱:')
        tel = forms.CharField(label='手机号:')
    
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)  # 已绑定数据的表单对象
            if form.is_valid():
                print(form.cleaned_data)
            else:
                # form有错误信息携带,并保上次输入正确的内容
                return render(request, 'reg.html', {'form': form})
    
        form = UserForm()  # 未绑定数据的表单对象
        return render(request, 'reg.html', {'form': form})
    
  • templates/reg.html

    <h1>渲染方式2</h1>
    <form action="" method="post">
        {% csrf_token %}
        {% for field in form %}
            <p>
                <label for="">{{ field.label }}</label>{{ field }}
                <span>{{ form.errors.0 }}</span>
            </p>
        {% endfor %}
        <input type="submit">
    </form>
    

1-6 forms参数的配置

  • app01\views.py

    from django.shortcuts import render
    from django import forms
    from django.forms import widgets
    from django.core.validators import RegexValidator
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3, label='用户名:',
                               error_messages={'required': "该字段不能为空"},
                               widget=widgets.TextInput(attrs={"class": "form-control"}))
        pwd = forms.CharField(min_length=3, label='密码:',
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        r_pwd = forms.CharField(min_length=3, label='确认密码:',
                                widget=widgets.TextInput(attrs={"class": "form-control"}))
        email = forms.EmailField(label='邮箱:',
                                 error_messages={'invalid': "格式错误"},
                                 widget=widgets.EmailInput(attrs={"class": "form-control"}))
        tel = forms.CharField(label='手机号:',
                              widget=widgets.TextInput(attrs={"class": "form-control"}),
                             help_text="请输入11位整数的手机号。。", initial='13513512222',
      					   required=True, validators=[RegexValidator(r'^[0-9]+$', '密码必须是数字')],)
    
        """
        - widget=widgets.PasswordInput 修改字段类型
        - error_messages={'invalid': "格式错误"} 错误信息提示为中文
        - error_messages={'required': "不能为空错误"} 错误信息提示为中文
          另一种方式:修改settings文件:LANGUAGE_CODE = 'zh-Hans'
        - attrs={"class": "form-control"}  添加属性
        - help_text="请输入11位整数的手机号。。"  备注提示信息
        - initial='哈哈哈哈'   前端输入框展示默认信息"哈哈哈哈"
        - required=True  该字段必填,不填就报错
        - validators=[]  正则校验
        """
    
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)  # 已绑定数据的表单对象
            if form.is_valid():
                print(form.cleaned_data)
            else:
                # form有错误信息携带,并保上次输入正确的内容
                return render(request, 'reg.html', {'form': form})
    
        form = UserForm()  # 未绑定数据的表单对象
        return render(request, 'reg.html', {'form': form})
    

    扩展:如果每次都要手动输入widget参数,会很麻烦,我们可以这样做:

    class UserForm(forms.Form):
        user = forms.CharField(label='用户名:')
        pwd = forms.CharField(abel='密码:')
     
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            for name, field in self.fields.items():
                # name为字段,field为对象
                # if name == "title":
                #     continue
                field.widget.attrs['class'] = "form-control"
                field.widget.attrs['placeholder'] = "请输入{}".format(field.label)
    
  • templates\reg.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="../static/css/bootstrap.css">
    </head>
    <body>
    
    
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1>渲染方式2</h1>
                <form action="" method="post">
                    {% csrf_token %}
                    {% for field in form %}
                        <p>
                            <label for="">{{ field.label }}</label>{{ field }}
                            <span>{{ form.errors.0 }}</span>
                            {% if field.help_text %}
                            	<span style="font-weight: 400;color: #333333;">({{ field.help_text }})</span>
                            {% endif %}
                        </p>
                    {% endfor %}
                    <input type="submit">
                </form>
            </div>
        </div>
    </div>
    </body>
    </html>
    

1-7 forms局部钩子

  • app01\views.py

    from django.shortcuts import render
    from django import forms
    from django.forms import widgets
    from app01.models import UserInfo
    from django.core.exceptions import ValidationError
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3, label='用户名:',
                               error_messages={'required': "该字段不能为空"},
                               widget=widgets.TextInput(attrs={"class": "form-control"}))
        pwd = forms.CharField(min_length=3, label='密码:',
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        r_pwd = forms.CharField(min_length=3, label='确认密码:',
                                widget=widgets.TextInput(attrs={"class": "form-control"}))
        email = forms.EmailField(label='邮箱:',
                                 error_messages={'invalid': "格式错误"},
                                 widget=widgets.EmailInput(attrs={"class": "form-control"}))
        tel = forms.CharField(label='手机号:',
                              widget=widgets.TextInput(attrs={"class": "form-control"}))
    
        def clean_user(self):
            val = self.cleaned_data.get('user')
            ret = UserInfo.objects.filter(name=val)
            if not ret:
                return val
            else:
                raise ValidationError('该用户已注册')
    
        def clean_tel(self):
            val = self.cleaned_data.get('tel')
            if len(val) == 11:
                return val
            else:
                raise ValidationError('手机号格式错误')
    
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)  # 已绑定数据的表单对象
            if form.is_valid():
                print(form.cleaned_data)
            else:
                return render(request, 'reg.html', {'form': form})
    
        form = UserForm()  # 未绑定数据的表单对象
        return render(request, 'reg.html', {'form': form})
    
    
  • templates\reg.html

    <form action="" method="post">
        {% csrf_token %}
        {% for field in form %}
        <p>
            <label for="">{{ field.label }}</label>{{ field }}
            <span>{{ form.errors.0 }}</span>
        </p>
        {% endfor %}
        <input type="submit">
    </form>
    

1-8 forms全局钩子

  • app01\views.py

    from django.shortcuts import render
    from django import forms
    from django.forms import widgets
    from app01.models import UserInfo
    from django.core.exceptions import ValidationError
    
    
    class UserForm(forms.Form):
        user = forms.CharField(min_length=3, label='用户名:',
                               error_messages={'required': "该字段不能为空"},
                               widget=widgets.TextInput(attrs={"class": "form-control"}))
        pwd = forms.CharField(min_length=3, label='密码:',
                              widget=widgets.PasswordInput(attrs={"class": "form-control"}))
        r_pwd = forms.CharField(min_length=3, label='确认密码:',
                                widget=widgets.TextInput(attrs={"class": "form-control"}))
        email = forms.EmailField(label='邮箱:',
                                 error_messages={'invalid': "格式错误"},
                                 widget=widgets.EmailInput(attrs={"class": "form-control"}))
        tel = forms.CharField(label='手机号:',
                              widget=widgets.TextInput(attrs={"class": "form-control"}))
    
        def clean_user(self):
            val = self.cleaned_data.get('user')
            ret = UserInfo.objects.filter(name=val)
            if not ret:
                return val
            else:
                raise ValidationError('该用户已注册')
    
        def clean_tel(self):
            val = self.cleaned_data.get('tel')
            if len(val) == 11:
                return val
            else:
                raise ValidationError('手机号格式错误')
    
        def clean(self):
            pwd = self.cleaned_data.get('pwd')
            r_pwd = self.cleaned_data.get('r_pwd')
            if pwd and r_pwd:
                if pwd == r_pwd:
                    return self.cleaned_data
                else:
                    raise ValidationError('两次密码不一致')
            else:
                return self.cleaned_data
    
    
    def reg(request):
        if request.method == "POST":
            form = UserForm(request.POST)  # 已绑定数据的表单对象
            if form.is_valid():
                print(form.cleaned_data)
            else:
                # 全局钩子错误
                errors = form.errors.get('__all__')
                return render(request, 'reg.html', {'form': form, 'errors': errors})
    
        form = UserForm()  # 未绑定数据的表单对象
        return render(request, 'reg.html', {'form': form})
    
    
  • templates\reg.html

    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:{{ form.user }}<span>{{ form.errors.0 }}</span></p>
        <p>密码:{{ form.pwd }}<span>{{ form.errors.0 }}</span></p>
        <p>确认密码:{{ form.r_pwd }}<span>{{ errors.0 }}</span></p>
        <p>邮箱:{{ form.email }}<span>{{ form.errors.0 }}</span></p>
        <p>手机号:{{ form.tel }}<span>{{ form.errors.0 }}</span></p>
        <input type="submit">
    </form>
    

1-9 forms的默认选中

  • form或modelForm显示默认值

    form = LevelForm(initial={'title': "xxx"})
    

2 modelForm组件

在写表单的时候,会发现表单中的Field和模型中的Field基本上是一模一样的。而且一般情况下表单中需要验证的数据就是我们模型中需要保存的数据。那么这个时候我们就可以将模型中的字段和表单中的字段进行绑定。

modelform是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来。

比如我们的数据库中有这样一张学生表,字段有姓名,年龄,爱好,邮箱,电话,住址,注册时间等等一大堆信息,现在让你写一个创建学生的页面,你的后台应该怎么写呢?

  • 前端:首先会在前端一个一个罗列出这些字段,让用户去填写,然后后台一个一个接收用户的输入
  • 后台:定义一个学生模型,用来保存学生信息
  • 后台:定义一个学生表单,用来验证前端传递过来的数据
  • 后台:在视图函数中使用get()方法来一个一个的获取已通过验证的数据,然后使用模型中的QuerySet方法将数据保存起来

在上面示例中:其实表单的定义和模型的定义其实是差不多的,但是如果按照上面这种方式来的话,一个差不多的东西我们就需要完整的定义两边,这样就显得混麻烦了。因此Django就提供了ModelForm组件:这个组件主要就是用来整合表单和模型,将它们两个连接起来使用。就不需要完整的定义两次了。

2-1 modelform所有属性

image

2-2 创建一个Django项目

  • 创建项目

    django-admin startproject modelformdemo
    
  • 创建app

    python manage.py startapp app01
    
  • 配置settings

    INSTALLED_APPS = [
    	...
        'app01'
    ]
    
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    STATICFILES_DIRS = [
        os.path.join(STATIC_ROOT, "css"),
        os.path.join(STATIC_ROOT, "js"),
    ]
    
  • 表创建

    from django.db import models
    
    class Student(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        birth = models.DateField()
        email = models.EmailField()  # 根modelForm有关系的字段类型EmailField
        createDate = models.DateField(auto_now_add=True)
    
  • 数据库迁移

    # python manage.py makemigrations
    # python manage.py migrate
    

2-3 构建前端页面

  • urls.py

    from django.contrib import admin
    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('addstu/', views.addstu),
    ]
    
  • app01\views.py

    from django.shortcuts import render
    from django.forms import ModelForm
    from app01.models import Student
    from django.forms import widgets as wid
    from django import fomrs 
    
    
    class StudentModelForm(ModelForm):
        class Meta:
            model = Student
            # fields = "__all__"  # 校验所有字段
            # fields = ['name', 'age', 'email', 'birth']  # 想要校验的字段
            exclude = ['createDate']  # 除去该字段其它都校验
            labels = {'name': '用户名', 'age': '年龄'}  # 定制前端显示的字段名(如果没写,则是models中verbose_name的字段名)
            # ModelForm默认不能为空,除非models中,black和null都等于True,则代表可以为空,
            # models中可添加字段:help_text="啊哈哈",可体现在前端中的label
            # widgets 添加字段的属性
            widgets = {'name': wid.TextInput(attrs={'class': 'form-control'}),
                       'age': wid.NumberInput(attrs={'class': 'form-control'}),
                       'email': wid.EmailInput(attrs={'class': 'form-control'}),
                       'birth': wid.DateInput(attrs={'class': 'form-control', 'type': 'date'})}
            """
            # 也可以这样写:
            widgets = {'name': fomrs.TextInput(attrs={'class': 'form-control'}),
                       'age': fomrs.NumberInput(attrs={'class': 'form-control'}),
                       'email': fomrs.EmailInput(attrs={'class': 'form-control'}),
                       'birth': fomrs.DateInput(attrs={'class': 'form-control', 'type': 'date'})}
            """
    
    
    def addstu(request):
        if request.method == "GET":
            modelform = StudentModelForm()
    
            return render(request, 'addstu.html', {'modelform': modelform})
    
    

    扩展:如果每次都要手动输入widget参数,会很麻烦,我们可以这样做:

    class LevelModelForm(forms.ModelForm):
        class Meta:
            model = models.Level
            fields = ["title", "percent"]
            
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            for name, field in self.fields.items():
                # name为字段,field为对象
                # if name == "title":
                #     continue
                field.widget.attrs['class'] = "form-control"
                field.widget.attrs['placeholder'] = "请输入{}".format(field.label)
    
  • templates/addstu.html

    <h3>添加学生</h3>
    <form action="">
        {% for form in modelform %}
        <div class="form-group">
            <label for="">{{ form.label }}</label>
            <p>{{ form }}</p>
        </div>
        {% endfor %}
        <input type="submit" class="btn btn-primary">
    </form>
    

2-4 添加功能实现

  • urls.py

    from django.contrib import admin
    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('addstu/', views.addstu),
        path('index/', views.index),
    ]
    
  • app01/views.py

    from django.shortcuts import render, redirect
    from django.forms import ModelForm
    from app01.models import Student
    from django.forms import widgets as wid
    from django.http import JsonResponse
    
    
    class StudentModelForm(ModelForm):
        
        """
        def __init__(self):
        super(StudentModelForm, self).__init__()
        # 统一给ModelForm生成字段添加样式
        for name, field in self.fields.items():
        	field.widget.attrs['class'] = 'form-control'
        """
        
        class Meta:
            model = Student
            exclude = ['createDate']  # 除去该字段其它都校验
            labels = {'name': '用户名', 'age': '年龄'}  # 定制前端显示的字段名
            # widgets 添加字段的属性
            widgets = {'name': wid.TextInput(attrs={'class': 'form-control'}),
                       'age': wid.NumberInput(attrs={'class': 'form-control'}),
                       'email': wid.EmailInput(attrs={'class': 'form-control'}),
                       'birth': wid.DateInput(attrs={'class': 'form-control', 'type': 'date'})}
    
    
    def addstu(request):
        if request.method == "GET":
            modelform = StudentModelForm()
            return render(request, 'addstu.html', {'modelform': modelform})
        if request.method == "POST":
            # 添加功能
            modelform = StudentModelForm(request.POST)
            if modelform.is_valid():  # 校验数据
                modelform.save()
                return redirect('/index/')
            else:
                return JsonResponse(modelform.errors)
    
    
    def index(request):
        students = Student.objects.all()
        return render(request, 'index.html', locals())
    
  • templates/addstu.html

    <h3>添加学生</h3>
    <form action="" method="post">
        {% csrf_token %}
        {% for form in modelform %}
        <div class="form-group">
            <label for="">{{ form.label }}</label>
            <p>{{ form }}</p>
        </div>
        {% endfor %}
        <input type="submit" class="btn btn-primary">
    </form>
    
  • templates/index.html

    <h3>学生信息</h3>
    <a class="btn btn-success" href="/addstu/" style="margin: 5px 0">添加学生</a>
    <table class="table table-bordered">
        <tr>
            <td>序号</td>
            <td>姓名</td>
            <td>年龄</td>
            <td>生日</td>
            <td>邮箱</td>
        </tr>
        {% for stu in students %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ stu.name }}</td>
            <td>{{ stu.age }}</td>
            <td>{{ stu.birth|date:'Y-m-d' }}</td>
            <td>{{ stu.email }}</td>
        </tr>
        {% endfor %}
    </table>
    

2-5 编辑功能实现

  • urls.py

    from django.contrib import admin
    from django.urls import path, re_path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('addstu/', views.addstu),
        path('index/', views.index),
        re_path('editstu/(\d+)', views.editstu),
    ]
    
  • app01/views.py

    from django.shortcuts import render, redirect
    from django.forms import ModelForm
    from app01.models import Student
    from django.forms import widgets as wid
    from django.http import JsonResponse
    
    
    class StudentModelForm(ModelForm):
        def __init__(self):
            super(StudentModelForm, self).__init__()
            # 统一给ModelForm生成字段添加样式
            for name, field in self.fields.items():
                field.widget.attrs['class'] = 'form-control'
    
        class Meta:
            model = Student
            # fields = "__all__"  # 校验所有字段
            # fields = ['name', 'age', 'email', 'birth']  # 想要校验的字段
            exclude = ['createDate']  # 除去该字段其它都校验
            labels = {'name': '用户名', 'age': '年龄'}  # 定制前端显示的字段名
    
    
    def addstu(request):
        if request.method == "GET":
            modelform = StudentModelForm()
            return render(request, 'addstu.html', {'modelform': modelform})
        if request.method == "POST":
            # 添加功能
            modelform = StudentModelForm(data=request.POST)
            if modelform.is_valid():  # 校验数据
                modelform.save()
                return redirect('/index/')
            else:
                return JsonResponse(modelform.errors)
    
    
    def index(request):
        students = Student.objects.all()
        return render(request, 'index.html', locals())
    
    
    def editstu(request, edit_id):
        stu_obj = Student.objects.get(pk=edit_id)
        if request.method == "GET":
            modelform = StudentModelForm(instance=stu_obj)
            return render(request, 'editstu.html', locals())
        else:
            modelform = StudentModelForm(data=request.POST, instance=stu_obj)
            if modelform.is_valid():
                modelform.save()  # 数据更新操作
                return redirect('/index/')
            else:
                return JsonResponse(modelform.errors)
    
  • templates/editstu.html

    <h3>添加学生</h3>
    <form action="" method="post">
        {% csrf_token %}
        {% for form in modelform %}
        <div class="form-group">
            <label for="">{{ form.label }}</label>
            <p>{{ form }}</p>
        </div>
        {% endfor %}
        <input type="submit" class="btn btn-primary">
    </form>
    

2-6 默认选中

  • modelForm显示默认值

    def level_edit(request, pk):
        level_object = models.Level.objects.filter(id=pk, active=1).first()
    
        if request.method == "GET":
            form = LevelModelForm(instance=level_object)
            return render(request, 'form.html', {"form": form})
    
        form = LevelModelForm(request.POST, instance=level_object)
        if not form.is_valid():
            return render(request, 'form.html', {"form": form})
    
        form.save()
    
        return redirect(reverse("level_list"))
    

2-7 添加额外字段

class LevelModelForm(BootStrapForm, forms.ModelForm):
    xxx = forms.CharField(label='xxx')

    class Meta:
        model = models.Level
        # fields = "__all__"
        # exclude = ['active']
        fields = ['title', 'xxx', 'percent', ]
class LevelModelForm(BootStrapForm, forms.ModelForm):
    title = forms.ChoiceField(label='xxx', choices=((1, "xxx"), (2, "xxxxxx")))

    class Meta:
        model = models.Level
        # fields = "__all__"
        # exclude = ['active']
        fields = ['title', 'percent', ]

2-8 生成HTML标签 + 插件 + 和 参数的配置

class LevelModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent', ]
        widgets = {
            'name': forms.PasswordInput(render_value=True)
			# render_value=True 保留密码字段框不清空
        }

2-9 表单验证

class LevelModelForm(BootStrapForm, forms.ModelForm):
    class Meta:
        model = models.Level
        fields = ['title', 'percent', ]

    def clean_percent(self):
        value = self.cleaned_data['percent']
        return value
class LevelModelForm(BootStrapForm, forms.ModelForm):
    title = forms.CharField(validators=[])
    class Meta:
        model = models.Level
        fields = ['title', 'percent', ]

    def clean_percent(self):
        value = self.cleaned_data['percent']
        return value

2-10 新增,更新

form = LevelModelForm(data=request.POST)
form.save()
form = LevelModelForm(data=request.POST,install=对象)
form.save()
form = LevelModelForm(data=request.POST) # 或有 ,install=对象

form.instance.percent = 10
form.save()
class LevelModelForm(BootStrapForm, forms.ModelForm):
    confirm_percent = forms.CharField(label="确认")

    class Meta:
        model = models.Level
        fields = ['title', 'percent']
        

def level_add(request):
    if request.method == "GET":
        form = LevelModelForm()
        return render(request, 'form.html', {"form": form})

    form = LevelModelForm(data=request.POST)
    if not form.is_valid():
        return render(request, 'form.html', {"form": form})

    # {'title': '1', 'percent': 2, 'confirm_percent': '3'}
    print(form.cleaned_data)
    # form.instance.percent = 10
    form.save()

    return redirect(reverse('level_list'))

Form组件和ModelForm的区别

  1. ModelFormDjango Model.pyForm组件的结合体,可以简单、快速使用 Form验证和数据库操作功能,但不如Form组件灵活
  2. 如果在使用Django做web开发过程中验证的数据和数据库字段相关(可以对表进行增、删、改操),建议优先使用ModelForm,用起来更方便些。
  3. ModelForm适合中小型应用程序。因为ModelForm是依赖于models的。而Form更适合大型应用程序。

Django中Model负责操作数据库,并且具有简单的数据库验证功能(基本不用);Form用于用户请求的验证,具有强悍的数据库验证功能;ModelForm是将二者合二为一,即可用于数据库操作(部分),也可用于用户请求的验证(部分)。但由于ModelForm的耦合性太强,其作用一般用作于结构简单的小站点

基本:用户验证一类使用Form,增删改查用ModelForm。

其他补充:

Djangocssjs等引入方式1

templates\reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="../static/css/bootstrap.css">
</head>
<body>
...
</body>
</html>

Djangocssjs等引入方式2

templates\reg.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
</head>
<body>
...
<script type="text/javascript" src="{% static 'js/bootstrap.js' %}"></script>
</body>
</html>

settings.py

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

STATICFILES_DIRS = [
    os.path.join(STATIC_ROOT, "css"),
    os.path.join(STATIC_ROOT, "js"),
]
posted @ 2022-08-11 17:55  角角边  Views(87)  Comments(0)    收藏  举报