Django详细教程(二) - 部门用户管理案例

文章目录

  • 前言
  • 一、新建项目
  • 二、新建app
  • 三、设计表结构
  • 四、新建数据库
  • 五、新建静态文件
  • 六、部门管理
    • 1.部门展示
    • 2.部门添加
    • 3.部门删除
    • 4.部门编辑
  • 七、模板继承
  • 八、用户管理
    • 1.辨析三种方法
      • 方法一:原始方法
      • 方法二:Form组件(简便)
      • 方法三:ModelForm组件(最简便)
    • 2.用户添加(ModelForm)
    • 3.数据校验错误提示
    • 3.编辑用户
    • 4.删除用户

前言

前一篇博客介绍了Django的一些基本操作,本篇博客将结合部门用户管理案例介绍更多的操作,包括表结构的级联、约束,重定向,模板继承,ModelForm各种操作,校验错误提示等等。

一、新建项目

  • 新建
    在这里插入图片描述
  • 删除不需要的部分
    在这里插入图片描述

二、新建app

  • 新建:python manage.py startapp app01
  • 如果打开了Run manage...窗口,则只需要输入后半部分:startapp app01在这里插入图片描述
  • 注册app在这里插入图片描述

三、设计表结构

  • 理清关系
    在这里插入图片描述
  • 代码:注意表结构的级联和约束
from django.db import models


class Department(models.Model):
    """ 部门表 """
    title = models.CharField(verbose_name='标题', max_length=32)


class UserInfo(models.Model):
    """ 员工表 """
    name = models.CharField(verbose_name="姓名", max_length=16)
    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="入职时间")

    # 无约束
    # depart_id = models.BigIntegerField(verbose_name="部门ID")
    # 1.有约束
    #   - to,与那张表关联
    #   - to_field,表中的那一列关联
    # 2.django自动
    #   - 写的depart
    #   - 生成数据列 depart_id
    # 3.部门表被删除
    # ### 3.1 级联删除
    depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
    # ### 3.2 置空
    # depart = models.ForeignKey(to="Department", to_field="id", null=True, blank=True, on_delete=models.SET_NULL)

    # 在django中做的约束
    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)

在这里插入图片描述

四、新建数据库

  • MySQL生成数据库
create database gx_day16 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
  • 修改配置文件,连接MySQL
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'gx_day16',  # 数据库名字
        'USER': 'root',
        'PASSWORD': 'root123',
        'HOST': '127.0.0.1',  # 那台机器安装了MySQL
        'PORT': 3306,
    }
}

在这里插入图片描述

  • django命令生成数据库表
python manage.py makemigrations
python manage.py migrate
  • 如果打开了Run manage...窗口则只需要输入后一部分
    在这里插入图片描述
  • 验证表结构创建成功
    在这里插入图片描述

五、新建静态文件

  • static目录
    在这里插入图片描述

六、部门管理

1.部门展示

  • url
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('depart/list/', views.depart_list),
]
  • view
from turtle import title
from django.shortcuts import render, redirect
from qpp01.models import Department,UserInfo

# Create your views here.
def depart_list(request):
    """部门列表"""

    depart_list = Department.objects.all()

    return render(request, "depart_list.html", {"depart_list": depart_list})
  • depart_list.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>

    <link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1/css/bootstrap.css">
    <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css">

    <style>
        .navbar {
            border-radius: 0;
        }
    </style>
</head>

<body>

    <!-- 导航条, https://v3.bootcss.com/components/#navbar -->
    <nav class="navbar navbar-default">
        <div class="container">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">员工管理系统</a>
            </div>

            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li><a href="#">部门管理</a></li>
                    <li><a href="#">部门管理</a></li>

                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">注册</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                            aria-expanded="false">poker <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                        </ul>
                    </li>
                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <!-- 新建区域 -->
    <div>
        <div class="container">
            <div style="margin-bottom: 10px">
                <a class="btn btn-primary" href="/depart/add/" target="_blank">新建部门</a>
            </div>
            <div>
                <div class="panel panel-default">
                    <!-- Default panel contents -->
                    <div class="panel-heading">
                        <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span>
                        <span>部门列表</span>
                    </div>

                    <!-- Table -->
                    <table class="table table-bordered">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>名称</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for obj in depart_list %}
                            <tr>
                                <th>{{ obj.id }}</th>
                                <td>{{ obj.title }}</td> 
                                <td>
                                    <button type="button" class="btn btn-primary btn-xs">编辑</button>
                                    <button type="button" class="btn btn-danger btn-xs">删除</button>
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>

    <script src="/static/js/jquery-3.6.1.min.js"></script>
    <script src="/static/plugins/bootstrap-3.4.1/js/bootstrap.min.js"></script>
