Django 管理平台用户界面编写

Django 网页公共部分编写

前言:目前还在学习中,这是第一个尝试的项目,多有不足,感谢大家的观看与批评。

目标:

一. 前端页面

这次没找到前辈的模板,自行编写base.html和base.css

<!DOCTYPE html>
<html lang="zh-CN">
{% load static %}
<head>
    <meta charset="UTF-8">
    <title>用户界面</title>
    <link rel="stylesheet" type="text/css" href="{% static 'base/scripts/svg_img/iconfont.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'base/css/base.css' %}">
</head>
<body>
    {# 上方基本信息展示 #}
    <nav class="nav_top">
        <div class="leftNav iconfont">&#xe673;&nbsp刷票管理平台</div>
        <div class="rightSvg iconfont">&#xe60f;</div>
        <div class="rightNav">zcc</div>
    </nav>

    {# 下方主要内容部分 #}
    <div class="main_content">
        <div class="mainDiv">
            {# 左边导航栏 #}
            <div class="leftDiv">
                <div class="iconfont">&#xe74a; 用户信息</div>
                <ul class="user_info" style="margin-bottom: 0">
                    <a href="#"><li>个人资料</li></a>
                    <a href="#"><li>我的交易</li></a>
                </ul>
                <div class="iconfont">&#xe600; 平台分类</div>
                <ul class="plat_type">
                    <a href="#"><li>央视频</li></a>
                    <a href="#"><li>B站完播</li></a>
                    <a href="#"><li>B站播放量(30%~50%完播)</li></a>
                </ul>
            </div>

            {# 右侧用户操作内容展示,这里是上方的小字导航栏和右侧、下侧的滑块部分 #}
            <div class="rightDiv">
                <div class="infor">
                </div>
                <div class="information">
                </div>
            </div>
        </div>
    </div>
</body>
</html>
* {
    margin: 0;
    padding: 0;
}

/*顶部基本信息展示部分*/
.nav_top {
    background-color: #2f72ab;
    width: 100%;
    height: 60px;
    border-top-left-radius: 12px;
    border-top-right-radius: 12px;
    position: fixed;
}

/*左部导航栏*/
.leftNav {
    float: left;
    height: 20px;
    padding-left: 40px;
    padding-top: 20px;
    font-family: Microsoft YaHei;
    color: white;
}

/*右侧用户操作内容部分*/
.rightNav {
    float: right;
    height: 20px;
    padding-top: 20px;
    font-family: Microsoft YaHei;
    color: white;
}

.rightSvg {
    float: right;
    height: 40px;
    line-height: 40px;
    font-size: 36px;
    padding-right: 40px;
    padding-top: 10px;
    color: white;
}

.main_content {
    width: 100%;
    height: calc(100vh - 60px);
    display: flex;
    flex-flow: column nowrap;
}

.mainDiv {
    margin-top: 60px;
    flex: 1;
}

/*去除左侧导航栏所有超链接的下划线*/
.main_content .mainDiv .leftDiv ul a:hover {
    text-decoration: none;
}

.leftDiv {
    float: left;
    width: calc(20% - 6px);
    height: calc(100vh - 60px);;
    background-color: #eaedf1;
}

.leftDiv div {
    background-color: #f5f5f5;
    padding-left: 10px;
    height: 40px;
    line-height: 40px;
}

.leftDiv li {
    background-color: #fff;
    padding-left: 30px;
    height: 30px;
    line-height: 30px;
    color: #2f72ab;
}

.rightDiv {
    float: left;
    width: 80%;
    height: calc(100vh - 60px);
    margin-left: 5px;
    overflow: scroll;
    border-left: #e8e8e8 solid 1px;
}

/*用户操作部分上方导航*/
.infor {
    width: 100%;
    height: 30px;
    background-color: #f5f5f5;
    padding-left: 20px;
    line-height: 30px;
}

.infor ul li {
    display: inline-block;
    list-style-type: none;
}

.infor ul li a {
    color: black;
}

.infor ul li a:hover {
    text-decoration: none;
}

/*右侧上方小导航部分,最后一部分文字颜色不一样*/
.infor ul li a:last-child {
    color: #828282;
}

.information {
    width: 100%;
}

注意:

1.  矢量图下载与使用:iconfont-阿里巴巴矢量图标库,按照官网流程操作。

2.  注意margin的使用——相邻块元素合并嵌套块元素塌陷。建议多用padding。

3. CSS各个单位的区别:px、pt、em、rem、vh、vw。参考前辈文章常见CSS单位总结_css 相对单位-CSDN博客

4. 自动填充页面剩余部分:使用Flex布局 - - > 参考前辈文章Flex布局详解-CSDN博客

二. Django前端调整

添加 {% block style %}{% endblock %} 用于其他页面添加CSS代码;使用 {{ title }} 用于不同的标题, {{ username }} 同理。

<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
    <link rel="stylesheet" type="text/css" href="{% static 'base/scripts/svg_img/iconfont.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'base/css/base.css' %}">
    {% block style %}{% endblock %}
</head>
<body>

<nav class="nav_top">
    <div class="leftNav iconfont">&#xe673;&nbsp刷票管理平台</div>
    <div class="rightSvg iconfont">&#xe60f;</div>
    <div class="rightNav">{{ username }}</div>
</nav>

用户操作部分:

{% block spans %}{% endblock %} 用于修改上方小导航;{% block information %}{% endblock %} 用于添加主题内容。

<div class="rightDiv">
    <div class="infor">
        {% block spans %}
        {% endblock %}
    </div>
    <div class="information">
        {% block information %}
        {% endblock %}
    </div>
</div>

至此结束。

Django 用户资料界面编写

目标:

一. 前端页面

引入公共部分 base.html

{% extends 'base_html/base.html' %}

引入CSS文件和Bootstrap

{% load static %}

{% block style %}
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
    <link rel="stylesheet" type="text/css" href="{% static 'user/css/user.css' %}">
{% endblock %}

右侧上方小导航部分:

{% block spans %}
    <ul>
        <li>
            <a href="#"><span>用户信息</span></a>
            <span>/</span>
        </li>
        <li>
            <a href="#"><span>个人资料</span></a>
        </li>
    </ul>
{% endblock %}

右侧主体部分:

{% block information %}
    {# 左侧用户资料 #}
    <div class="myInfo">
        <div class="iconfont">&#xe74a; 我的资料</div>
        <div>
            <table>
                <tbody>
                <tr>
                    <td>用户名</td>
                    <td>{{ username }}</td>
                </tr>
                <tr>
                    <td>账户余额</td>
                    <td>{{ balance }}</td>
                </tr>
                <tr>
                    <td>注册时间</td>
                    <td>{{ regTime }}</td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>

    {# 右侧修改密码 #}
    <div class="pwdChange">
        <div class="iconfont">&#xe62e; 修改密码</div>
        <div>
            <form id="pwd-form" method="post" role="form" novalidate>
                {% csrf_token %}
                <table>
                    <tbody>
                    <tr>
                        <td>密码</td>
                        <td>{{ form.enterPwd }}</td>
                    </tr>
                    <tr>
                        <td>确认密码</td>
                        <td>{{ form.ensurePwd }}</td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <button type="submit" class="form-control">提交</button>
                            <span class="error_massage">
                                {{ form.ensurePwd.errors }}
                            </span>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </form>
        </div>
    </div>
{% endblock %}

CSS代码:

/*左侧导航栏左边装饰效果*/
.leftDiv .user_info > a:first-child li {
    border-left: #2f72ab solid 5px;
    padding-left: 25px;
}

/*Flex布局*/
.information{
    display: flex;
    flex-flow: row nowrap;
    justify-content: space-between;
}

.information .myInfo{
    margin-left: 25px;
    width: 47%;
    margin-top: 25px;
    height: 250px;
}

.information .pwdChange{
    margin-right: 25px;
    width: 47%;
    margin-top: 25px;
    height: 250px;
}

/*左侧用户资料*/
/*上面的名字*/
.information .myInfo div:first-child{
    width: 100%;
    height: 50px;
    border: #eaedf1 solid 2px;
    background-color: #f5f5f5;
    line-height: 50px;
    padding-left: 20px;
    font-weight: bold;
}

.information .myInfo div:last-child{
    width: 100%;
    height: 200px;
    border: #eaedf1 solid 2px;
    border-top: #eaedf1 solid 0;
}

.information .myInfo div table{
    padding-top: 20px;
    padding-left: 36px;
    border-collapse: initial;
}

.information .myInfo div table tr td{
    padding: 10px;
}

.information .myInfo div table tr td:first-child{
    text-align: right;
    font-weight: bold;
}

/*右侧·修改密码*/
.information .pwdChange div:first-child{
    width: 100%;
    height: 50px;
    border: #eaedf1 solid 2px;
    background-color: #f5f5f5;
    line-height: 50px;
    padding-left: 20px;
    font-weight: bold;
}

.information .pwdChange div:last-child{
    width: 100%;
    height: 200px;
    border: #eaedf1 solid 2px;
    border-top: #eaedf1 solid 0;
}

.information .pwdChange div table{
    padding-top: 20px;
    padding-left: 36px;
    border-collapse: initial;
}

.information .pwdChange div table tr td{
    padding: 10px;
}

.information .pwdChange div table tr td:first-child{
    text-align: right;
    font-weight: bold;
}

.information .pwdChange div table tr button{
    width: 27%;
    height: 30px;
    line-height: 5px
}

.error_massage li{
    color: red;
    list-style-type: none;
    padding-top: 5px;
}

二. Django后端各种py文件

urls.py:

int:id 用于传输登录用户的id,便于后续查询数据库。

name:"user_view" 方便后续跳转网页。

path('user/<int:id>/', user_views.user, name="user_view"),

views.py:

和上一篇博客的login差不多,但存在问题,即修改密码后刷新浏览器会出现警告“新密码不应该与旧密码相同”

class pwdForm(forms.Form):
    # 输入新密码
    enterPwd = forms.CharField(
        required=True,
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "请输入密码", 'style': "width: 200%"}),
        error_messages={"required": "该字段不能为空"},
        label='输入密码'
    )

    # 确认密码
    ensurePwd = forms.CharField(
        required=True,
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "请确认密码", 'style': "width: 200%"}),
        error_messages={"required": "该字段不能为空"},
        label='确认密码'
    )

def user(request, **kwargs):
    # 获取数据库数据
    user_id = kwargs.get('id')
    user_info = User.objects.get(id=user_id)

    username = user_info.name
    oldPwd = user_info.pwd
    balance = user_info.balance
    regTime = user_info.regTime

    if request.method == "GET":
        form = pwdForm()
        return render(request, 'user_html/user.html',
                      {"form": form, "title": "用户界面", "username": username, "balance": balance, "regTime": regTime,
                       "userId": user_id})

    elif request.method == 'POST':
        form = pwdForm(request.POST)
        if form.is_valid():
            # 输入新密码
            enterPwd = form.cleaned_data['enterPwd']
            # 确认密码
            ensurePwd = form.cleaned_data['ensurePwd']

            if enterPwd == ensurePwd and enterPwd != oldPwd:
                User.objects.filter(id=user_id).update(pwd=enterPwd)
                form.add_error("ensurePwd", "密码修改成功")
                return render(request, "user_html/user.html",
                              {"form": form, id: user_id, "title": "用户界面", "username": username, "balance": balance,
                               "regTime": regTime, "userId": user_id})

            # 浏览器刷新后自动提交表单导致出现"新密码不应该与旧密码相同"提醒
            elif enterPwd == ensurePwd and enterPwd == oldPwd:
                form.add_error("ensurePwd", "新密码不应该与旧密码相同")
                return render(request, "user_html/user.html",
                              {"form": form, id: user_id, "title": "用户界面", "username": username, "balance": balance,
                               "regTime": regTime, "userId": user_id})

            else:
                form.add_error("ensurePwd", "两次密码不一致")
                return render(request, "user_html/user.html",
                              {"form": form, id: user_id, "title": "用户界面", "username": username, "balance": balance,
                               "regTime": regTime, "userId": user_id})
    else:
        form = pwdForm()

        return render(request, 'user_html/user.html',
                      {"form": form, "title": "用户界面", "username": username, "balance": balance, "regTime": regTime,
                       "userId": user_id})

Django交易界面编写

目标:

一. 前端页面

使用bootstrap即可,没什么注意点。

二. Django分页器Paginator

此处参考了这位前辈的文章:Django 使用Paginator分页器_django paginator-CSDN博客

from django.core.paginator import Paginator

2.0 创建数据库

class Transaction(models.Model):
    ACTION_STATES = {
        "Y": "已执行",
        "N": "待执行"
    }

    username = models.CharField(verbose_name='用户名', max_length=32)
    actionDate = models.DateField(verbose_name='交易日期', auto_now=True)
    actionNumber = models.CharField(verbose_name='订单号', max_length=32, default="")
    aimUrl = models.CharField(verbose_name='目标URL', max_length=256)
    actionAmount = models.IntegerField(verbose_name='刷单数量', default=0)

    # 最大数位为5,小数点后保留两位小数
    originalPrice = models.DecimalField(verbose_name='原价', max_digits=5, decimal_places=2, default=0.00)
    deductionPrice = models.DecimalField(verbose_name='折扣价', max_digits=5, decimal_places=2, default=0.00)

    originalBroadcast = models.CharField(verbose_name="原播放量", max_length=32, default="0")
    actionState = models.CharField(verbose_name="状态", max_length=1, choices=ACTION_STATES, default="N")
    note = models.CharField(verbose_name="备注", max_length=128, default="测试")

注意点:

(1). choices

ACTION_STATES = {
        "Y": "已执行",
        "N": "待执行"
    }

actionState = models.CharField(verbose_name="状态", max_length=1, choices=ACTION_STATES, default="N")

方便操作,后续使用时,object.actionState = "Y", object.get_actionState_display = "已执行"。

(2). 保留两位小数

originalPrice = models.DecimalField(verbose_name='原价', max_digits=5, decimal_places=2, default=0.00)

max_digits=5:最大数位为5;decimal_places=2:保留两位小数。

2.1 创建实例

order_info = Transaction.objects.filter(username=username)

paginator = Paginator(order_info, 10) # 数据来源为order_info,每页最多十行数据

page = request.GET.get('page', 1)  # 获取当前请求的页码,默认为第一页

currentData = paginator.get_page(page) # 获取第一页的数据,传递到前端页面

前端代码:

<tbody>
{% for order in currentDate %}
    <tr>
        <td>{{ order.actionDate }}</td>
        <td>{{ order.actionNumber }}</td>
        <td>{{ order.aimUrl }}</td>
        <td>{{ order.actionAmount }}</td>
        <td>¥{{ order.originalPrice }}</td>
        <td>¥{{ order.deductionPrice }}</td>
        <td>{{ order.originalBroadcast }}</td>
        <td>{{ order.get_actionState_display }}</td>
        <td>{{ order.note }}</td>
    </tr>
{% endfor %}
</tbody>

分页效果:

<ul class="pagination">
    {% if order_list.has_previous %}
    <li class="page-item"><a class="page-link" href="?id={{ currentData.previous_page_number }}">上一页</a></li>
    {% else %}
    <li class="page-item disabled"><a class="page-link" href="#">上一页</a></li>
    {% endif %}

    {# ... #}
</ul>

2.3 优化

def YSP(request, **kwargs):
    user_id = kwargs.get('id')
    user_info = User.objects.get(id=user_id)
    username = user_info.name

    # 获取分页数据
    order_info = Transaction.objects.filter(username=username)

    # 创建实例
    orderPaginator = Paginator(order_info, 10)
    currentPage = int(request.GET.get("id", 1))

    # 当数据大于10页时,页面只显示10页
    if orderPaginator.num_pages > 15:
        if currentPage - 5 < 1:
            pageRange = range(1, 11)
        elif currentPage + 5 > orderPaginator.num_pages:
            pageRange = range(currentPage - 5, orderPaginator.num_pages)
        else:
            pageRange = range(currentPage - 5, currentPage + 5)
    else:
        pageRange = orderPaginator.page_range

    # 分页器id超出范围时返回第一面或最后一面
    try:
        order_list = orderPaginator.page(currentPage)
    except PageNotAnInteger:
        order_list = orderPaginator.page(1)
    except EmptyPage:
        order_list = orderPaginator.page(orderPaginator.num_pages)

    return render(request, "user_html/YSP.html", {"userId": user_id,
                                                  "username": username,
                                                  "order_list": order_list,
                                                  "paginator": orderPaginator,
                                                  "page_range": pageRange,
                                                  "currentPage": currentPage,
                                                  "title": "平台分类"})

前端代码:

<table class="table table-bordered">
    <thead>
    <tr>
        <th>日期</th>
        <th>订单号</th>
        <th>URL</th>
        <th>数量</th>
        <th>原价</th>
        <th>折扣价</th>
        <th>原播放量</th>
        <th>状态</th>
        <th>备注</th>
        <th>删除</th>
    </tr>
    </thead>

    <tbody>

    {% for order in order_list %}
        <tr>
            <td>{{ order.actionDate }}</td>
            <td>{{ order.actionNumber }}</td>
            <td>{{ order.aimUrl }}</td>
            <td>{{ order.actionAmount }}</td>
            <td>¥{{ order.originalPrice }}</td>
            <td>¥{{ order.deductionPrice }}</td>
            <td>{{ order.originalBroadcast }}</td>
            <td>{{ order.get_actionState_display }}</td>
            <td>{{ order.note }}</td>
            <td>
                <form method="GET" action="./deleteOrder/">
                    {% csrf_token %}
                    <input type="hidden" name="order_actionNumber" value="{{ order.actionNumber }}">
                    <button type="submit" class="btn btn-danger btn-xs">删除</button>
                </form>
            </td>
        </tr>
    {% endfor %}

    </tbody>

</table>

<nav class="d-flex justify-content-center" aria-label="Page navigation example">
    <ul class="pagination">

        {% if order_list.has_previous %}
            <li class="page-item"><a class="page-link" href="?id={{ order_list.previous_page_number }}">上一页</a>
            </li>
        {% else %}
            <li class="page-item disabled"><a class="page-link" href="#">上一页</a></li>
        {% endif %}

        {% for item in page_range %}
            {% if item == currentPage %}
                <li class="page-item active"><a class="page-link" href="?id={{ item }}">{{ item }}</a></li>
            {% else %}
                <li class="page-item"><a class="page-link" href="?id={{ item }}">{{ item }}</a></li>
            {% endif %}
        {% endfor %}

        {% if order_list.has_next %}
            <li class="page-item"><a class="page-link" href="?id={{ order_list.next_page_number }}">下一页</a></li>
        {% else %}
            <li class="page-item disabled"><a class="page-link" href="#">下一页</a></li>
        {% endif %}

        <li class="page-item">
            <span class="page-link" id="stataData"
                  style="color: #828282">共 {{ paginator.count }} 条数据, 页码{{ currentPage }}/{{ paginator.num_pages }}页</span>
        </li>
    </ul>
</nav>

2.4 实际效果

三. 添加与删除订单

目标页面:

后端代码:

def createOrder(request, **kwargs):
    user_id = kwargs.get('id')
    user_info = User.objects.get(id=user_id)
    username = user_info.name

    if request.method == 'POST':
        form = CORForm(request.POST)
        if form.is_valid():
            aimUrl = form.cleaned_data['aimUrl']
            actionAmount = form.cleaned_data['actionAmount']
            note = form.cleaned_data['note']
            actionNumber = ''.join(str(random.randint(0, 9)) for _ in range(22))
            originalPrice = 0.0004 * actionAmount
            Transaction.objects.create(username=username, actionNumber=actionNumber, aimUrl=aimUrl,actionAmount=actionAmount, originalPrice=originalPrice, note=note)
            return redirect("YSP", id=user_id)
    else:
        form = CORForm()
        return render(request, "user_html/createOrder.html",
                      {"userId": user_id, "username": username, "form": form, "title": "平台分类"})


def deleteOrder(request, **kwargs):
    user_id = kwargs.get('id')
    user_info = User.objects.get(id=user_id)
    username = user_info.name

    if request.method == 'POST':
        delete_actionNumber = request.POST.get("order_actionNumber")
        order_info = Transaction.objects.get(actionNumber=delete_actionNumber)
        order_info.delete()
        return redirect("YSP", id=user_id)
    else:
        delete_actionNumber = request.GET.get("order_actionNumber")
        order_info = Transaction.objects.get(actionNumber=delete_actionNumber)
        return render(request, "user_html/deleteOrder.html",
                      {"userId": user_id, "username": username, "order": order_info, "title": "平台分类"})

普通的增加 Transaction.objects.create() 和

删除 Transaction.objects.get(actionNumber=delete_actionNumber).delete() 。

四. 交易记录页面

创建数据库

class Operation(models.Model):
    OPERATIONS = {
        "D": "删除订单",
        "C": "创建订单",
        "O": "执行订单",
    }
    NOTES = {
        "Y": "央视频播放",
        "B": "B站播放",
        "T": "B站30%播放",
    }

    username = models.CharField(verbose_name='用户名', max_length=32, default="")
    actionNumber = models.CharField(verbose_name='订单号', max_length=32, default="")
    transactionAmountSign = models.CharField(verbose_name='交易金额正负', max_length=1, default="+")
    transactionAmount = models.DecimalField(verbose_name='交易金额', max_digits=5, decimal_places=2, default=0.00)
    operator = models.CharField(verbose_name='操作员', max_length=32, default="-")
    actionDate = models.DateField(verbose_name='交易日期', auto_now=True)
    operation = models.CharField(verbose_name='操作类型', max_length=1, choices=OPERATIONS)
    note = models.CharField(verbose_name="备注", max_length=1, choices=NOTES)

后端代码编写:

由于分页器用得比较多,所以包装成函数

def makePagination(data_list, request):
    from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage

    Paginator = Paginator(data_list, 10)
    currentPage = int(request.GET.get("id", 1))

    if Paginator.num_pages > 15:
        if currentPage - 5 < 1:
            pageRange = range(1, 11)
        elif currentPage + 5 > Paginator.num_pages:
            pageRange = range(currentPage - 5, Paginator.num_pages)
        else:
            pageRange = range(currentPage - 5, currentPage + 5)
    else:
        pageRange = Paginator.page_range

    try:
        page_list = Paginator.page(currentPage)
    except PageNotAnInteger:
        page_list = Paginator.page(1)
    except EmptyPage:
        page_list = Paginator.page(Paginator.num_pages)

    page_list = {"page_list": page_list, "Paginator": Paginator, "pageRange": pageRange, "currentPage": currentPage}
    return page_list
def transaction(request, **kwargs):
    user_id = kwargs.get('id')
    user_info = User.objects.get(id=user_id)
    username = user_info.name
    operation_info = Operation.objects.filter(username=username)

    page_list = makePagination(operation_info, request)

    return render(request, "user_html/transaction.html", {"userId": user_id,"username": username,"operation_list": page_list['page_list'],"paginator": page_list['Paginator'],"page_range": page_list['pageRange'],"currentPage": page_list['currentPage'],"title": "交易记录"})

关于顶部快速筛选的button,先欠着,以后再补

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值