当前位置: 首页 > news >正文

联通用户管理系统(二)

靓号界面开发

上上篇文章没有处理的问题,在这里给出解决,对用户的编辑和删除给出方法。

1、 编辑用户

  • 点击编辑,跳转到编辑页面(将编辑行的ID携带过去)。

  • 编辑页面(默认数据,根据ID获取并设置到页面中)

  • 提交:

    • 错误提示

    • 数据校验

    • 在数据库更新

      models.UserInfo.filter(id=4).update(...)
      
def user_edit(request,nid):
    """编辑用户"""
    row_object = models.UserInfo.objects.filter(id=nid).first()
    if request.method == "GET":
        """设置编辑界面每一项的默认值,根据id去数据库获取要编辑的哪一行数据"""

        form = UserModelForm(instance=row_object)
        return render(request, 'user_edit.html', {'form':form})

    # 要指明将数据更新到nid中,否则mdelform会在list中新增一个数据
    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})

2、删除

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

一、靓号管理

1.1 表结构

在这里插入图片描述

根据表结构的需求,在models.py中创建类(由类生成数据库中的表)。

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

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

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

自己在数据模拟创建一些数据:

insert into app01_prettynum(mobile,price,level,status)values("111111111",19,1,1);
mysql> select * from app01_prettynum;
+----+-----------+-------+-------+--------+
| id | mobile    | price | level | status |
+----+-----------+-------+-------+--------+
|  1 | 111111111 |    19 |     1 |      1 |
|  2 | 111111111 |    19 |     1 |      1 |
|  3 | 111111111 |    19 |     1 |      1 |
|  4 | 111111111 |    19 |     1 |      1 |
+----+-----------+-------+-------+--------+
4 rows in set (0.01 sec)

1.2 靓号列表

  • URL

  • 函数

    • 获取所有的靓号

    • 结合html+render将靓号罗列出来

      id	号码	价格	级别(中文)	状态(中文)
      

1.3 新建靓号

  • 列表点击跳转:/mobile/add/

  • URL

  • ModelForm类

    from django import forms
    
    class MobileModelForm(forms.ModelForm):
    	...
    
class MobileModelForm(forms.ModelForm):

    #使用正则表达式,检验号码是否输入合法
    mobile = forms.CharField(
        label = "手机号",
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')],
    )
    class Meta:
        model = models.MobileInfo
        ##fields = ["mobile", "price", "level", "status"]
        fields = '__all__'
        # 或则排除那个字段
        # exclude =['lecvel']

    # 添加bootstrap样式
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        #循环找到所有的插件,添加class=“”样式
        for name, field in self.fields.items():
            field.widget.attrs = {'class': 'form-control', 'placeholder': field.label}

    ## 判断手机号是否重复
    def clean_mobile(self):
        txt_mobile = self.cleaned_data['mobile']  # 获取用户提交的手机号
        exists = models.MobileInfo.objects.filter(mobile=txt_mobile).exists()  # 正确调用 exists 方法
        if exists:
            raise ValidationError("手机号已存在")  # 如果手机号已经存在,抛出验证错误
        return txt_mobile
  • 函数

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

    • 数据校验
    • 保存到数据库
    • 跳转回靓号列表

    图片中给出两种验证手机号是否合法的方式:

在这里插入图片描述

  • 代码解析:
mobile = forms.CharField(
    label="手机号",  # 标签,显示在表单中,用来告诉用户这个字段代表的是手机号
    validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')],  # 正则验证器
)
  1. forms.CharField
  • forms.CharField 是 Django 中用于接收字符串输入的表单字段类型。
  • 它通常用于接收文本数据,像是用户名、手机号等。

这里,mobile 字段的类型是 CharField,意味着它会接收用户输入的手机号作为字符串。

  1. label="手机号"
  • label 是表单字段的标签,表示这个字段的名称,用于向用户描述这个字段的含义。在渲染表单时,label 会显示在字段上方或旁边。
  • 这里的标签是 "手机号",表示这个字段用于输入手机号。
  1. validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')]
  • validators 是用于字段的验证器。它接受一个列表,其中每个元素都是一个验证函数或验证类。在这里,使用的是 RegexValidator
  • RegexValidator 是一个正则表达式验证器,用于根据给定的正则表达式规则验证输入值。

