十四、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)

views.py

MyForm类

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

首先需要实现一个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})

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': <Department: IT部门>, '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})

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 %}
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">新建用户</h3>
            </div>
            <div class="panel-body">
                <form method="post" novalidate>
                    {% csrf_token %}
                    {% for field in form %}
                        <div class="form-group">
                        <label>{{ field.label }}</label>
                        {{ field }}
                        <span style="color: red">{{ field.errors.0 }}</span>
                        </div>
                    {% endfor %}
                    <button type="submit" class="btn btn-primary">提 交</button>
                </form>
            </div>
        </div>
    </div>
{% endblock %}

settings.py

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

相关推荐
Yan-英杰9 分钟前
百度搜索和文心智能体接入DeepSeek满血版——AI搜索的新纪元
图像处理·人工智能·python·深度学习·deepseek
weixin_307779131 小时前
Azure上基于OpenAI GPT-4模型验证行政区域数据的设计方案
数据仓库·python·云计算·aws
玩电脑的辣条哥2 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52352 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
Moon.92 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
垚垚 Securify 前沿站2 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
m0_748256144 小时前
SpringBoot
java·spring boot·后端
多想和从前一样5 小时前
Django 创建表时 “__str__ ”方法的使用
后端·python·django
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js