【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)

目录

  • 员工编辑删除功能
    • 1. 员工编辑功能
      • 1.1 user_list.htm
      • 1.2 url.py
      • 1.3 view.py
      • 1.4 user_edit.html
    • 2. 员工删除功能
      • 2.1 user_list.htm
      • 2.2 url.py
      • 2.3 view.py
  • 靓号管理
    • 0. layout.html 模板添加栏目
    • 1. 数据表设计
    • 2. 靓号列表
      • 2.1 URL
      • 2.2 view.py
      • 2.3 pretty_list.html
      • 2.4 呈现效果
    • 3. 新建靓号
      • 3.1 URL
      • 3.2 view.py
      • 3.3 pretty_list.html
      • 3.4 呈现效果
    • 4. 数据校验的2种方法
      • 4.1 方式1 字段+正则
      • 4.2 方式2 钩子方法
    • 5. 编辑靓号
      • 5.1 URL
      • 5.2 view.py
      • 5.3 pretty_list.html
    • 6. 常见校验:重复数据的校验
      • 6.1 添加时手机号码不能重复
      • 6.2 编辑时手机号码不能重复
    • 7. 靓号删除
      • 7.1 url.py
      • 7.2 view.py
    • 总结


欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中

在上一文基础上继续
【Django 网页Web开发】08. 实战项目:部门和员工管理系统(01)(保姆级图文)

员工编辑删除功能

1. 员工编辑功能

1.1 user_list.htm

修改编辑按钮超链接传入员工id参数
【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第1张图片

  • user_list.html的部分代码修改
<a class="btn btn-primary btn-xs" href="#">编辑a> 
上面的修改为下面的
<a class="btn btn-primary btn-xs" href="/user/{{ obj.id }}/edit/">编辑a>

【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第2张图片

1.2 url.py

urlpatterns中添加下面一行
    path('user//edit/', views.user_edit),

1.3 view.py

  • 核心在于instance的应用,实现了数据自动展示。修改数据时,一开始的输入框中填写好了原来修改前的值

  • 如果有其他新增的数据不是用户输入的,但是希望也能存入数据库(例如注册时的浏览器),可以通过form.instance.字段名 = 值的方式加入数据库。

def user_edit(request, nid):
    """ 编辑用户 """
    row_object = models.UserInfo.objects.filter(id=nid).first()#获取指定用户的那一行数据

    if request.method == "GET":
        # 根据ID去数据库获取要编辑的那一行数据(对象)
        form = UserModelForm(instance=row_object)
        #instance 数据表的某一行,ModelForm会自动把这一行数据填充到表单中,也就是修改数据时,一开始的输入框中填写好了原来修改前的值
        return render(request, 'user_edit.html', {'form': form})

    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():#如果是合法的数据准备保存进数据库
        # 默认保存的是用户输入的所有数据,如果想要再用户输入以外增加一点值
        # form.instance.字段名 = 值
        form.save()
        return redirect('/user/list/')
    return render(request, 'user_edit.html', {"form": form})#如果数据不合法

1.4 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 %}

  • 效果展示
    【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第3张图片
  • 修改错误提示
    【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第4张图片

2. 员工删除功能

2.1 user_list.htm

修改删除按钮超链接传入员工id参数

<a class="btn btn-danger btn-xs" href="#">删除a>
上面的修改为下面的
<a class="btn btn-danger btn-xs" href="/user/{{ obj.id }}/delete/">删除a>

2.2 url.py

urlpatterns中添加下面一行
    path('user//delete/', views.user_delete),

2.3 view.py

def user_delete(request, nid):
    models.UserInfo.objects.filter(id=nid).first().delete()#一行delete,这个first可加可不加,看你的id是否唯一
    return redirect('/user/list/')

靓号管理

0. layout.html 模板添加栏目

添加一个
<li><a href="/pretty/list/">靓号管理a>li>