</body>

</html>
  • 效果
    请添加图片描述

2.部门添加

  • url
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
]
  • views
def depart_add(request):
    """部门添加"""
    if request.method == "GET":
        return render(request, "depart_add.html")

    # 获取用户提交的部门数据
    depart_title = request.POST.get("depart_title")

    # 保存到数据库
    Department.objects.create(title=depart_title)

    return redirect("/depart/list/")
  • depart_list.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>

    <link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1/css/bootstrap.css">
    <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css">

    <style>
        .navbar {
            border-radius: 0;
        }
    </style>

</head>

<body>
    <div>
        <!-- 导航条, https://v3.bootcss.com/components/#navbar -->
        <nav class="navbar navbar-default">
            <div class="container">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">员工管理系统</a>
                </div>

                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <ul class="nav navbar-nav">
                        <li><a href="#">部门管理</a></li>
                        <li><a href="#">部门管理</a></li>

                    </ul>
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">注册</a></li>
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                                aria-haspopup="true" aria-expanded="false">poker <span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li><a href="#">Action</a></li>
                                <li><a href="#">Another action</a></li>
                                <li><a href="#">Something else here</a></li>
                                <li role="separator" class="divider"></li>
                                <li><a href="#">Separated link</a></li>
                            </ul>
                        </li>
                    </ul>
                </div><!-- /.navbar-collapse -->
            </div><!-- /.container-fluid -->
        </nav>
    </div>
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">新建部门</h3>
            </div>
            <div class="panel-body">
                <form action="/depart/add/" method="post">
                    {% csrf_token %}
                    <div class="form-group">
                        <label>部门名称</label>
                        <input type="text" class="form-control" placeholder="部门名称" name="depart_title">
                    </div>

                    <button type="submit" class="btn btn-primary">保存</button>

                </form>
            </div>
        </div>
    </div>
</body>
</html>
  • 效果
    请添加图片描述

请添加图片描述

3.部门删除

  • url
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
]
  • views(注意redirect重定向)
def depart_delete(request):
    """部门删除"""

    nid = request.GET.get('nid')
    Department.objects.filter(id=nid).delete()

    # 重定向回部门列表
    return redirect("/depart/list/")
  • depart_list.html
<tbody>
    {% for obj in depart_list %}
    <tr>
        <th>{{ obj.id }}</th>
        <td>{{ obj.title }}</td> 
        <td>
            <a class="btn btn-primary btn-xs">编辑</a>
            <a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除</a>
        </td>
    </tr>
    {% endfor %}
</tbody>

请添加图片描述

4.部门编辑

  • url
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
]
  • views
def depart_edit(request, nid):
    """部门编辑"""

    if request.method == "GET":
        # 根据nid,获取数据
        row_object = Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"row_object": row_object})
    
    # 如果是POST请求,保存修改
    depart_title = request.POST.get('depart_title')
    Department.objects.filter(id=nid).update(title=depart_title)

    # 重定向回部门列表
    return redirect('/depart/list/')
  • depart_edit.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>

    <link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1/css/bootstrap.css">
    <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css">

    <style>
        .navbar {
            border-radius: 0;
        }
    </style>

</head>

<body>
    <div>
        <!-- 导航条, https://v3.bootcss.com/components/#navbar -->
        <nav class="navbar navbar-default">
            <div class="container">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">员工管理系统</a>
                </div>

                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <ul class="nav navbar-nav">
                        <li><a href="#">部门管理</a></li>
                        <li><a href="#">部门管理</a></li>

                    </ul>
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">注册</a></li>
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                                aria-haspopup="true" aria-expanded="false">poker <span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li><a href="#">Action</a></li>
                                <li><a href="#">Another action</a></li>
                                <li><a href="#">Something else here</a></li>
                                <li role="separator" class="divider"></li>
                                <li><a href="#">Separated link</a></li>
                            </ul>
                        </li>
                    </ul>
                </div><!-- /.navbar-collapse -->
            </div><!-- /.container-fluid -->
        </nav>
    </div>
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">编辑部门</h3>
            </div>
            <div class="panel-body">
                <form action="/depart/{{ row_object.id }}/edit/" method="post">
                    {% csrf_token %}
                    <div class="form-group">
                        <label>部门名称</label>
                        <input type="text" class="form-control" placeholder="部门名称" name="depart_title" value="{{ row_object.title }}">
                    </div>
                    <button type="submit" class="btn btn-primary">保存</button>
                </form>
            </div>

        </div>
    </div>
