dj项目2,靓号管理


1创建模型

from django.db import models

# Create your models here.
class Department(models.Model):
    def __str__(self):
        return self.title
    """部门表"""
    # id=models.BigAutoField(verbose_name="ID",primary_key=True)
    # id=models.BigAutoField(verbose_name="ID",primary_key=True)可以自己写id,上面是bigint,下面是int,verbosename是表字段的注释
    title=models.CharField(verbose_name="标题",max_length=32)
class UserInfo(models.Model):

    """员工表"""
    name=models.CharField(verbose_name="姓名",max_length=16)
    password=models.CharField(max_length=64)
    age=models.IntegerField()
    account=models.DecimalField(verbose_name="账户余额",max_digits=10,decimal_places=2,default=0)
    create_time=models.DateField(verbose_name="入职时间")
    #如果有外键
    #无约束
    # depart = models.BigIntegerField()

    # 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",blank=True,null=True,on_delete=models.SET_NULL)
    gender_choices=(
        (1,"男"),
        (2,"女")
    )
    gender=models.SmallIntegerField(choices=gender_choices,verbose_name="性别")
class PrettyNum(models.Model):
    """靓号表"""
    mobile=models.CharField(verbose_name="手机号",max_length=32)#会用到搜索所以字符串
    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("1111111",55,1,1),("22222222",100,2,2),("33333333",120,4,2);

在这里插入代码片

2靓号列表

这个很简单

def pretty_list(request):
    queryset = models.PrettyNum.objects.all().order_by("-level")  # 按照level降序排序
    return render(request, "pretty_list.html", {"queryset": queryset})

html

{% extends 'layout.html' %}
{% block content %}
    <div class="container">
        <div>
            <a class="btn btn-success" href="/pretty/add/"><!--可以在新页面打开,只需要添加一个target="_blank"-->
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建靓号
            </a>

        </div>
        <div class="panel panel-default" style="margin-top: 10px">
            <div class="panel-heading">
                <h3 class="panel-title"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>靓号列表
                </h3>
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>号码</th>
                    <th>价格</th>
                    <th>等级</th>
                    <th>状态</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for obj in queryset %}
                    <tr>
                        {#                    模版语法中不需要加括号 |date:"Y-m-d H:i:s"#}
                        <td>{{ obj.id }}</td>
                        <td>{{ obj.mobile }}</td>
                        <td>{{ obj.price }}</td>
                        <td>{{ obj.get_level_display }}</td>
                        {#去掉括号#}
                        <td>{{ obj.get_status_display }}</td>
                        <td>
                            <a href="/user/{{ obj.id }}/edit/" class="btn btn-primary btn-xs">编辑</a>
                            <a href="/user/{{ obj.id }}/delete/" class="btn btn-danger btn-xs">删除</a>
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
{% endblock %}

3新建靓号

1列表点击跳转
2url
3modelform类

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

4函数
实例化类对象,render将对象传入html,循环展示所有字段
5点击提交
校验
保存
跳转回列表
这里需要处理mobile为非数字的问题
方式1字段+正则

from django.core.validators import RegexValidator

    mobile=forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1[3-9]\d{9}$','手机号格式错误')],
    )

方法2钩子方法

    def clean_mobile(self):
        txt_mobile=self.cleaned_data
        if len(txt_mobile) !=11:
            raise ValidationError("格式错误")
        return txt_mobile



上面的前提是
    class Meta:
        model = models.PrettyNum
        # fields = "__all__"
        fields=["mobile","price","level","status"]中的fields里面有mobile

编辑

1编辑列表
2url
3views
根据id获取当前编辑对象
modelform配合,默认显示数据
提交修改

  • 修改靓号的时候很少需要对电话号码进行修改,所以用来编辑的类需要进行修改。下面注释行的作用就是防止mobile字段被修改
class PrettyEditModelForm(forms.ModelForm):
    # mobile=forms.CharField(disabled=True)

不允许手机号重复

obj = models.PrettyNum.objects.filter(mobile=).exists()判断查询结果是否为空

这个功能可以加在钩子函数里面
 def clean_mobile(self):
        txt_mobile = self.cleaned_data["mobile"]
        if models.PrettyNum.objects.filter(mobile=txt_mobile).exists():
            raise ValidationError("已存在")
        return txt_mobile
但是编辑提交的时候,手机号一定是存在的,应该是判断排除自己以外是否重复

  • 比较简单的检查可以实用正则表达式,复杂的需要用钩子函数,编辑的完整代码如下
class PrettyEditModelForm(forms.ModelForm):
    # mobile=forms.CharField(disabled=True)
    mobile = forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')],
    )
    class Meta:
        model = models.PrettyNum
        # fields = "__all__"
        fields=["mobile","price","level","status"]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            print(field, name)
            field.widget.attrs = {"class": "form-control"}

    def clean_mobile(self):
        txt_mobile = self.cleaned_data["mobile"]
        if models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists():
            raise ValidationError("已存在")
        return txt_mobile