完整代码

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
    <style>
        .navbar {
            border-radius: 0;
        {#去掉圆角#}
        }
    </style>
</head>
<body>
<nav class="navbar navbar-default">
    <div class="container">
        <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="/depart/list/"> XX公司用户管理系统 </a>
        </div>
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="/depart/list/">部门管理</a></li>
                <li><a href="/user/list/">用户管理</a></li>
                <li><a href="/pretty/list/">靓号管理</a></li>
                <li><a href="#">Link</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">mzh <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">个人资料</a></li>
                        <li><a href="#">我的信息</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">注销</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>

<div>
    {% block content %}{% endblock %}
</div>

{#导入jquery和bootstrap,注意要先导入js再导入jquery,顺序的问题#}
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>

1. 数据表设计

  • models.py
class PrettyNum(models.Model):
    """ 靓号表 """
    mobile = models.CharField(verbose_name="手机号", max_length=11)#最大长度11
    # 想要允许为空 null=True, blank=True
    price = models.IntegerField(verbose_name="价格", default=0)#默认价格0

    level_choices = (
        (1, "1级"),
        (2, "2级"),
        (3, "3级"),
        (4, "4级"),
    )
    level = models.SmallIntegerField(verbose_name="级别", choices=level_choices, default=1)#默认1级

    status_choices = (
        (1, "已占用"),
        (2, "未使用")
    )
    status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=2)#默认未使用

【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第5张图片
【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第6张图片

2. 靓号列表

2.1 URL

path('pretty/list/', views.pretty_list),

2.2 view.py

  • 获取所有的靓号
  • 结合html+render将靓号罗列出来
    id	号码	价格	级别(中文)	状态(中文)
    
def pretty_list(request):
    """ 靓号列表 """

    data_dict = {}
    search_data = request.GET.get('q', "")
    if search_data:
        data_dict["mobile__contains"] = search_data

    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")

    page_object = Pagination(request, queryset)

    context = {
        "search_data": search_data,

        "queryset": page_object.page_queryset,  # 分完页的数据
        "page_string": page_object.html()  # 页码
    }
    return render(request, 'pretty_list.html', context)

2.3 pretty_list.html

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px" class="clearfix">
            <a class="btn btn-success" href="/pretty/add/">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true">span>
                新建靓号
            a>


        div>
        <div class="panel panel-default">
            
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true">span>
                靓号列表
            div>

            
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>IDth>
                    <th>号码th>
                    <th>价格th>
                    <th>级别th>
                    <th>状态th>
                    <th>操作th>
                tr>
                thead>
                <tbody>
                {% for obj in queryset %}
                    <tr>
                        <th>{{ obj.id }}th>
                        <td>{{ obj.mobile }}td>
                        <td>{{ obj.price }}td>
                        <td>{{ obj.get_level_display }}td>
                        <td>{{ obj.get_status_display }}td>
                        <td>
                            <a class="btn btn-primary btn-xs" href="/pretty/{{ obj.id }}/edit/">编辑a>
                            <a class="btn btn-danger btn-xs" href="/pretty/{{ obj.id }}/delete/">删除a>
                        td>
                    tr>
                {% endfor %}

                tbody>
            table>
        div>
        <div class="clearfix">
            <ul class="pagination">
                {{ page_string }}
            ul>

        div>

    div>
{% endblock %}

2.4 呈现效果

【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第7张图片

3. 新建靓号

3.1 URL

  • 列表点击跳转:/pretty/add/
    模板html中的按钮
<a class="btn btn-success" href="/pretty/add/">
  • url.py
path('pretty/add/', views.pretty_add),

3.2 view.py

  • ModelForm类
    from django import forms
    
    class PrettyModelForm(forms.ModelForm):
    	...
    

函数

  • 实例化类的对象
  • 通过render将对象传入到HTML中。
  • 模板的循环展示所有的字段。

点击提交

  • 数据校验
  • 保存到数据库
  • 跳转回靓号列表
class PrettyModelForm(forms.ModelForm):
    class Meta:
        model=models.PrettyNum
        fields=["mobile","price","level","status"]#选择展示的字段
        # fields="__all__"#显示所有字段
        # exclude=["id"]#不显示id字段
    #下面的def固定写法用于给所有控件加上指定样式 "class": "form-control", "placeholder": field.label
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

def pretty_add(request):
    """ 添加靓号 """
    if request.method == "GET":
        form = PrettyModelForm()
        return render(request, 'pretty_add.html', {"form": form})
    form = PrettyModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect('/pretty/list/')
    return render(request, 'pretty_add.html', {"form": form})

3.3 pretty_list.html

这里要注意form表单中的novalidate表示不启用浏览器自带的表单校验,我们用自己后端或是django的表单校验(后期开发中遇到的不同浏览器的校验可能有区别,只能信任自己的校验)

{% 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 %}

3.4 呈现效果

【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第8张图片

4. 数据校验的2种方法

4.1 方式1 字段+正则

from django.core.validators import RegexValidator#导入正则模块
from django.core.exceptions import ValidationError#导入Django异常模块
class PrettyModelForm(forms.ModelForm):
    # 数据校验:方式1 字段+正则
    mobile = forms.CharField(
        label="手机号",
        #通过正则的方式直接判断
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '字段+正则手机号格式错误'), ],#正则匹配首位数字1,第二位数字3-9,接下来9位数字
    )


    class Meta:
        model=models.PrettyNum
        fields=["mobile","price","level","status"]#选择展示的字段
        # fields="__all__"#显示所有字段
        # exclude=["id"]#不显示id字段
    #下面的def固定写法用于给所有控件加上指定样式 "class": "form-control", "placeholder": field.label
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第9张图片