具体来说:

  • r'^1[3-9]\d{9}$':这是一个正则表达式,用于验证输入的手机号是否符合中国大陆的手机号格式。其含义已经在之前的回答中解释过了,验证规则是手机号以 1 开头,第二位是 3-9 之间的任意数字,接下来是 9 个数字。
  • '手机号格式错误':这是当用户输入的手机号不符合正则表达式规则时显示的错误消息。若手机号格式不对,Django 会返回这个错误信息给用户。

正则表达式的含义

  • ^:表示字符串的开始。
  • 1:手机号的第一位必须是 1
  • [3-9]:手机号的第二位必须是 3-9 中的任何一个数字。
  • \d{9}:接下来的 9 位必须是数字(\d 表示数字,{9} 表示正好 9 个数字)。
  • $:表示字符串的结束。

1.4 编辑靓号

  • 列表页面:/mobile/数字/edit/
  • URL
  • 函数
    • 根据ID获取当前编辑的对象
    • ModelForm配合,默认显示数据。
    • 提交修改。
      在这里插入图片描述

不允许手机号重复。

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

    # [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()
    
    ## 判断手机号是否重复
    def clean_mobile(self):
        txt_mobile = self.cleaned_data['mobile']  # 获取用户提交的手机号
        exists = models.MobileInfo.objects.filter(mobile=txt_mobile).exists()  # 正确调用 exists 方法
        if exists:
            raise ValidationError("手机号已存在")  # 如果手机号已经存在,抛出验证错误
        return txt_mobile

1.5 搜索手机号

models.PrettyNum.objects.filter(mobile="19999999991",id=12)

data_dict = {"mobile":"19999999991","id":123}
models.PrettyNum.objects.filter(**data_dict)
models.PrettyNum.objects.filter(id=12)       # 等于12
models.PrettyNum.objects.filter(id__gt=12)   # 大于12
models.PrettyNum.objects.filter(id__gte=12)  # 大于等于12
models.PrettyNum.objects.filter(id__lt=12)   # 小于12
models.PrettyNum.objects.filter(id__lte=12)  # 小于等于12

data_dict = {"id__lte":12}
models.PrettyNum.objects.filter(**data_dict)
models.PrettyNum.objects.filter(mobile="999")               # 等于
models.PrettyNum.objects.filter(mobile__startswith="1999")  # 筛选出以1999开头
models.PrettyNum.objects.filter(mobile__endswith="999")     # 筛选出以999结尾
models.PrettyNum.objects.filter(mobile__contains="999")     # 筛选出包含999

data_dict = {"mobile__contains":"999"}
models.PrettyNum.objects.filter(**data_dict)

在靓号列表函数中的如下代码便是此功能共:

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

搜索框提交发出q请求,search_data接受请求,并将内容存放在data_dict中,之后在返回HTML界面显示符合条件的搜索结果

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

1.6 分页(使用公共组件)

在上一篇文章中,我们已将介绍了分页组件的使用方法:在这一我们不再重新开发:
下面是分页组件:存放在如图位置即可:
在这里插入图片描述

""""
自定义分页组件,之后如果想使用这个分页组件,你需要做如下的事情:
在视图函数中:
def mobile_list(request):

    # 1. 筛选自的情况去筛选自己的数据
    queryset = models.MobileInfo.objects.filter。all()

    # 2. 实例化分页对象
    page_object = Pagination(request,queryset)


    context = {
        'queryset': page_object.page_queryset,   # 分完页的数据
        "page_string": page_object.html()   # 生成所有的页码
    }
    return render(request, 'mobile_list.html', context)

在HTML页面中进行如下编写
      // 数据的循环展示
      {% for obj in queryset %}
            {{ obj.id }}
      {% endfor %}

      // 页码的展示
      <ul class="pagination">
        {{ page_string }}
      </ul>
"""

from django.utils.safestring import mark_safe
import copy

