欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
在上一文基础上继续
【Django 网页Web开发】08. 实战项目:部门和员工管理系统(01)(保姆级图文)
<a class="btn btn-primary btn-xs" href="#">编辑a>
上面的修改为下面的
<a class="btn btn-primary btn-xs" href="/user/{{ obj.id }}/edit/">编辑a>
urlpatterns中添加下面一行
path('user//edit/' , views.user_edit),
核心在于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})#如果数据不合法
{% 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 %}
修改删除按钮超链接传入员工id参数
<a class="btn btn-danger btn-xs" href="#">删除a>
上面的修改为下面的
<a class="btn btn-danger btn-xs" href="/user/{{ obj.id }}/delete/">删除a>
urlpatterns中添加下面一行
path('user//delete/' , views.user_delete),
def user_delete(request, nid):
models.UserInfo.objects.filter(id=nid).first().delete()#一行delete,这个first可加可不加,看你的id是否唯一
return redirect('/user/list/')
添加一个
<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>
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)#默认未使用
path('pretty/list/', views.pretty_list),
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)
{% 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 %}
/pretty/add/
<a class="btn btn-success" href="/pretty/add/">
path('pretty/add/', views.pretty_add),
from django import forms
class PrettyModelForm(forms.ModelForm):
...
函数
点击提交
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})
这里要注意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 %}
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}
可以操作数据库相关的内容,比如说后文用到的重复数据判断,正则不能实现与已经在数据库中数据的联动
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}
/pretty/edit/
<a class="btn btn-primary btn-xs" href="/pretty/{{ obj.id }}/edit/">编辑a>
path('pretty//edit/' , views.pretty_edit),
编辑功能显示的字段和设计如果要和添加靓号不一样,需要新建一个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})
{% 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 %}
要求添加和编辑数据时手机号不能重复。需要在钩子函数中加入判断。
添加:【正则表达式】【手机号不能存在】
# [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})
编辑:【正则表达式】【手机号不能存在】
排除自己以外,其他的数据是否手机号是否重复?
# 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})
path('pretty//delete/' , views.pretty_delete),
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)』
【更多内容敬请期待】