目录
天天学习,天天向上
一、models.py
# models.py
from django.db import models
class PrettyNum(models.Model):
"""靓号管理"""
mobile = models.CharField(verbose_name='手机号码', max_length=11)
price = models.DecimalField(verbose_name='价格', default=0, decimal_places=2, max_digits=10)
level_choices = (
(1, '1级'),
(2, '2级'),
(3, '3级'),
(4, '4级'),
(5, '5级'),
)
level = models.SmallIntegerField(choices=level_choices, verbose_name='级别', default=1)
status_choices = (
(1, '已占用'),
(2, '未占用'),
)
status = models.SmallIntegerField(choices=status_choices , verbose_name='状态', default=2)
二、app.views.py
# app.views.py
from django import forms
from django.core.validators import RegexValidator
from django.shortcuts import render, redirect
from mobile_app import models
from mobile_app import models
class PrettyModelForm(forms.ModelForm):
"""定义models.PrettyNum 的ModelForm组件"""
# 重定义mobile 字段的模型,检验手机号码格式,为下面增加手机号码时候做准备,报错会返回前端页面提示
mobile = forms.CharField(label='手机号码', validators=[RegexValidator(r'^1[3-9]\d{9}', "手机号码格式错误")])
class Meta:
model = models.PrettyNum
# 表示 读取全部字段
fields = "__all__"
# fields = ['mobile','price','level','status'] # 单独读取某些要用的字段
# exclude = ['status'] # 除了status字段,其他都要
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # 父类继承 __init__
for name, field in self.fields.items(): # 把models的 字段名和verbose_name 一起打包
field.widget.attrs = {'class': 'form-control', 'placeholder': field.label}
def mobile_info(request):
# -level == desc select * from 表名 order by 字段 desc
if request.method == 'GET':
data_list = models.PrettyNum.objects.all().order_by('-level')
return render(request, 'mobile_list.html', {'data_list': data_list})
def mobile_add(request):
if request.method == 'GET':
form = PrettyModelForm()
return render(request, 'mobile_add.html', {'form': form})
form = PrettyModelForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('/mobile/info/')
# 校验失败,返回前端报错信息
return render(request, 'mobile_add.html', {'form': form})
def mobile_update(request, nid):
row_objects = models.PrettyNum.objects.get(id=nid)
if request.method == 'GET':
form = PrettyModelForm(instance=row_objects)
return render(request, 'mobile_update.html', {'form': form})
form = PrettyModelForm(data=request.POST, instance=row_objects)
if form.is_valid():
form.save()
return redirect('/mobile/info/')
return render(request, 'mobile_update.html', {'form': form})
def mobile_del(request, nid):
models.PrettyNum.objects.get(id=nid).delete()
return redirect('/mobile/info/')
对代码写法有疑问的,可以参考以下代码代码写法不一样的,实际是一样的效果:
# 方法一:
def mobile_update(request, nid):
row_objects = models.PrettyNum.objects.get(id=nid)
if request.method == 'GET':
form = PrettyModelForm(instance=row_objects)
return render(request, 'mobile_update.html', {'form': form})
form = PrettyModelForm(data=request.POST, instance=row_objects)
if form.is_valid():
form.save()
return redirect('/mobile/info/')
return render(request, 'mobile_update.html', {'form': form})
# 方法二:
def mobile_update2(request, nid):
row_objects = models.PrettyNum.objects.get(id=nid)
if request.method == 'GET':
"""instance=row_objects表示从a标签跳转过来的时候,在input框里显示原来要修改的信息"""
form = PrettyModelForm(instance=row_objects)
return render(request, 'mobile_update.html', {'form': form})
if request.method == 'POST':
"""instance=row_objects表示修改参数的时候,是对这个id列参数进行修改,如果没有这个参数,会变成新增信息,达不到想要的效果"""
form = PrettyModelForm(data=request.POST, instance=row_objects)
if form.is_valid(): # 校验前端输入信息是否为空
form.save() # 提交到数据库保存
return redirect('/mobile/info/') # 添加成功之后,重定向返回信息列表
else:
# 检验失败,返回当前页面,提示错误信息,不能为空
return render(request, 'mobile_update.html', {'form': form})
三、HTML
父类html
1、插件bootstrap-4.6.2、fontawesome-free-5.15.4
# index.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static '/plugins/bootstrap-4.6.2-dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static '/plugins/fontawesome-free-5.15.4-web/css/all.min.css' %}">
</head>
<body>
<div>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/user/info/">信息管理系统</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/depart/list/">部门管理 <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/user/info/">用户列表</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mobile/info/">靓号管理</a>
</li>
</ul>
<div class="form-inline my-2 my-lg-0">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">登 陆<span class="sr-only">(current)</span></a>
</li>
</ul>
<div class="dropdown">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" data-toggle="dropdown"
aria-expanded="false">
当前用户
</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">个人信息</a>
<a class="dropdown-item" href="#">修改密码</a>
<a class="dropdown-item" href="#">注销</a>
</div>
</div>
</div>
</div>
</nav>
</div>
<div>
{% block content %}{% endblock %}
</div>
<script src="{% static '/js/jquery-3.7.1.min.js' %}."></script>
<script src="{% static '/plugins/bootstrap-4.6.2-dist/js/bootstrap.min.js' %}"></script>
<script src="{% static '/plugins/fontawesome-free-5.15.4-web/js/all.min.js' %}"></script>
</body>
</html>
信息查询界面
1、copy我的代码时候,注意我的模板是用的继承的父类
2、<a href="/mobile/{{ data.id }}/update/">编辑</a>
a标签跳转的时候,携带了ID在get请求上面,后端获取了ID就知道 修改/删除 那一条数据
3、get_字段名_display(),在django是一个方法,专门的是为了获取model.py中status_choices和level_choices中的“文字”在前端显示,因为数据记录的是数字不是文字
注意:在前端写法不用写“()”括号,浏览器会自动帮你处理,在后端使用的时候就要括号
{% extends 'index.html' %}
{% block content %}
<div class="container">
<div style="width: 100%;margin: 10px">
<a href="/mobile/add/">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
添加手机号码信息
</a>
</div>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">ID</th>
<th scope="col">手机号码</th>
<th scope="col">价格</th>
<th scope="col">等级</th>
<th scope="col">状态</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
{% for data in data_list %}
<tr>
<th scope="row">{{ data.id }}</th>
<td>{{ data.mobile }}</td>
<td>{{ data.price }}</td>
<td>{{ data.get_level_display }}</td>
<td>{{ data.get_status_display }}</td>
<td>
<a href="/mobile/{{ data.id }}/update/">编辑</a>
<a href="/mobile/{{ data.id }}/delete/">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
信息增加
1、novalidate表示取消前端的检验,因为不同的浏览器检验的方法不同,不一定准确,用自己的后端检验
2、foo.errors.0
foo.eroers是一个列表,错误信息可能有很多,0获取列表第一个错误信息
{% extends 'index.html' %}
{% block content %}
<div class="container">
<a href="/mobile/add/">
<button type="button" class="btn btn-primary" style="margin-bottom: 10px">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
添加号码信息
</button>
</a>
<--novalidate表示取消前端的检验,因为不同的浏览器检验的方法不同,不一定准确,我用自己的后端检验-->
<form method="post" novalidate>
{% csrf_token %}
{% for foo in form %}
<div>{{ foo.label }}</div>
<div>
{{ foo }}
{{ foo.errors.0}}
</div>
{% endfor %}
<div>
<input type="submit" value="提交">
</div>
</form>
</div>
{% endblock %}
修改信息
{% extends 'index.html' %}
{% block content %}
<div class="container">
<a href="/mobile/update/">
<button type="button" class="btn btn-primary" style="margin-bottom: 10px">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
修改号码信息
</button>
</a>
<form method="post" novalidate>
{% csrf_token %}
{% for foo in form %}
<div>{{ foo.label }}</div>
<div>
{{ foo }}
{{ foo.errors.0}}
</div>
{% endfor %}
<div>
<input type="submit" value="提交">
</div>
</form>
</div>
{% endblock %}
删除信息
1、 <a href="/mobile/{{ data.id }}/delete/">删除</a>
a标签携带过去的id,后端根据id直接删除就行了,不需要跳转其他界面,重定向当前页面
四、路由文件
1、主路由文件
from django.contrib import admin
from django.urls import path,include
from staff_app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('mobile/', include('mobile_app.urls')),
]
2、分路由文件
<int:nid>可以理解为正则匹配,主要为了a标签跳转的时候,携带nid给后端
from django.urls import path
from mobile_app import views
urlpatterns = [
path('info/',views.mobile_info),
path('add/', views.mobile_add),
path('<int:nid>/update/', views.mobile_update),
path('<int:nid>/delete/', views.mobile_del),
]