def pretty_edit(request,eid):
    row_object=models.PrettyNum.objects.filter(id=eid).first()
    if request.method=='GET':
        form = PrettyEditModelForm(instance=row_object)
        return render(request,"pretty_edit.html", {"form":form})
    else:

        form = PrettyEditModelForm(data=request.POST, instance=row_object)  # 这里不能再是直接save了,需要加一个instance,否则就是直接添加了一行
        if form.is_valid():
            # 默认是用户输入的所有数据,如果有不希望用户输入且希望保存的
            # form.instance.字段名=123
            form.save()
            return redirect("/pretty/list/")
        else:
            # print(form.errors)
            return render(request, "pretty_edit.html", {"form": form})  # 这次这个form和get返回的是不一样的,包含了错误信息

搜索手机号

models.PrettyNum.objects.filter(mobile="19999",id=2)
也可以串一个字典
data_dict={"mobile":"19999","id":2}
models.PrettyNum.objects.filter(**data_dict)


models.PrettyNum.objects.filter(id=12)
models.PrettyNum.objects.filter(id__gt=12)
models.PrettyNum.objects.filter(id__gte=12)
models.PrettyNum.objects.filter(id__lt=12)
models.PrettyNum.objects.filter(mobile__startswith="12")
models.PrettyNum.objects.filter(mobile__endswith="12")
models.PrettyNum.objects.filter(mobile__contains="12")
也可以搞成字典

data_dict为空则相当于筛选条件为空,如果不为空就返回筛选后剩下的数据

def pretty_list(request):
    data_dict={}
    serrch_data = request.GET.get("q","")#用于获取 GET 请求中的查询参数 "q" 的值,如果不存在则返回默认值
    if serrch_data:
        data_dict={"mobile__contains":serrch_data}
        # res=models.PrettyNum.objects.filter(**data_dict)
        # print(res)
    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")  # 按照level降序排序
    return render(request, "pretty_list.html", {"queryset": queryset,"serrch_data":serrch_data})

加载container和面板中间的一部分内容,添加了搜索输入框和搜索按钮,注意,button的type必须为submit,输入写在form表单中

<div class="clearfix">
            <a class="btn btn-success" href="/pretty/add/"><!--可以在新页面打开,只需要添加一个target="_blank"-->
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建靓号
            </a>

            <div style="float: right;width: 300px">
                <form action="" method="get">
                    <div class="input-group">

                        <input type="text" class="form-control" placeholder="{{ serrch_data }}" name="q">
                        <span class="input-group-btn">
        <button class="btn btn-default" type="submit">
            <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        </button>
      </span>

                    </div>
                </form>
            </div>

        </div>

分页

先添加300条数据

 # for i in range(300):
    #     models.PrettyNum.objects.create(mobile="1223333333",price=10,level=1,status=2)

使用get请求处理分页,这种分页需要在url中输入页码

 page=int(request.GET.get("page"))
    start=(page-1)*10
    end=start+10
    if serrch_data:
        data_dict={"mobile__contains":serrch_data}
    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")[start:end]  # 按照level降序排序

直接在后端生成html字符串,作为参数传入.html会直接显示字符串,除非标记为安全

from django.utils.safestring import mark_safe
    for i in range(1,21):
        ele='<li><a href="?page={}">{}</a></li>'.format(i,i)
        page_str_list.append(ele)
    page_string=mark_safe(("".join(page_str_list)))#需要标记为安全,否则无法将字符串转换为标签
data=models.PrettyNum.objects.all().acount()符合条件的个数

简单用if-else实现了页码的逻辑,可以输入页码进行跳转,下面是简单的代码
修改后的pretty_list.html