</body>
</html>

请添加图片描述

  • 修改depart_list.html
<tbody>
    {% for obj in depart_list %}
    <tr>
        <th>{{ obj.id }}</th>
        <td>{{ obj.title }}</td> 
        <td>
            <a class="btn btn-primary btn-xs" href="/depart/{{ obj.id }}/edit/">编辑</a>
            <a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除</a>
        </td>
    </tr>
    {% endfor %}
</tbody>
  • 效果
    请添加图片描述

七、模板继承

  • 定义目版:layout.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'plugin...min.css' %}">
    {% block css %}{% endblock %}
</head>
<body>
    <h1>标题</h1>
    <div>
        {% block content %}{% endblock %}
    </div>
    <h1>底部</h1>
    
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    {% block js %}{% endblock %}
</body>
</html>
  • 继承母版
{% extends 'layout.html' %}

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


{% block content %}
    <h1>首页</h1>
{% endblock %}


{% block js %}
	<script src="{% static 'js/jqxxxin.js' %}"></script>
{% endblock %}

八、用户管理

Django组件:

Form组件(简便)
ModelForm组件(最简便)

1.辨析三种方法

方法一:原始方法

  • url
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
    path('user/list/', views.user_list),
]
  • views
def user_list(request):

    # 获取所有用户列表
    user_data = UserInfo.objects.all()

    # 用 python 的语法获取数据
    """
    for obj in user_data:
        # obj.get_gender_display() 表示匹配 男/女,原始字段名为gender,obj.get_字段名称_display()
        # obj.create_time.strftime("%Y-%m-%d") 表示将时间格式转换成固定格式的字符串
        # obj.depart.title 表示获取depart_id对应的部门名称,因为我们在models中定义表时与另外一张表设置了级联关系,有外键
        print(obj.id, obj.name, obj.password, obj.age, obj.account, obj.get_gender_display(), obj.depart.title, obj.create_time.strftime("%Y-%m-%d"))
    """
    
    return render(request, "user_list.html", {"user_data": user_data})
  • user_list.html
  • 注意: HTML 中获取数据的方式与 Python 中有些不同,例如:
    • HTML中引入函数不能带括号, obj.get_gender_display()
    • 日期类型转字符串有Django自己的格式, obj.create_time|date:“Y-m-d”
{% extends 'layout.html' %}

{% block content %}
<div class="container">
    <div style="margin-bottom: 10px">
        <a class="btn btn-primary" href="/depart/add/" target="_blank">新建用户</a>
    </div>
    <div>
        <div class="panel panel-default">
            <!-- Default panel contents -->
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span>
                <span>用户列表</span>
            </div>

            <!-- Table -->
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>密码</th>
                        <th>年龄</th>
                        <th>性别</th>
                        <th>账户余额</th>
                        <th>入职时间</th>
                        <th>部门</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for obj in user_data %}
                    <tr>
                        <th>{{ obj.id }}</th>
                        <td>{{ obj.name }}</td>
                        <td>{{ obj.password }}</td>
                        <td>{{ obj.age }}</td>
                        <td>{{ obj.get_gender_display }}</td>
                        <td>{{ obj.account }}</td>
                        <td>{{ obj.create_time|date:"Y-m-d" }}</td>
                        <td>{{ obj.depart.title }}</td>
                        <td>
                            <a class="btn btn-primary btn-xs" href="/user/{{ obj.id }}/edit/">编辑</a>
                            <a class="btn btn-danger btn-xs" href="/user/delete/?nid={{ obj.id }}">删除</a>
                        </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

{% endblock %}
  • 不足:
    • 数据校验较麻烦
    • 页面没有错误提示
    • 页面上每一个字段都需要重新写一遍
    • 关联的数据,需要手动获取并循环展示在页面