4.2 方式2 钩子方法

可以操作数据库相关的内容,比如说后文用到的重复数据判断,正则不能实现与已经在数据库中数据的联动

from django.core.validators import RegexValidator#导入正则模块
from django.core.exceptions import ValidationError#导入Django异常模块
class PrettyModelForm(forms.ModelForm):

    # 数据校验:方式2 钩子方法
    def clean_mobile(self):
        # 当前编辑的哪一行的ID
        # print(self.instance.pk)
        txt_mobile = self.cleaned_data["mobile"]#拿到了手机号码数据可以通过if等逻辑进行判断
        if len(txt_mobile)!=11:
            raise ValidationError("钩子方法:手机号长度不对劲")

        # 验证通过,用户输入的值返回
        return txt_mobile

    class Meta:
        model=models.PrettyNum
        fields=["mobile","price","level","status"]#选择展示的字段
        # fields="__all__"#显示所有字段
        # exclude=["id"]#不显示id字段
    #下面的def固定写法用于给所有控件加上指定样式 "class": "form-control", "placeholder": field.label
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

【Django 网页Web开发】09. 实战项目:员工编辑删除功能与靓号管理(02)(保姆级图文)_第10张图片

5. 编辑靓号

5.1 URL

  • 列表点击跳转:/pretty/edit/
    模板html中的按钮
<a class="btn btn-primary btn-xs" href="/pretty/{{ obj.id }}/edit/">编辑a>
  • url.py
path('pretty//edit/', views.pretty_edit),

5.2 view.py

编辑功能显示的字段和设计如果要和添加靓号不一样,需要新建一个modelForm类

class PrettyEditModelForm(forms.ModelForm):

    mobile=forms.CharField(disabled=True,label="手机号")#让手机号可以显示,但是不能修改
    class Meta:
        model = models.PrettyNum
        fields = ['mobile','price', 'level', 'status']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

def pretty_edit(request, nid):
    """ 编辑靓号 """
    row_object = models.PrettyNum.objects.filter(id=nid).first()

    if request.method == "GET":
        form = PrettyEditModelForm(instance=row_object)
        return render(request, 'pretty_edit.html', {"form": form})

    form = PrettyEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/pretty/list/')

    return render(request, 'pretty_edit.html', {"form": form})

5.3 pretty_list.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 %}

6. 常见校验:重复数据的校验

要求添加和编辑数据时手机号不能重复。需要在钩子函数中加入判断。

6.1 添加时手机号码不能重复

  • 添加:【正则表达式】【手机号不能存在】

    # [obj,obj,obj]
    queryset = models.PrettyNum.objects.filter(mobile="1888888888")
    
    obj = models.PrettyNum.objects.filter(mobile="1888888888").first()
    
    # True/False
    exists = models.PrettyNum.objects.filter(mobile="1888888888").exists() 
    是否有已经存在的手机号码为1888888888,如果存在那么返回true
    
from django.core.exceptions import ValidationError#导入Django异常模块
class PrettyModelForm(forms.ModelForm):
    # 数据校验:方式2 钩子方法
    def clean_mobile(self):
        # 当前编辑的哪一行的ID
        print(self.instance.pk)
        txt_mobile = self.cleaned_data["mobile"]#拿到了手机号码数据可以通过if等逻辑进行判断
        # if len(txt_mobile)!=11:
        #     raise ValidationError("钩子方法:手机号长度不对劲")
        exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError("钩子方法:手机号已存在")

        # 验证通过,用户输入的值返回
        return txt_mobile

    class Meta:
        model=models.PrettyNum
        fields=["mobile","price","level","status"]#选择展示的字段
        # fields="__all__"#显示所有字段
        # exclude=["id"]#不显示id字段
    #下面的def固定写法用于给所有控件加上指定样式 "class": "form-control", "placeholder": field.label
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