{% extends 'layout.html' %}
{% block content %}
    <div class="container">
        <div class="clearfix">
            <a class="btn btn-success" href="/pretty/add/"><!--可以在新页面打开,只需要添加一个target="_blank"-->
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>新建靓号
            </a>

            <div style="float: right;width: 300px">
                <form action="" method="get">
                    <div class="input-group">

                        <input type="text" class="form-control" placeholder="{{ serrch_data }}" name="q">
                        <span class="input-group-btn">
        <button class="btn btn-default" type="submit">
            <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        </button>
      </span>

                    </div>
                </form>
            </div>

        </div>
        <div class="panel panel-default" style="margin-top: 10px">
            <div class="panel-heading">
                <h3 class="panel-title"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>靓号列表
                </h3>
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>号码</th>
                    <th>价格</th>
                    <th>等级</th>
                    <th>状态</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for obj in queryset %}
                    <tr>
                        {#                    模版语法中不需要加括号 |date:"Y-m-d H:i:s"#}
                        <td>{{ obj.id }}</td>
                        <td>{{ obj.mobile }}</td>
                        <td>{{ obj.price }}</td>
                        <td>{{ obj.get_level_display }}</td>
                        {#去掉括号#}
                        <td>{{ obj.get_status_display }}</td>
                        <td>
                            <a href="/pretty/{{ obj.id }}/edit/" class="btn btn-primary btn-xs">编辑</a>
                            <a href="/pretty/{{ obj.id }}/delete/" class="btn btn-danger btn-xs">删除</a>
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
        <div class="clearfix">
            <nav aria-label="Page navigation">
                <ul class="pagination" style="float: left">
                    {{ page_string }}
                    <li>
                        <form action="" method="get" style="float: left">
                            <div class="input-group" style="width: 200px">
                                <input type="text" class="form-control" placeholder="页码" name="page">
                                <span class="input-group-btn">
            <button class="btn btn-default" type="submit">跳转</button>
          </span>
                            </div>
                        </form>


                    </li>
                </ul>
            </nav>
            {#    这里新加了页码搜索的功能#}

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

views.py中修改后的pretty_list函数

def pretty_list(request):
    data_dict={}
    serrch_data = request.GET.get("q","")#用于获取 GET 请求中的查询参数 "q" 的值,如果不存在则返回默认值
    # for i in range(300):生成数据
    #     models.PrettyNum.objects.create(mobile="1223333333",price=10,level=1,status=2)
    # 符合数据的总条数
    page = int(request.GET.get("page", 1))
    page_size = 10
    start = (page - 1) * page_size
    end = start + page_size

    page_str_list = []
    if serrch_data:
        data_dict={"mobile__contains":serrch_data}

    #数据总条数
    total_count = models.PrettyNum.objects.filter(**data_dict).order_by("-level").count()
    #总页码
    total_page_count, div = divmod(total_count, page_size)
    if div:
        total_page_count += 1
    plus=5
    if total_page_count<=plus*2+1:#数据库数据很少
        start_page=1
        end_page=total_page_count
    else:
        if page<=plus:
            start_page=1
            end_page=2*plus
        elif plus+page>=total_page_count:
            start_page = total_page_count-2*plus
            end_page = total_page_count
        else:
            start_page=page-plus#数据很多
            end_page=page+plus
    if page>1:
        prev = '<li><a href="?page={}">上一页</a></li>'.format(page-1)
    else:
        prev = '<li><a href="?page={}">上一页</a></li>'.format(1)
    if page<total_page_count:
        nxt = '<li><a href="?page={}">下一页</a></li>'.format(page+1)
    else:
        nxt = '<li><a href="?page={}">下一页</a></li>'.format(total_page_count)
    page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))
    page_str_list.append(prev)
    for i in range(start_page, end_page+1):
        if i ==page:
            ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
        else:
            ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)
        page_str_list.append(ele)
    page_str_list.append(nxt)
    page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(total_page_count))
    page_string = mark_safe(("".join(page_str_list)))  # 需要标记为安全,否则无法将字符串转换为标签
    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")[start:end]  # 按照level降序排序
    return render(request, "pretty_list.html", {"queryset": queryset,"serrch_data":serrch_data,"page_string":page_string})

  • 封装分页类
    写项目用pagination.py公共组件