方法二:Form组件(简便)

  • url
class MyForm(Form):
	user = forms.CharField(widget=forms.Input)
	pwd = forms.CharField(widget=forms.Input)
	email = forms.CharField(widget=forms.Input)

def user_add(request):
	if request.method == "GET":
	form = MyForm()
		return render(request, "user_add.html", {"form": form})
  • user_add.html
<form method="post">
	{{ form.user }}
	{{ form.pwd }}
	{{ form.email }}
</form>

或者

<form method="post">
	{% for field in form %}
		{{ field }}
	{% endfor %}
</form>

方法三:ModelForm组件(最简便)

  • models.py
from django.db import models

# Create your models here.
class Department(models.Model):
    """部门表"""
    title = models.CharField(max_length=32, verbose_name='标题')


class UserInfo(models.Model):
    """员工表"""
    name = models.CharField(max_length=16, verbose_name="姓名")
    password = models.CharField(max_length=64, verbose_name="密码")
    age = models.IntegerField(verbose_name="年龄")
    account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
    create_time = models.DateTimeField(verbose_name="入职时间")
    depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE, verbose_name="部门")
    
    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(choices=gender_choices,verbose_name="性别")
  • views
class MyForm(ModelForm):
	class Meta:
		field = ["name", "password", "age"]
 
def user_add(request):
	if request.method == "GET":
	form = MyForm()
		return render(request, "user_add.html", {"form": form})
  • user_add.html
<form method="post">
	{{ form.user }}
	{{ form.pwd }}
	{{ form.email }}
</form>

或者

<form method="post">
	{% for field in form %}
		{{ field }}
	{% endfor %}
</form>

2.用户添加(ModelForm)

  • url
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('depart/list/', views.depart_list),
    path('depart/add/', views.depart_add),
    path('depart/delete/', views.depart_delete),
    path('depart/<int:nid>/edit/', views.depart_edit),
    path('user/list/', views.user_list),
    path('user/model/form/add/', views.user_model_form_add),
]
  • views
########################## ModelForm 演示 #############################

from django import forms

class UserModelForm(forms.ModelForm):

    ### 自定义数据校验
    # 例如: 用户名最小三个字符
    #name = forms.CharField(min_length=3, label="用户名")

    class Meta:
        model = UserInfo
        fields = ["name", "password", "age", "account", "create_time", "gender", "depart"]
        # 逐一控制标签的样式
        # widgets = {
        #     "name": forms.TextInput(attrs={"class": "form-control"}),
        #     "password": forms.PasswordInput(attrs={"class": "form-control"}),
        # }
        
        # 这里让日期可以手动点击鼠标选择,所以单独拎出来,加上日期插件
        widgets = {
            "create_time": forms.DateTimeInput(attrs={'class': 'form-control', 'id': 'myDate'}),
        }

    # 循环找到所有的插件,添加 "class": "form-control"
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        for name, field in self.fields.items():
            # 可以排除指定的字段
            if name == "create_time":
                continue
            print(name, field)
            field.widget.attrs = {"class": "form-control"}


def user_model_form_add(request):
    """添加用户(ModelForm版本)"""
    if request.method == "GET": 
        form = UserModelForm()
        return render(request, "user_model_form_add.html", {"form": form})
    
    # 用户POST请求提交数据,需要进行数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        print(form.cleaned_data)
        # 直接保存至数据库
        form.save()
        return redirect("/user/list/")
    
    # 校验失败(在页面上显示错误信息)
    return render(request, "user_model_form_add.html", {"form": form})
  • user_model_form_add.html
{% 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 action="/user/model/form/add/" 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 %}
</body>
</html>
  • 修改models.py:目的是让自动生成的部门字段不显示"对象"本身,显示对象对应的"title"
class Department(models.Model):
    """部门表"""
    title = models.CharField(max_length=32, verbose_name='标题')

    def __str__(self):
        return self.title

请添加图片描述

3.数据校验错误提示

  • user_model_form_add.html加入{{ field.errors.0 }}字段
    请添加图片描述

  • 修改settings.py:改为中文,目的是为了让页面提示错误信息时显示中文,否则会显示英文

#LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'
  • 效果
    请添加图片描述

3.编辑用户

  • url
path('user/<int:nid>/edit/', views.user_edit),
  • views