def pretty_add(request):
    """ 添加靓号 """
    if request.method == "GET":
        form = PrettyModelForm()
        return render(request, 'pretty_add.html', {"form": form})#通过render将对象传入到HTML中。
    form = PrettyModelForm(data=request.POST)
    if form.is_valid():#数据校验
        form.save()#保存到数据库
        return redirect('/pretty/list/')#跳转回靓号列表
    return render(request, 'pretty_add.html', {"form": form})

6.2 编辑时手机号码不能重复

  • 编辑:【正则表达式】【手机号不能存在】

    排除自己以外,其他的数据是否手机号是否重复?
    
    # id!=2 and mobile='1888888888'
    models.PrettyNum.objects.filter(mobile="1888888888").exclude(id=2) 
    除了自身外是否存在有手机号码为1888888888的,如果有的话,返回true
    
class PrettyEditModelForm(forms.ModelForm):

    mobile=forms.CharField(disabled=True,label="手机号")#让手机号可以显示,但是不能修改
    class Meta:
        model = models.PrettyNum
        fields = ['mobile','price', 'level', 'status']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}
    # 数据校验:方式2 钩子方法
    def clean_mobile(self):

        print(self.instance.pk) # 当前编辑的哪一行的ID
        txt_mobile = self.cleaned_data["mobile"]#拿到了手机号码数据可以通过if等逻辑进行判断
        # if len(txt_mobile)!=11:
        #     raise ValidationError("钩子方法:手机号长度不对劲")
        
        exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError("钩子方法:手机号已存在")

        # 验证通过,用户输入的值返回
        return txt_mobile

def pretty_edit(request, nid):
    """ 编辑靓号 """
    row_object = models.PrettyNum.objects.filter(id=nid).first()

    if request.method == "GET":
        form = PrettyEditModelForm(instance=row_object)
        return render(request, 'pretty_edit.html', {"form": form})

    form = PrettyEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/pretty/list/')

    return render(request, 'pretty_edit.html', {"form": form})

7. 靓号删除

7.1 url.py

path('pretty//delete/', views.pretty_delete),

7.2 view.py

def pretty_delete(request, nid):
    models.PrettyNum.objects.filter(id=nid).delete()
    return redirect('/pretty/list/')

总结

大家喜欢的话,给个,点个关注!给大家分享更多有趣好玩的Python 网页Web开发知识!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2023 mzh

Crated:2023-3-1

欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
『01. 安装配置Django』
『02. 创建并运行一个Django项目』
『03. 初识Django』
『04. 请求和响应,网页跳转重定向,实战简易表单模拟登陆』
『05. 数据库操作,实战用户管理』
『06. 报错:You have 26 unapplied migration(s). Your project may not work properly until you apply the migra』
『07. 模板语法』
『08. 实战项目:部门和员工管理系统(01)』
『09. 实战项目:员工编辑删除功能与靓号管理(02)』
『10. 实战项目:靓号搜索功能(03)』
『11. 实战项目:分页与页码跳转功能(04)』
『12. 实战项目:分页组件的封装 面向接口编程(05)』
『13. 实战项目:添加用户时的时间选择组件(06)』
『14. 实战项目:一些面向对象的代码结构优化(07)』
『15. 实战项目:管理员增删改查,md5密码和密码重置(08)』
『16. 实战项目:BootStrap类的进一步优化(09)』
『17. 实战项目:login业务涉及cookie、session、中间件(10)』
『18. 实战项目:登录时的验证码(11)』
『19. 实战项目:初识Ajax请求(12)』
『20. 实战项目:Ajax实战之订单管理与弹出对话框(13)』
『21. 实战项目:echart数据图表(14)』
『22. 实战项目:简单的文件上传(15)』
『23. 实战项目:Excel和form和moudleForm的文件上传(16)』
【更多内容敬请期待】


你可能感兴趣的:(python,#,Django网页Web开发,django,前端,python,后端)