【玩转全栈】----靓号管理系统实现

先赞后看,养成习惯。。。

目录

数据库设置

基本功能

路由器

靓号显示

靓号添加

靓号编辑

视图函数

额外功能

搜索功能

分页

一般逻辑

动态页码

上下页

首尾页

数据库设置

新建一个数据库(或者就用之前部门、用户管理的也行),用Django连接到数据库:

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "mydata_1",
        "USER": "root",
        "PASSWORD": "您的密码",
        "HOST": "127.0.0.1",
        "PORT": "3306",
    }
}

新建数据库,在models中新建数据表,定义表的结构:

from django.db import models

# Create your models here.
class Vanitynumber(models.Model):
    mobile = models.CharField(verbose_name="手机号",max_length=11, unique=True)
    price = models.IntegerField(verbose_name="价格",default=0)
    # 默认为空:null=True,blank=True
    level_ = {
        (1,"一类号"),
        (2,"二类号"),
        (3,"三类号"),
    }
    statues_ = {
        (1,"占用"),
        (2,"未占用"),
    }
    level = models.SmallIntegerField(verbose_name="级别",choices=level_,default=1)
    status = models.SmallIntegerField(verbose_name="占用情况",choices=statues_,default=2)

迁移数据库命令:

# 生成迁移文件
python manage.py makemigrations

# 应用迁移
python manage.py migrate

可以自己添加点数据并在终端查看是否存入数据库:

 insert into app01_vanitynumber(mobile,price,level,status) values(13992349299,2400,2,2);

【玩转全栈】----靓号管理系统实现_第1张图片

与预期无异。

基本功能

大体跟之前用户、部门管理类似,大家也可以玩玩其他的BootStrap样式

路由器

from django.contrib import admin
from django.urls import path
from sqlalchemy.dialects.mssql.information_schema import views
from app01 import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", views.vanity_show),
    path("vanity/show/", views.vanity_show),
    path("vanity/add/", views.vanity_add),
    path("vanity//edit/", views.vanity_edit),
    path("vanity//delete/", views.vanity_delete),
]

靓号显示

vanity_show.html:

{% extends 'layout.html' %}
{% block content %}
    
靓号列表
{% for items in queryset %} {% endfor %}
ID 号码 价格 类别 占用情况 操作
{ { items.id }} { { items.mobile }} { { items.price }} { { items.get_level_display }} { { items.get_status_display }} 编辑 删除
{% endblock %}

靓号添加

vanity_add.html:

{% extends 'layout.html' %}
{% block content %}
    