"""
自定义组件
自定义的分页组件,以后如果想要用这个分页组件,你需要做如下几件事:
def pretty_list(request):
    #1根据自己的情况去筛选自己的数据
    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")
    #2实例化分页对象
     page_obj=Pagenation(request,queryset)

    context={
        "queryset": page_obj.page_queryset,#分完页的数据

        "page_string": page_obj.html()#生成页码
    }
    return render(request, "pretty_list.html", context)

    在html中
    数据:
     {% for obj in queryset %}
                        <td>{{ obj.id }}</td>
                {% endfor %}
    页码:
     <ul class="pagination" style="float: left">
                    {{ page_string }}

                </ul>
"""
from django.utils.safestring import mark_safe
class Pagenation(object):
    def __init__(self,request,queryset,page_size = 10,page_param="page",plus=5):
        """

        :param request: 请求对象
        :param queryset: 查询的符合条件的数据
        :param page_size: 每页显示多少条数据
        :param page_param: yrl中get的参数
        :param plus: 当前页的前后多少个被显示
        """
        page=request.GET.get(page_param,"1")
        if page.isdecimal():
            page=int(page)
        else:page=1
        self.page=page
        # print(page,type(page))
        self.page_size=page_size
        start = (page - 1) * page_size
        end = start + page_size
        self.start=start
        self.end=end
        self.page_queryset=queryset[self.start:self.end]
        # 数据总条数
        total_count = queryset.count()
        # 总页码
        total_page_count, div = divmod(total_count, page_size)
        if div:
            total_page_count += 1
        self.total_page_count=total_page_count
        self.plus=plus
        self.page_str_list = []
    def html(self):
        if self.total_page_count <= self.plus * 2 + 1:  # 数据库数据很少
            start_page = 1
            end_page = self.total_page_count
        else:
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus
            elif self.plus + self.page >= 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
        if self.page > 1:
            prev = '<li><a href="?page={}">上一页</a></li>'.format(self.page - 1)
        else:
            prev = '<li><a href="?page={}">上一页</a></li>'.format(1)
        if self.page < self.total_page_count:
            nxt = '<li><a href="?page={}">下一页</a></li>'.format(self.page + 1)
        else:
            nxt = '<li><a href="?page={}">下一页</a></li>'.format(self.total_page_count)
        self.page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))
        self.page_str_list.append(prev)
        for i in range(start_page, end_page + 1):
            if i == self.page:
                ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
            else:
                ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)
            self.page_str_list.append(ele)
        self.page_str_list.append(nxt)
        self.page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(self.total_page_count))
        search_string = """<li>
                            <form action="" method="get" style="float: left">
                                <div class="input-group" style="width: 200px">
                                    <input type="text" class="form-control" placeholder="页码" name="page">
                                    <span class="input-group-btn">
                <button class="btn btn-default" type="submit">跳转</button>
              </span>
                                </div>
                            </form>
                        </li>"""
        self.page_str_list.append(search_string)
        page_string = mark_safe(("".join(self.page_str_list)))  # 需要标记为安全,否则无法将字符串转换为标签
        return page_string

def pretty_list(request):
    # for i in range(300):生成数据
    #     models.PrettyNum.objects.create(mobile="1223333333",price=10,level=1,status=2)

    serrch_data = request.GET.get("q", "")  # 用于获取 GET 请求中的查询参数 "q" 的值,如果不存在则返回默认值
    data_dict = {}

    if serrch_data:
        data_dict={"mobile__contains":serrch_data}
    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")
    page_obj=Pagenation(request,queryset)
    context={
        "queryset": page_obj.page_queryset,
        "serrch_data": serrch_data,
        "page_string": page_obj.html()
    }
    return render(request, "pretty_list.html", context)

还有一个小bug,搜索&分页

bootstrap样式父类

  • 项目文件的整理

自定义一个类,放在app01的utils目录下,命名为bootstrap,然后将views里的UserModelForm,PrettyModelForm,PrettyEditModelForm三个类装在utils目录下的form.py文件中,form.py要导入bootstrap中的父类;再把user,pretty,depart分别装在app下的views目录下,把原来的views删掉,导入包。修改urls的导入和url路径,就完成了项目文件的整理。

class BootStrapModelForm(forms.ModelForm):
    # mobile=forms.CharField(disabled=True)
    class Meta:
        model = models.PrettyNum
        # fields = "__all__"
        fields=["mobile","price","level","status"]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            # print(field, name)
            #字段中有属性保留原来的属性,没有属性才增加
            if field.widget.attrs:
                field.widget.attrs["class"] ="form-control"
                field.widget.attrs["placeholder"] =field.label
            else:
                field.widget.attrs = {"class": "form-control","placeholder":field.label}

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值