def user_edit(request, nid):
    """编辑用户"""
    
    row_obj = UserInfo.objects.filter(id=nid).first()
    
    # GET请求
    if request.method == "GET":
        form = UserModelForm(instance=row_obj)
        return render(request, "user_edit.html", {"form": form})
    
    # POST请求
    form = UserModelForm(data=request.POST, instance=row_obj)
    if form.is_valid():
        form.save()
        return redirect("/user/list/")

    return render(request, "user_edit.html", {"form": form})    
  • user_edit.html
{% 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 %}
</body>
</html>
  • 只显示年月日就可以了,不应该显示时分秒,修改数据库models
    请添加图片描述

  • 效果:点击编辑
    请添加图片描述

4.删除用户

  • url
path('user/<int:nid>/delete/', views.user_delete),
  • views
def user_delete(request, nid):
    """用户删除"""
    UserInfo.objects.filter(id=nid).delete()
    return redirect("/user/list/")
  • user_list.html
<td>
    <a class="btn btn-primary btn-xs" href="/user/{{ obj.id }}/edit/">编辑</a>
    <a class="btn btn-danger btn-xs" href="/user/{{ obj.id }}/delete/">删除</a>
</td>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/502923.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ARM-按键中断实验

代码 #include "stm32mp1xx_gic.h" #include "stm32mp1xx_exti.h" extern void printf(const char *fmt, ...); unsigned int i 0; void do_irq(void) {//获取要处理的中断的中断号unsigned int irqnoGICC->IAR&0x3ff;switch (irqno){case 99:pr…

前端工程师————HTML5学习

HTML5基础 开发工具很多&#xff0c;其中Hbulider较好用&#xff0c;下载网址如下&#xff1a; DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 html表示整个页面 head表示搜素框 body表示内容 ti…

【蓝桥杯】矩阵快速幂

一.快速幂概述 1.引例 1&#xff09;题目描述&#xff1a; 求A^B的最后三位数表示的整数&#xff0c;A^B表示&#xff1a;A的B次方。 2&#xff09;思路&#xff1a; 一般的思路是&#xff1a;求出A的B次幂&#xff0c;再取结果的最后三位数。但是由于计算机能够表示的数字…

Gromacs模拟一:配体-双链蛋白质复合物体系准备

1、蛋白质的准备&#xff1a; 在RCSB网站下载想要的蛋白晶体&#xff08;教程里是3htb&#xff09;&#xff0c;用notepad等编辑器或是分子可视化软件除去里面的非蛋白分子或离子。 这里采用的是一个经过分子对接后的蛋白质pdb和配体小分子的pdb。 教程里提到的配体是2-丙基…

java算法day39 | 动态规划part02 ● 62.不同路径 ● 63. 不同路径 II

62.不同路径 思路&#xff1a; 本题非常巧妙。 第一步&#xff1a;定义一个dp数组存储到达每个位置的路径数。 第二步&#xff1a;每个位置的路径数它左面位置的路径数上面位置的路径数。 第三步&#xff1a;不好想的是如何初始化数组。 既然只能向下或向右走&#xff0c;可推出…

网络七层模型之会话层:理解网络通信的架构(五)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

浅谈AI未来发展趋势与挑战

对于AI大模型未来发展趋势与挑战的个人看法&#xff1a; 1、未来的发展趋势&#xff1a; AI大模型未来发展趋势可以从以下几个关键方面来讨论&#xff1a; 1. 能源与计算效率 绿色计算与节能技术&#xff1a;随着硬件技术的发展&#xff0c;预计未来的AI大模型将进一步降低能…

python电商结合双轨制

最近又重新整合翻看以前的数据&#xff0c;图片&#xff0c;绘画&#xff0c;还有各种编程代码&#xff0c;python,leetcode,还有关于商业方面的一些见解,想起了大学时候和同学们并肩作战&#xff0c;熬夜编码的时光。还有大数据&#xff0c;八爪鱼爬虫。 下面是我的手稿电商打…

Arduino通过Wire库读取AS5600编码器数据

Arduino通过Wire库读取AS5600编码器数据 ✨在实际测试中&#xff0c;测试AS5600除了使用径向磁铁之外&#xff0c;球型的或者正四方体的强磁铁&#xff0c;也是可以准确的测量角度。测试高度的话&#xff0c;从板子&#xff08;芯片引脚底部&#xff09;到磁铁底部15毫米内&…