新建 靓号
{% csrf_token %} {% for items in form %}
{# #} { { items }} {# 要是有错误信息,会显示#} { { items.errors.0 }} {# 直接手写{ { items }},因为他会自动帮我们生成html标签#}
{# { { items.label }} : { { items }}#} {% endfor %}
{% endblock %}

靓号编辑

vanity_edit.html:

{% extends 'layout.html' %}
{% block content %}
    
编辑 靓号
{% csrf_token %} {% for items in form %}
{ { items }} { { items.errors.0 }}
{% endfor %}
{% endblock %}

视图函数

from django.shortcuts import render,HttpResponse,redirect
from app01.models import Vanitynumber
from django import forms


class VanitynumberForm(forms.ModelForm):
    class Meta:
        model = Vanitynumber
        fields = ['mobile','price','level','status']

    # 2、循环到所有的插件再赋予form-control样式
    def __init__(self,*args,**kwargs):
        super(VanitynumberForm,self).__init__(*args,**kwargs)
        # 循环找到所有的插件
        for name,field in self.fields.items():
            field.widget.attrs = {'class':'form-control'}
def vanity_show(request):
    form = VanitynumberForm()
    queryset = Vanitynumber.objects.all()
    return render(request,'vanity_show.html',{'form':form,'queryset':queryset})

def vanity_add(request):
    """添加用户,ModelForm版本"""
    if request.method == "GET":
        form = VanitynumberForm()
        return render(request, "vanity_add.html",{"form":form})
    # 用户提交POST请求,校验数据
    form = VanitynumberForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect("/vanity/show")
    else:
        print(form.errors)

def vanity_edit(request,nid):
    row_object = Vanitynumber.objects.filter(id=nid).first()
    if request.method == "GET":
        # 根据ID去数据库获取要编辑的那一行数据(对象)
        # 加上instance=row_object会默认将对应ID的数据显示到页面输入框中,这就比之前的部门管理要方便很多
        form = VanitynumberForm(instance=row_object)
        return render(request, "vanity_edit.html", {"form": form})
    # 如果不加下面这行代码,并且UserForm中加instance,那么数据库中就不是更新数据,因为程序不知道要更新哪一行数据,所有程序会自动新添加一行数据,原来数据保持不变
    form = VanitynumberForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/vanity/show/")
    return render(request, "vanity_edit.html", {"form": form})

def vanity_delete(request,nid):
    Vanitynumber.objects.filter(id=nid).delete()
    return redirect("/vanity/show/")

额外功能

搜索功能

搜索功能就是按照输入的某些数字,在已有号码中搜索满足某些条件的内容

Django中搜索的两张方式:

都是差不多的,区别在于第二种传字典作为参数

第一种:

q1 = Vanitynumber.objects.filter(status=1,id=1)
print(q1)

第二种:

data_list = {"mobile":"19999234567","id":3}
q2 = Vanitynumber.objects.filter(**data_list)
print(q2)

使用第二种更方便做其他操作,比如加正则。

Django还提供了一些更加便捷的索引规则,比如双下划线,可将具体筛选规则以字典形式传参,前面要加上双星号。

Vanitynumber.objects.filter(id=12)       # 等于12
Vanitynumber.objects.filter(id__gt=12)   # 大于12
Vanitynumber.objects.filter(id__gte=12)  # 大于等于12
Vanitynumber.objects.filter(id__lt=12)   # 小于12
Vanitynumber.objects.filter(id__lte=12)  # 小于等于12

data_dict1 = {"id__lte":12}
Vanitynumber.objects.filter(**data_dict1)

Vanitynumber.objects.filter(mobile="999")               # 等于
Vanitynumber.objects.filter(mobile__startswith="1999")  # 筛选出以1999开头
Vanitynumber.objects.filter(mobile__endswith="222")     # 筛选出以222结尾
Vanitynumber.objects.filter(mobile__contains="222")     # 筛选出包含222

data_dict2 = {"mobile__contains":"222"}
Vanitynumber.objects.filter(**data_dict2)

在展示页面,我们可以在右上方加个输入框和提交按钮,用户接收用户搜索输入语句,有时用户输入可能包含其他字符,我们可以用正则提取到符合条件的内容,这里是连续的数字。通过data_list搜索到的数据,可以返还到html上,显示搜索到的内容。具体实现代码如下:

views.py:

import re
def vanity_show(request):
    form = VanitynumberForm()
    # 先定义一个壳子,再添加
    data_list = {}
    search_data = request.GET.get('q',"")
    search_data = re.search(r'\d+', search_data)
    if search_data:
        search_data=search_data.group()
    else:
        search_data=""
    if search_data:
        data_list["mobile__contains"] = search_data
    queryset = Vanitynumber.objects.filter(**data_list).order_by('-level')
    return render(request,'vanity_show.html',{'form':form,'queryset':queryset,'search_data':search_data})

        这里通过GET传参获取q和一个空字符串,作用是使当q无值时,默认为空,以避免因data_list无值而产生报错;对search_data运行正则提取第一个出现的连续数字,如果不为空,则解对象,如果为空,赋值空字符串;再将search_data添加到search_list中;通过filter找到符合条件的queryset,传回html

vanity_show.html:

{% extends 'layout.html' %}
{% block content %}
    
靓号列表
{% for items in queryset %} {% endfor %}
ID 号码 价格 类别 占用情况 操作
{ { items.id }} { { items.mobile }} { { items.price }} { { items.get_level_display }} { { items.get_status_display }} 编辑 删除
{% endblock %}

再将符合条件信息展示到页面上,并将输入框传入search_data作为默认值。

这样,就完成了搜索功能。

分页

一般逻辑

        当数据量很大的时候,页面会向下延伸很长,这样不仅影响观感,还浪费空间,可以设置分页功能,为每一页都设置一个最大数据量。

分页的具体逻辑也很简单,也是html标签实现跳转:

  • 但如果页数很多的话,html文件会很长,而且也不利于一些更复杂的操作,可以在视图函数中以字符串的形式传给html页面,但直接传的话会报错,Django无法正常将字符串标签转换为标签,需要在视图函数中引入mark_safe函数,对字符串进行包裹,类似这样:

    mark_safe('
  • ')

    也可将一个一个的标签,动态存入列表,再使用join函数构造字符串,再用mark_safe包裹,传回html,例如:

    data_list = []
    for i in range(start_page,end_page+1):
        if i == page:
            str_html_1 = f'
  • {i}
  • ' else: str_html_1 = f'
  • {i}
  • ' data_list .append(str_html_1) data_str = mark_safe("\n".join(data_list )) queryset = Vanitynumber.objects.filter(**data_list).order_by('-level')[start:end]

    对于多行数据,一页是放不下的,可以一页放一定的数据(这里一页放10条),放多页。

    此时,对于第一页:页数是1,数据是(0,10)

    第二页:页数是2,数据是(10,20)

    ...............

    第 n 页:页数是n,数据是((n-1)×10,n×10)

    数据库中的数据条数是可以用函数得到的:

    num = Vanitynumber.objects.all().count()

    所以可通过总数据条数反推页数

    对于特定的某页,可通过索引在数据库中取值:

    start = (page-1)*10
    end = page * 10
    queryset = Vanitynumber.objects.filter(**data_list).order_by('-level')[start:end]

    再构造标签字符串,使得页面中点击页码就会跳转到该页,并显示数据。

    动态页码

    但如果数据量足够多,页码也会很多,在页面中也显示不完,或者说看着很丑,这时,可用动态页码加以改进:

    我们希望在页面上展示的页码数不能超过一定的阈值(这里是11)。对于用户提交,从而前端返回的页码数page,我们可用只显示page前五页到page后五页,总共11页

    即:

    start_page = page - 5
    end_page = page + 5

    这样去显示效果会好得多,但这样还要问题,当用户点击4页及以前或者最大页码时,左边会出现负数页码,右边则可能会报错,如何解决呢?

    可以增加判断语句,如果页码 <= 5,start_page = 1,如果页码 >= 最大页码 - 4,end_page = 最大页码:

    if start_page < 1:
        start_page = 1
    end_page = page + 5
    # 保证页码不会超限
    if end_page > int(Vanitynumber.objects.all().count()/10):
        end_page = int(Vanitynumber.objects.all().count()/10)

    这样,就能保证不会出现异常。

    上下页

    增加上下页逻辑很简单,就是点击后page相应地加一减一。需要注意的是“上一页”应当放到最前面,"下一页"放到最后面,因为.append()方法是在后面添加,当然,你也可以使用其他的插入函数。

    并且,当page已经是首页或者尾页时,不能跳转了,需要判断一下,具体代码如下:

    # 上一页
    if page >= 1:
        prev = f'
  • 上一页
  • ' page_html_list.append(prev) else: prev = f'
  • 上一页
  • ' page_html_list.append(prev)
    # 下一页
    if page < int(Vanitynumber.objects.all().count() / 10):
        prior = f'
  • 下一页
  • ' page_html_list.append(prior) else: prior = f'
  • 下一页
  • ' page_html_list.append(prior)

    首尾页

    首尾页直接定位即可:

    # 首页
    page_html_list.append(f'
  • 首页
  • ') # 尾页 page_html_list.append(f'
  • 尾页
  • ')

    分页相关代码如下:

    views.py:

     vanity_show(request):
        form = VanitynumberForm()
        data_list = {}
        search_data = request.GET.get('q',"")
        search_data = re.search(r'\d+', search_data)
        if search_data:
            search_data=search_data.group()
        else:
            search_data=""
        if search_data:
            data_list["mobile__contains"] = search_data
    
        page = int(request.GET.get('page',1))
        page_html_list = []
        # 如果展示页码大于10
        if int(Vanitynumber.objects.all().count()/10) > 10:
            # 起止页码
            start = (page-1)*10
            end = page*10
            # 页码轮转
            start_page = page - 5
            # 保证页码不会出现非正数
            if start_page < 1:
                start_page = 1
            end_page = page + 5
            # 保证页码不会超限
            if end_page > int(Vanitynumber.objects.all().count()/10):
                end_page = int(Vanitynumber.objects.all().count()/10)
            # 首页
            page_html_list.append(f'
  • 首页
  • ') # 上一页 if page >= 1: prev = f'
  • 上一页
  • ' page_html_list.append(prev) else: prev = f'
  • 上一页
  • ' page_html_list.append(prev) # 构造标签 for i in range(start_page,end_page+1): if i == page: str_html_1 = f'
  • {i}
  • ' else: str_html_1 = f'
  • {i}
  • ' page_html_list.append(str_html_1) # 下一页 if page < int(Vanitynumber.objects.all().count() / 10): prior = f'
  • 下一页
  • ' page_html_list.append(prior) else: prior = f'
  • 下一页
  • ' page_html_list.append(prior) # 尾页 page_html_list.append(f'
  • 尾页
  • ') # mark_safe使得字符串能在页面正常显示 data_str = mark_safe("\n".join(page_html_list)) queryset = Vanitynumber.objects.filter(**data_list).order_by('-level')[start:end] # 展示页码小于10 else: start = (page - 1) * 10 end = page * 10 num = int(Vanitynumber.objects.all().count()/10) for i in range(1, num+1): if i == page: str_html_2 = f'
  • {i}
  • ' else: str_html_2 = f'
  • {i}
  • ' page_html_list.append(str_html_2) data_str = mark_safe("\n".join(page_html_list)) queryset = Vanitynumber.objects.filter(**data_list).order_by('-level')[start:end] return render(request,'vanity_show.html',{'form':form,'queryset':queryset,'search_data':search_data,'data_str':data_str})

    vanity_show:

    {% extends 'layout.html' %}
    {% block content %}
        
    靓号列表
    {% for items in queryset %} {% endfor %}
    ID 号码 价格 类别 占用情况 操作
    { { items.id }} { { items.mobile }} { { items.price }} { { items.get_level_display }} { { items.get_status_display }} 编辑 删除
      { { data_str }}
    {% endblock %}

    因为用了ModelForm,无序列表中直接{ { data_str }}即可,无需循环。

    需要整个项目源码的可以私信我,这里我就不放出来了,过几天会放到我的资源里,大家自取。

    感谢您的三连!!!

    你可能感兴趣的:(oracle,数据库,django)