Django之modelform使用

Django新增修改数据功能优化

目录

1.新增数据功能优化

2.修改数据功能优化

在我们做数据优化处理之前, 我们先回顾下传统的写法, 是如何实现增加修改的。

我们需要在templates里面新建前端的页面, 需要有新增还要删除, 比如说员工数据的新增, 那需要有很多个输入框, 那html结构里面, 都需要一一写入label, input, 选择框select里面配合option这样的组件。包括在后端写代码的时候, 在user.py那个views里面, 新增函数里面需要列出每一个字段并赋值, 就像以下代码:

python 复制代码
name = request.POST.get("name")
age = request.POST.get("age")
gender = request.POST.get("gender")
salary = request.POST.get("salary")
dtime = request.POST.get("dtime")
depart = request.POST.get("depart")

这样的写法, 会显得非常冗余, 代码质量不高, 这篇文章, 我们就是要解决这种问题的, 优化新增和修改功能, 使代码质量变得更高, 不出现冗余代码的情况(前端和后端代码需要达成的一致要求)。

还要一点就是传统的写法, 它没有数据校验功能。

那这篇文章, 我们要讲的是modelform, 它可以很好的解决我们上面所提到的一些问题。

一、新增数据功能优化

我们打开user.py, 编辑以下代码:

python 复制代码
class userInfoModelForm(forms.ModelForm):
    name = forms.CharField(min_length=2, label="姓名")
    class Meta:
        model = models.UserInfo
        # 在UserInfo表给里面指定的字段可使用
        # fields = ["name", "gender"] # 代表可以用name和gender这两个字段
        # 所有的UserInfo表格的字段都使用
        fields = "__all__"
        # 相当于代替了之前的以下代码:
        #name = request.POST.get("name")
        # age = request.POST.get("age")
        # gender = request.POST.get("gender")
        # salary = request.POST.get("salary")
        # dtime = request.POST.get("dtime")
        # depart = request.POST.get("depart")
        # 如果是想要某张表格的某个字段不想用, 那就可以用exclude
        # exclude = ["create_time"]

    # 由于我们的userInfoModelForm类继承了forms.ModelForm类, 所以我们写构造函数的时候, 需要传入*args, **kwargs这两个参数
    def __init__(self, *args, **kwargs):
        super(userInfoModelForm, self).__init__(*args, **kwargs)
        # item是属性名, field是属性值
        for item, field in self.fields.items():
            # 给输入框input增加一个class属性
            field.widget.attrs.update({"class": "form-control"})

然后我们继续写添加函数在user.py里面:

python 复制代码
def user_add_modelform(request):
    if request.method == "GET":
        title = "添加信息2.0版本"
        form = userInfoModelForm()
        return render(request, "user/user_modelform.html", {"title": title, "form": form})
    # 接受表单提交过来的数据
    form = userInfoModelForm(request.POST)
    # 校验数据是否完整
    if form.is_valid():
        # 存储到数据库
        form.save()
        return redirect("/user/")
    # 如果数据不完整,则返回当前添加页面,展示错误信息
    return render(request, "user/user_modelform.html", {"form": form})

这里我们需要创建一个userInfoModelForm对象。并将它传给前端。需要注意的是form = userInfoModelForm(request.POST)这行代码, 里面需要加request.POST, 这个是为了接受表单提交过来的数据, 提交表单数据, 就是用的POST方法。所以这里必须要加request.POST。

我们在templates里面的user文件夹里, 创建user_modelform.html:

html 复制代码
{% extends "index/model_tmp.html" %}
{% load static %}

{% block css %}
    <link rel="stylesheet" href="{% static 'css/layui.css' %}">
{% endblock %}