class Pagination(object):
    def __init__(self, request, queryset, page_size=10, page_param="page", plus=5):
        """
        :param request: 请求对象
        :param queryset: 查询数据(根据此进行分页)
        :param page_size: 每页多少条数据
        :param page_param: URL 参数中的分页参数
        :param plus: 当前页前后显示几页
        """
        query_dict = copy.deepcopy(request.GET)
        query_dict.mutable = True
        self.query_dict = query_dict

        self.params = page_param
        page = request.GET.get(page_param, 1)
        if str(page).isdecimal():
            page = int(page)
        else:
            page = 1
        self.page = page
        self.page_size = page_size
        self.start = (page - 1) * page_size
        self.end = page * page_size
        self.page_queryset = queryset[self.start:min(self.end, len(queryset))]

        # 计算总页数
        total_count = queryset.count()
        self.total_page_count = (total_count + page_size - 1) // page_size
        self.plus = plus
        # # 总页码
        # total_count = queryset.count()
        # total_page_count, div = divmod(total_count, page_size)   ## divmod返回商和余数
        # if div:
        #     total_page_count += 1
        # self.total_page_count = total_page_count
        # self.plus = plus

    def html(self):
        # 计算页码区间
        if self.total_page_count <= 2 * self.plus + 1:
            start_page = 1
            end_page = self.total_page_count
        else:
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus + 1
            else:
                if (self.page + self.plus) > self.total_page_count:
                    start_page = self.total_page_count - 2 * self.plus
                    end_page = self.total_page_count
                else:
                    start_page = self.page - self.plus
                    end_page = self.page + self.plus

        # 页码生成
        page_str_list = []
        self.query_dict.setlist(self.params, [1])
        prev = f'<li><a href="?{self.query_dict.urlencode()}">首页</a></li>'
        page_str_list.append(prev)

        # 上一页
        if self.page > 1:
            self.query_dict.setlist(self.params, [self.page - 1])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">上一页</a></li>'
        else:
            self.query_dict.setlist(self.params, [1])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">上一页</a></li>'
        page_str_list.append(prev)

        # 页码
        for i in range(start_page, end_page + 1):
            self.query_dict.setlist(self.params, [i])
            if i == self.page:
                ele = f'<li class="active"><a href="?{self.query_dict.urlencode()}">{i}</a></li>'
            else:
                ele = f'<li><a href="?{self.query_dict.urlencode()}">{i}</a></li>'
            page_str_list.append(ele)

        # 下一页
        if self.page < self.total_page_count:
            self.query_dict.setlist(self.params, [self.page + 1])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">下一页</a></li>'
        else:
            self.query_dict.setlist(self.params, [end_page])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">下一页</a></li>'
        page_str_list.append(prev)

        # 尾页
        self.query_dict.setlist(self.params, [self.total_page_count])
        prev = f'<li><a href="?{self.query_dict.urlencode()}">尾页</a></li>'
        page_str_list.append(prev)

        page_string = mark_safe("".join(page_str_list))
        return page_string
""""
自定义分页组件,之后如果想使用这个分页组件,你需要做如下的事情:
在视图函数中:
def mobile_list(request):

    # 1. 筛选自的情况去筛选自己的数据
    queryset = models.MobileInfo.objects.filter。all()

    # 2. 实例化分页对象
    page_object = Pagination(request,queryset)


    context = {
        'queryset': page_object.page_queryset,   # 分完页的数据
        "page_string": page_object.html()   # 生成所有的页码
    }
    return render(request, 'mobile_list.html', context)

在HTML页面中进行如下编写
      // 数据的循环展示
      {% for obj in queryset %}
            {{ obj.id }}
      {% endfor %}

      // 页码的展示
      <ul class="pagination">
        {{ page_string }}
      </ul>
"""

from django.utils.safestring import mark_safe
import copy