算法打卡day21(开始回溯)

今日任务&#xff1a; 1&#xff09;77.组合 77.组合 题目链接&#xff1a;77. 组合 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;带你学透回溯算法-组合问题&#xff08;对应力扣题目&#xff1a;77…

Spring日志框架

前言 本文我们简单说说关于Spring中的日志框架,以及对应的注解 我们知道,公司服务器在运行的时候,一定会打印日志,有很多优点,比如预防报警,或者是某重大事故尝试修复等等都需要查看日志 应该说日志对我们来说并不陌生,我们在之前刷题或者是程序遇到bug的时候也经常会将程序的状…

Java数据结构-链表OJ题

目录 1. 移除链表元素2. 反转链表3. 返回中间结点4. 返回倒数第k个结点5. 合并两个有序链表6. 分割链表7. 回文链表8. 找相交链表的公共结点9. 判断链表是否有环10. 返回链表环的入口 老铁们好&#xff0c;学习完链表这个数据结构之后&#xff0c;怎么能少了OJ题呢&#xff1f;…

SQL语句学习+牛客基础39SQL

什么是SQL&#xff1f; SQL (Structured Query Language:结构化查询语言) 是用于管理关系数据库管理系统&#xff08;RDBMS&#xff09;。 SQL 的范围包括数据插入、查询、更新和删除&#xff0c;数据库模式创建和修改&#xff0c;以及数据访问控制。 SQL语法 数据库表 一个…

Windows下使用tensorrt配置YOLOv8进行加速

Windows下使用tensorrt配置YOLOv8进行加速 致谢&#xff1a; win10下 yolov8 tensorrt模型加速部署【实战】 - 知乎 (zhihu.com) yolov8 tensorrt 实战之先导_哔哩哔哩_bilibili FeiYull/TensorRT-Alpha: &#x1f525;&#x1f525;&#x1f525;TensorRT for YOLOv8、YOLOv8…

K8S故障处理指南:pod驱逐问题处理

更多技术博客,请关注微信公众号:运维之美 在K8S集群故障处理过程中,你可能遇到过pod的各种状态,Evicted状态代表你的K8S环境遇到了资源驱逐的问题,本节通过对驱逐问题的解决,参数的调整,问题的处理思路,希望给你解决此类问题提供帮助。 一、pod驱逐问题 pod出现状态为…

AR智能眼镜解决方案_MTK平台安卓主板硬件芯片方案开发

AR智能眼镜&#xff0c;是一个可以让现场作业更智能的综合管控设备。采用移动互联网、大数据和云计算等技术&#xff0c;现场数据的采集与分析&#xff1b;同时实现前端现场作业和后端管理的实时连动、信息的同步传输与存储。让前端现场作业更加智能&#xff0c;后端管理更加高…

Java代码基础算法练习-自定义函数之字符串连接-2024.03.30

任务描述&#xff1a; 写一函数&#xff0c;将两个字符串连接起来&#xff0c;然后在主函数中调用该函数实现字符串连接操作。 任务要求&#xff1a; 代码示例&#xff1a; package M0317_0331;import java.util.Scanner;public class m240330 {public static void main(Stri…

Java使用数组实现栈、队列、堆

数组模拟栈&#xff1a; const int N 10010; // ******************** 栈 int stk[N], tt//tt是下标; // 插入 stk[k] x; // 删除 tt--; // 判断栈是否为空 if (tt > 0) not empty else empty // 栈顶 stk[tt]; // ******************** 队列 // 在队尾插入…

BitVM2:比特币上的无需许可验证

1. 引言 前序博客有&#xff1a; 基于BitVM的乐观 BTC bridgeBitVM&#xff1a;Bitcoin的链下合约Bitcoin Bridge&#xff1a;治愈还是诅咒&#xff1f; 最初的 BitVM 设计仅限于两方设置。BitVM2结合了并行和冗余实例&#xff0c;以引入基于 1-of-n 诚实假设的多方配置。这…

3D目标检测综述笔记

3D Object Detection for Autonomous Driving: A Review and New Outlooks https://arxiv.org/pdf/2206.09474.pdf 目录 0.background​编辑 1.1表示形式 1.2感知输入 1.3数据集 1.4评估指标 1. LiDAR-based 3D Object Detection 2.数据表征 2.1 point-based​ 2.1.…