{% block content %}
    <div class="container">
        <h1>{{ title }}</h1>
        <form method="post">
            {% csrf_token %}
            {% for filed in form %}
{#       filed.label这里面就是获取我们在models.py里面创建表格里面的每一个字段里面有个verbose_name这个参数的值         #}
                <label for="exampleInputEmail1">{{ filed.label }}</label>
                {{ filed }}
                {#       展示错误信息         #}
                <span style="color: red">{{ filed.errors.0 }}</span>
                <br>
            {% endfor %}
            <button type="submit" class="btn btn-success">提交</button>
        </form>
    </div>
{% endblock %}

{% block js %}
    <script src="{% static "js/layui.js" %}"></script>
    <script>
        layui.use(function () {
            var laydate = layui.laydate;
            // 渲染
            laydate.render({
                // 这个id是员工入职时间的那个input输入框的id, 我们使用了modelform, 它会自动给我们每一个input都会生成一个id,
                // 格式为id_数据库字段名, 我们数据库员工表格里面的员工入职时间的那个字段是create_time, 所以id是id_create_time。
                elem: '#id_create_time'
            });
        });
    </script>
{% endblock %}

我们可以从代码中发现, 我们前端不用再一一的去写input, select那种输入框选择框了, filed就是input, 要展现label组件, 那就是filed.label, 如果提交表单之后有错误信息的话, 那就展示错误信息, 用filed.errors.0来展示, 还有, modelform它会帮我们每一个input输入框都会自动创建id, 就比如我们员工入职的时间那栏, id为id_create_time, 所以下面的script标签里面, 那个elem参数要写#id_create_time。

urls.py:

python 复制代码
"""project_simple URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from project_one.views import depart, user

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("", depart.index),
    path("depart/", depart.depart),
    path("depart/add/", depart.add_depart),
    path("depart/<int:nid>/modify/", depart.depart_modify),
    path("depart/<int:nid>/del/", depart.del_depart),
    path("user/", user.user_info),
    path("user/add/", user.user_add),
    path("user/<int:nid>/modify/", user.user_modify),
    path("user/<int:nid>/del/", user.user_del),
    # 使用modelform来解决新增
    path("user/add/modelform", user.user_add_modelform)
]

完善user_list.html:

html 复制代码
{% extends "index/model_tmp.html" %}

{% block content %}

    <div class="container">
        <a href="/user/add/" class="btn btn-success">添加信息</a>
        {#  这个是优化过的新增功能  #}
        <a href="/user/add/modelform" class="btn btn-warning">添加信息</a>
        <div class="panel panel-danger">
            <div class="panel-heading">
                <h3 class="panel-title">部门表</h3>
            </div>
            <div class="panel-body">
                <table class="table table-hover">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>性别</th>
                        <th>薪水</th>
                        <th>年龄</th>
                        <th>入职时间</th>
                        <th>部门</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for data in user_list %}
                        <tr>
                            <th scope="row">{{ data.id }}</th>
                            <td>{{ data.name }}</td>
                            <td>{{ data.get_gender_display }}</td>
                            <td>{{ data.salary }}</td>
                            <td>{{ data.age }}</td>
                            <td>{{ data.create_time|date:"Y-m-d" }}</td>
                            <td>{{ data.department.title }}</td>
                            <td style="color: green">
                                <a href="/user/{{ data.id }}/modify/"><span style="color: green;" class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
                                <a href="/user/{{ data.id }}/del/"><span style="color: red;" class="glyphicon glyphicon-trash" aria-hidden="true"></span></a>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
{% endblock %}

运行结果:

点击右边黄色按钮的添加信息

由此可见, 我们成功的添加了数据。

二、修改数据功能优化

修改功能, 和刚才那个新增功能, 有异曲同工之妙, 但也有天壤之别。

我们同样的打开user.py:

python 复制代码
def user_modify_modelform(request, nid):
    # 获取要修改的那行数据
    obj = models.UserInfo.objects.filter(id=nid).first()
    if request.method == "GET":
        title = "修改信息2.0版本"
        # 这个代码的作用是当我们进入user_modelform.html界面的时候, 所有的输入框都会出现需要修改数据中的每一个字段内容里面的文字
        form = userInfoModelForm(instance=obj)
        return render(request, "user/user_modelform.html", {"title": title, "form": form})
    # 接受表单提交过来的数据
    form = userInfoModelForm(request.POST, instance=obj)
    # 校验数据是否完整
    if form.is_valid():
        # 存储到数据库
        form.save()
        return redirect("/user/")
    # 如果数据不完整,则返回当前修改页面,展示错误信息
    return render(request, "user/user_modelform.html", {"form": form})

这里面多了个obj = models.UserInfo.objects.filter(id=nid).first()这行代码, 因为我们修改某一行数据的时候, 需要先获取要修改的那行的所有数据, 并且展示到每一个输入框里面, 这样我们在做修改的时候, 才知道我们需要修改哪一行数据, 避免混淆。还有, 就是在创建userInfoModelForm对象的时候, 里面要传入instance参数, instance要传入的值就是我们获取到要修改的那行数据。其他的写法, 都和上面的新增数据一样。

这里面, 我们新增数据和修改数据, 都是用的同一个html文件, 都是user_modelform.html, 我们把它作为了新增和修改的公用页面。

urls.py:

python 复制代码
"""project_simple URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from project_one.views import depart, user

urlpatterns = [
    # path('admin/', admin.site.urls),
    path("", depart.index),
    path("depart/", depart.depart),
    path("depart/add/", depart.add_depart),
    path("depart/<int:nid>/modify/", depart.depart_modify),
    path("depart/<int:nid>/del/", depart.del_depart),
    path("user/", user.user_info),
    path("user/add/", user.user_add),
    path("user/<int:nid>/modify/", user.user_modify),
    path("user/<int:nid>/del/", user.user_del),
    path("user/add/modelform", user.user_add_modelform),
    path("user/<int:nid>/modify/modelform", user.user_modify_modelform)
]

完善user_list.html:

html 复制代码
{% extends "index/model_tmp.html" %}

{% block content %}

    <div class="container">
        <a href="/user/add/" class="btn btn-success">添加信息</a>
        {#  这个是优化过的新增功能  #}
        <a href="/user/add/modelform" class="btn btn-warning">添加信息</a>
        <div class="panel panel-danger">
            <div class="panel-heading">
                <h3 class="panel-title">部门表</h3>
            </div>
            <div class="panel-body">
                <table class="table table-hover">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>性别</th>
                        <th>薪水</th>
                        <th>年龄</th>
                        <th>入职时间</th>
                        <th>部门</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for data in user_list %}
                        <tr>
                            <th scope="row">{{ data.id }}</th>
                            <td>{{ data.name }}</td>
                            <td>{{ data.get_gender_display }}</td>
                            <td>{{ data.salary }}</td>
                            <td>{{ data.age }}</td>
                            <td>{{ data.create_time|date:"Y-m-d" }}</td>
                            <td>{{ data.department.title }}</td>
                            <td style="color: green">
                                {# 我们这里使用modelform来完成修改操作 #}
                                <a href="/user/{{ data.id }}/modify/modelform"><span style="color: green;" class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
                                <a href="/user/{{ data.id }}/del/"><span style="color: red;" class="glyphicon glyphicon-trash" aria-hidden="true"></span></a>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
{% endblock %}

user.py完整代码(包含之前写过的所有内容):

python 复制代码
from django.shortcuts import render, redirect
from django import forms

from project_one import models


# Create your views here.
def user_info(request):
    user_list = models.UserInfo.objects.all()
    return render(request, "user/user_list.html", {"user_list": user_list})


def user_add(request):
    if request.method == "GET":
        content = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, "user/user_add.html", content)
    name = request.POST.get("name")
    age = request.POST.get("age")
    gender = request.POST.get("gender")
    salary = request.POST.get("salary")
    dtime = request.POST.get("dtime")
    depart = request.POST.get("depart")
    models.UserInfo.objects.create(name=name, gender=gender, salary=salary, age=age, create_time=dtime,
                                   department_id=depart)
    return redirect("/user/")


def user_modify(request, nid):
    if request.method == "GET":
        data = models.UserInfo.objects.filter(id=nid).first()
        content = {
            "gender_choices": models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, "user/user_modify.html", {"content": content, "data": data})
    name = request.POST.get("name")
    age = request.POST.get("age")
    gender = request.POST.get("gender")
    salary = request.POST.get("salary")
    dtime = request.POST.get("dtime")
    depart = request.POST.get("depart")
    models.UserInfo.objects.filter(id=nid).update(name=name, gender=gender, salary=salary, age=age, create_time=dtime,
                                                  department_id=depart)
    return redirect("/user/")


def user_del(request, nid):
    models.UserInfo.objects.filter(id=nid).delete()
    return redirect("/user/")


class userInfoModelForm(forms.ModelForm):
    name = forms.CharField(min_length=2, label="姓名")
    class Meta:
        model = models.UserInfo
        # 所以的UserInfo表格的字段都使用
        fields = "__all__"
        # 如果是想要某张表格的某个字段不想用, 那就可以用exclude
        # exclude = ["create_time"]

    # 由于我们的userInfoModelForm类继承了forms.ModelForm类, 所以我们写构造函数的时候, 需要传入*args, **kwargs这两个参数
    def __init__(self, *args, **kwargs):
        super(userInfoModelForm, self).__init__(*args, **kwargs)
        # item是属性名, field是属性值
        for item, field in self.fields.items():
            # 给输入框input增加一个class属性
            field.widget.attrs.update({"class": "form-control"})


def user_add_modelform(request):
    if request.method == "GET":
        title = "添加信息2.0版本"
        form = userInfoModelForm()
        return render(request, "user/user_modelform.html", {"title": title, "form": form})
    # 接受表单提交过来的数据
    form = userInfoModelForm(request.POST)
    # 校验数据是否完整
    if form.is_valid():
        # 存储到数据库
        form.save()
        return redirect("/user/")
    # 如果数据不完整,则返回当前添加页面,展示错误信息
    return render(request, "user/user_modelform.html", {"form": form})


def user_modify_modelform(request, nid):
    # 获取要修改数据的那行数据
    obj = models.UserInfo.objects.filter(id=nid).first()
    if request.method == "GET":
        title = "修改信息2.0版本"
        # 这个代码的作用是当我们进入user_modelform.html界面的时候, 所有的输入框都会出现需要修改数据中的每一个字段内容里面的文字
        form = userInfoModelForm(instance=obj)
        return render(request, "user/user_modelform.html", {"title": title, "form": form})
    # 接受表单提交过来的数据
    form = userInfoModelForm(request.POST, instance=obj)
    # 校验数据是否完整
    if form.is_valid():
        # 存储到数据库
        form.save()
        return redirect("/user/")
    # 如果数据不完整,则返回当前修改页面,展示错误信息
    return render(request, "user/user_modelform.html", {"form": form})

运行结果:

比如说, 我们修改第二行数据:


我们发现, 数据修改成功了。

好了, 这篇文章关于优化新增和修改功能的内容, 就到此为止了。

以上就是Django新增修改数据功能优化的所有内容了, 如果有哪里不懂的地方,可以把问题打在评论区, 欢迎大家在评论区交流!!!

如果我有写错的地方, 望大家指正, 也可以联系我, 让我们一起努力, 继续不断的进步.

学习是个漫长的过程, 需要我们不断的去学习并掌握消化知识点, 有不懂或概念模糊不理解的情况下,一定要赶紧的解决问题, 否则问题只会越来越多, 漏洞也就越老越大.

人生路漫漫, 白鹭常相伴!!!

相关推荐
uhakadotcom2 分钟前
BentoML远程代码执行漏洞(CVE-2025-27520)详解与防护指南
后端·算法·面试
_x_w4 分钟前
【16】数据结构之基于树的排序算法篇章
开发语言·数据结构·python·算法·链表·排序算法
JavaEdge在掘金26 分钟前
告别 Webpack 困惑:一文读懂配置、Loaders 与高效开发流程
python
xmyLydia28 分钟前
我做了一个代码生成器:Spring Boot + Angular 全自动构建
后端
攻城狮7号33 分钟前
Python爬虫第14节-如何爬取Ajax的数据
爬虫·python·python爬虫
小叶爱吃鱼33 分钟前
python-各种文件(txt,xls,csv,sql,二进制文件)读写操作、文件类型转换、数据分析代码讲解
前端·javascript·python·学习
supermfc35 分钟前
Docker方式离线部署OpenWebUI
后端·deepseek
亿牛云爬虫专家41 分钟前
浏览器自动化检测对抗:修改navigator.webdriver属性的底层实现
python·selenium·自动化·爬虫代理·amazon·代理ip·playwright
恶霸不委屈1 小时前
情感科技新纪元!基于DeepSeek的智能情绪价值引擎设计与实践!!!
人工智能·python·科技·deepseek
橘猫云计算机设计1 小时前
基于django云平台的求职智能分析系统(源码+lw+部署文档+讲解),源码可白嫖!
数据库·spring boot·后端·python·django·毕业设计