class Pagination(object):
    def __init__(self, request, queryset, page_size=10, page_param="page", plus=5):
        """
        :param request: 请求对象
        :param queryset: 查询数据(根据此进行分页)
        :param page_size: 每页多少条数据
        :param page_param: URL 参数中的分页参数
        :param plus: 当前页前后显示几页
        """
        query_dict = copy.deepcopy(request.GET)
        query_dict.mutable = True
        self.query_dict = query_dict

        self.params = page_param
        page = request.GET.get(page_param, 1)
        if str(page).isdecimal():
            page = int(page)
        else:
            page = 1
        self.page = page
        self.page_size = page_size
        self.start = (page - 1) * page_size
        self.end = page * page_size
        self.page_queryset = queryset[self.start:min(self.end, len(queryset))]

        # 计算总页数
        total_count = queryset.count()
        self.total_page_count = (total_count + page_size - 1) // page_size
        self.plus = plus
        # # 总页码
        # total_count = queryset.count()
        # total_page_count, div = divmod(total_count, page_size)   ## divmod返回商和余数
        # if div:
        #     total_page_count += 1
        # self.total_page_count = total_page_count
        # self.plus = plus

    def html(self):
        # 计算页码区间
        if self.total_page_count <= 2 * self.plus + 1:
            start_page = 1
            end_page = self.total_page_count
        else:
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus + 1
            else:
                if (self.page + self.plus) > self.total_page_count:
                    start_page = self.total_page_count - 2 * self.plus
                    end_page = self.total_page_count
                else:
                    start_page = self.page - self.plus
                    end_page = self.page + self.plus

        # 页码生成
        page_str_list = []
        self.query_dict.setlist(self.params, [1])
        prev = f'<li><a href="?{self.query_dict.urlencode()}">首页</a></li>'
        page_str_list.append(prev)

        # 上一页
        if self.page > 1:
            self.query_dict.setlist(self.params, [self.page - 1])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">上一页</a></li>'
        else:
            self.query_dict.setlist(self.params, [1])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">上一页</a></li>'
        page_str_list.append(prev)

        # 页码
        for i in range(start_page, end_page + 1):
            self.query_dict.setlist(self.params, [i])
            if i == self.page:
                ele = f'<li class="active"><a href="?{self.query_dict.urlencode()}">{i}</a></li>'
            else:
                ele = f'<li><a href="?{self.query_dict.urlencode()}">{i}</a></li>'
            page_str_list.append(ele)

        # 下一页
        if self.page < self.total_page_count:
            self.query_dict.setlist(self.params, [self.page + 1])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">下一页</a></li>'
        else:
            self.query_dict.setlist(self.params, [end_page])
            prev = f'<li><a href="?{self.query_dict.urlencode()}">下一页</a></li>'
        page_str_list.append(prev)

        # 尾页
        self.query_dict.setlist(self.params, [self.total_page_count])
        prev = f'<li><a href="?{self.query_dict.urlencode()}">尾页</a></li>'
        page_str_list.append(prev)

        page_string = mark_safe("".join(page_str_list))
        return page_string

之后根据组件的使用方法,在靓号列表函数中使用:

    ## 导入自己编写的类,方便分页的代码重复编写
    from app01.utils.pagination import Pagination

    queryset = models.MobileInfo.objects.filter(**data_dict).order_by('-level')
    page_object = Pagination(request,queryset)
    page_queryset = page_object.page_queryset

    page_string = page_object.html()
    context = {
        'queryset': page_queryset,   # 分完页的数据
        "search_data": search_data,
        "page_string": page_string   # 页码
    }
    return render(request, 'mobile_list.html', context)
  • 分页的逻辑和处理规则
  • 封装分页类
    • 从头到尾开发
    • 写项目用【pagination.py】公共组件。

相关文章:

  • 基于SSM的《计算机网络》题库管理系统(源码+lw+部署文档+讲解),源码可白嫖!
  • 软件架构设计:网络基础
  • 计算机网络————(一)HTTP讲解
  • 百度搜索,能否将DeepSeek变成“内功”?
  • 【Linux】:应用层协议 HTTP (超文本传输协议)
  • 和平之翼代码生成器 SHCEU 版 4.0.0RC6 千年隼介绍二
  • 深入理解C语言中的位段
  • 【Linux】匿名管道的应用场景-----管道进程池
  • 基于深度学习的信号滤波:创新技术与应用挑战
  • 基于SpringBoot+vue+uniapp的智慧旅游小程序+LW示例参考
  • react 的 diff 算法
  • 多人协同创作gitea
  • 代码随想录D52-53 图论 Python
  • 深度学习-125-LangGraph之基础知识(二)自定义方式和内置节点方式构建聊天机器人
  • anaconda安装报错
  • MySQL | MySQL库、表的基本操作01
  • github配置sshkey
  • 数字人源码部署方案注意事项-AI口播数字人系统源码部署全解析!
  • ES6 新特性,优势和用法?
  • Windows Arm软件合集2024
  • 司法部:民营经济促进法明确禁止违规异地执法、利用行政或者刑事手段违法干预经济纠纷
  • 特色业务多点开花,苏州银行擦亮金融为民底色
  • 上海营商环境的“分寸”感:底线之上不断拓宽自由,底线之下雷霆制止
  • 消费者在天猫一旗舰店换手机电池疑遭套路致手机损坏,平台已介入
  • 贵州黔西市游船倾覆事故致9人死亡1人失联
  • 日本来信|劳动者的书信④