• 十四、Django之添加用户(django组件Form/ModelForm实现)


    原始方法与Form/ModelForm组件实现的对比

    原始方法实现的缺点有:

    • 用户提交数据没有校验
    • 用户输错信息页面上没有错误提示
    • html文件中每个字段都需要重写
    • 关联的数据是手动获取并循环展示在页面

    Form组件实现的优点有:
    django帮助完成前三点,第四点手动少量代码完成。

    ModelForm实现的优点有:
    django帮助完成全部四点。

    Form实现

    可以见资源的Form压缩包

    ModelForm实现

    Models.py

    注意这里UserInfo里每个字段最好都加上verbose_name,后期有用。
    同时给Department类里加个__str__函数,返回title。

    class Department(models.Model):
        title = models.CharField(verbose_name="标题", max_length=32)
    
        def __str__(self):
            return self.title
    
    class UserInfo(models.Model):
        name = models.CharField(verbose_name="姓名", max_length=32)
        password = models.CharField(verbose_name="密码", max_length=64)
        age = models.IntegerField(verbose_name="年龄")
        account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
        create_time = models.DateTimeField(verbose_name="入职时间")
        gender_choices = (
            (1, "男"),
            (2, "女"),
        )
        gender = models.SmallIntegerField(verbose_name="性别",choices=gender_choices)
        depart = models.ForeignKey(verbose_name="职位", to="Department", to_field="id", on_delete=models.CASCADE)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    views.py

    MyForm类

    class MyForm(ModelForm):
        class Meta:
            model = UserInfo
            fields = {"name","password","age","account","create_time","gender","depart"}
    
    • 1
    • 2
    • 3
    • 4

    首先需要实现一个MyForm类,参数是ModelForm,在这个类里还有一个Meta类。
    Meta类底下有两个字段,第一个字段是model,值是想要映射的models类。第二个字段是fields,值是想要具体映射的models类里面的值,达到了自动获取数据的目的。

    user_add

    如果为GET请求,实例化一个MyForm对象form,然后直接传入模板即可,达到了自动循环展示数据在页面的目的。
    如果为POST请求,实例化一个data为POST的MyForm对象form。该form对象自动提供了一个判断是否为空的函数is_valid(),达到了校验用户提交数据是否为空的目的。同时form对象自动提供了一个save函数,达到了自动更新数据库的目的。

    
    def user_add(request):
        if request.method=="GET":
            form = MyForm()
            return render(request, "user_add.html", {"form": form})
    
        form = MyForm(data=request.POST)
        if form.is_valid():
            form.save()
    
        else:
            print(form.errors)
        return render(request, "user_add.html",{"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    views.py完整代码

    其中的def __init__部分代码是用来循环添加样式的

    class MyForm(ModelForm):
        name = forms.CharField(min_length=3, label='用户名')
    
        class Meta:
            model = UserInfo
            fields = {"name","password","age","account","create_time","gender","depart"}
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            # 循环找到所有实例对象,给其加上样式
            for name, field in self.fields.items():
                if name == "test":
                    continue
                # 如果想要某个对象不加该样式,判断名字即可。
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}
    
    
    def user_add(request):
        if request.method=="GET":
            form = MyForm()
            return render(request, "user_add.html", {"form": form})
    
        form = MyForm(data=request.POST)
        if form.is_valid():
            print(form.cleaned_data)
            # {'name': 'yaqin Shan', 'age': 20, 'depart': , 'create_time': datetime.datetime(2020, 1, 11, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'account': Decimal('10'), 'password': '666', 'gender': 2}
            form.save()
    
        else:
            print(form.errors)
        return render(request, "user_add.html",{"form": form})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    user_add.html

    novalidate:是用来关闭浏览器的自动校验提交数据的
    {{ field.label }},能让django拿到models里UserInfo定义时每个字段的verbose_name的值
    {{ field }},说明field传入模板后,django自动将其转换成了html标签,且注意,像是性别这种含有元组的代码,django会自动识别成选择下拉标签,职位这种有外键的代码,django也会自动识别成选择下拉标签。
    {{ field.errors.0 }},说明django会自动封装报错信息给field,我们只需要拿到第一个即可。

    {% extends 'layout.html' %}
    {% block content %}
        

    新建用户

    {% csrf_token %} {% for field in form %}
    {{ field }} {{ field.errors.0 }}
    {% endfor %}
    {% endblock %}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    settings.py

    最后,如果想要页面显示的错误信息是中文的话,只需要settings.py中修改成LANGUAGE_CODE = "zh-hans"即可。

  • 相关阅读:
    【C字符串函数】——对C语言中有关字符串库函数的实现及模拟
    不到200一个成长枪皮?成长枪皮返厂,普适性入手方案都在这了
    【Paper】2021_有向间歇通讯下多智能体系统的一致性
    Leetcode 137. Single Number II (Python)
    【c++随笔08】可变参数——va_list、va_start、va_end、va_arg
    windows环境下安装logstash同步数据,注册系统服务
    RabbitMQ系列【18】对象序列化机制
    muduo源码剖析之Timer定时器
    MySQL 清空分区表单个分区数据
    java从入门到精通二十九(Spring测试环境的简单部署)
  • 原文地址:https://blog.csdn.net/zhiaidaidai/article/details/133529730