strak组件(6):列表定制列应用和引入静态文件

效果图:

新增函数

def get_choice_text(title, field)   闭包函数,显示choice字段
    def inner(self, obj=None, is_header=None)

 def display_edit(self, obj=None, is_header=None)  显示编辑
 def display_delete(self, obj=None, is_header=None) 显示删除

一、Model

web/models.py

class UserInfo(models.Model):
    """
    用户表
    """
    MALE = 1
    FEMALE = 2
    GENDER_CHOICES = (
        (MALE, ''),
        (FEMALE, ''),
    )
    CLASSES_CHOICES = (
        (1, 'python一班'),
        (2, 'python二班'),
    )
    name = models.CharField(verbose_name='姓名', max_length=32)
    age = models.CharField(verbose_name='年龄', max_length=32)
    email = models.CharField(verbose_name='邮箱', max_length=32)
    gender = models.PositiveIntegerField(verbose_name='性别', choices=GENDER_CHOICES, default=MALE)
    classes = models.PositiveIntegerField(verbose_name='班级', choices=CLASSES_CHOICES, default=1)
    department = models.ForeignKey(verbose_name='部门', to='Department', on_delete=models.CASCADE)

    def __str__(self):
        return self.name

二、stark

stark/service/core_func.py

from types import FunctionType

from django.urls import re_path
from django.utils.safestring import mark_safe
from django.shortcuts import HttpResponse, render, reverse


def get_choice_text(title, field):
    """
    对于Stark组件中定义列时,choice如果想要显示中文信息,调用此方法即可。
    :param title: 希望页面显示的表头
    :param field:  字段名称
    :return:
    """

    def inner(self, obj=None, is_header=None):
        if is_header:
            return title
        method = "get_%s_display" % field
        return getattr(obj, method)()
        # GENDER_CHOICES = ((MALE, '男'),(FEMALE, '女'),)
        # 对于choice字段,如果想获取获取第二个值,可以通过:对象.get_字段名_display()
    return inner


class StarkHandler(object):
    list_display = []

    def __init__(self, site, model_class, prev):
        self.site = site
        self.model_class = model_class
        self.prev = prev

    def display_edit(self, obj=None, is_header=None):
        """
        自定义页面显示的列(表头和内容)
        :param obj:
        :param is_header:
        :return:
        """
        if is_header:
            return '编辑'
        name = '%s:%s' % (self.site.namespace, self.get_edit_url_name,)
        return mark_safe('<a href="%s">编辑</a>' % reverse(name, args=(obj.pk,)))

    def display_delete(self, obj=None, is_header=None):
        if is_header:
            return '删除'
        name = '%s:%s' % (self.site.namespace, self.get_delete_url_name,)
        return mark_safe('<a href="%s">删除</a>' % reverse(name, args=(obj.pk,)))

    def get_list_display(self):
        """
        获取页面上应该显示的列,预留的自定义扩展,例如:以后根据用户的不同显示不同的列
        :return:
        """
        value = []
        value.extend(self.list_display)
        return value

    def list_view(self, request):
        """
        列表页面
        :param request:
        :return:
        """

        list_display = self.get_list_display()  # 会优先调用UserInfoHandler里的get_list_display()方法。
        # 1. 处理表格的表头
        header_list = []
        if list_display:
            for field_or_func in list_display:
                if isinstance(field_or_func, FunctionType):
                    verbose_name = field_or_func(self, obj=None, is_header=True)
                else:
                    verbose_name = self.model_class._meta.get_field(field_or_func).verbose_name
                header_list.append(verbose_name)
        else:
            header_list.append(self.model_class._meta.model_name)  # 如果用户没有填写list_display,就显示表名

        # 2. 处理表的内容
        data_list = self.model_class.objects.all()
        body_list = []
        for obj in data_list:
            tr_list = []
            if list_display:
                for field_or_func in list_display:
                    if isinstance(field_or_func, FunctionType):
                        tr_list.append(field_or_func(self, obj, is_header=False))
                    else:
                        tr_list.append(getattr(obj, field_or_func))
            else:
                tr_list.append(obj)  # 如果用户没有填写list_display,就显示表对象,所以表类要定义__str__方法
            body_list.append(tr_list)

        context = {
            'data_list': data_list,
            'header_list': header_list,
            'body_list': body_list,
        }

        return render(request, 'stark/data_list.html', context)

    def add_view(self, request):
        """
        添加页面
        :param request:
        :return:
        """
        return HttpResponse('添加页面')

    def edit_view(self, request, pk):
        """
        编辑页面
        :param request:
        :return:
        """
        return HttpResponse('编辑页面')

    def delete_view(self, request, pk):
        """
        删除页面
        :param request:
        :param pk:
        :return:
        """
        return HttpResponse('删除页面')

    def get_url_name(self, params):
        app_label, model_name = self.model_class._meta.app_label, self.model_class._meta.model_name
        if self.prev:
            return '%s_%s_%s_%s' % (app_label, model_name, self.prev, params)
        return '%s_%s_%s' % (app_label, model_name, params)

    @property
    def get_list_url_name(self):
        """
        获取列表页面URL的name
        :return:
        """
        return self.get_url_name('list')

    @property
    def get_add_url_name(self):
        """
        获取添加页面URL的name
        :return:
        """
        return self.get_url_name('add')

    @property
    def get_edit_url_name(self):
        """
        获取编辑页面URL的name
        :return:
        """
        return self.get_url_name('edit')

    @property
    def get_delete_url_name(self):
        """
        获取删除页面URL的name
        :return:
        """
        return self.get_url_name('delete')

    def get_urls(self):
        patterns = [
            re_path(r'^list/$', self.list_view, name=self.get_list_url_name),
            re_path(r'^add/$', self.add_view, name=self.get_add_url_name),
            re_path(r'^edit/(d+)/$', self.edit_view, name=self.get_edit_url_name),
            re_path(r'^delete/(d+)/$', self.delete_view, name=self.get_delete_url_name),
        ]

        patterns.extend(self.extra_urls())
        return patterns

    def extra_urls(self):
        return []


class StarkSite(object):
    def __init__(self):
        self._registry = []
        self.app_name = 'stark'
        self.namespace = 'stark'

    def register(self, model_class, handler_class=None, prev=None):
        """
        :param model_class: 是models中的数据库表对应的类。
        :param handler_class: 处理请求的视图函数所在的类
        :param prev: 生成URL的前缀
        :return:
        """

        if not handler_class:
            handler_class = StarkHandler
        self._registry.append(
            {'model_class': model_class, 'handler': handler_class(self, model_class, prev), 'prev': prev})

    def get_urls(self):
        patterns = []
        for item in self._registry:
            model_class = item['model_class']
            handler = item['handler']
            prev = item['prev']
            app_name, model_name = model_class._meta.app_label, model_class._meta.model_name
            if prev:
                patterns.append(
                    re_path(r'^%s/%s/%s/' % (app_name, model_name, prev,), (handler.get_urls(), None, None)))
            else:
                patterns.append(re_path(r'^%s/%s/' % (app_name, model_name,), (handler.get_urls(), None, None)))

        return patterns

    @property
    def urls(self):
        return self.get_urls(), self.app_name, self.namespace


site = StarkSite()

三、业务处理

web/stark.py

from stark.service.core_func import site, StarkHandler, get_choice_text

from web import models


class DepartmentHandler(StarkHandler):
    list_display = ['title']


class UserInfoHandler(StarkHandler):
    list_display = [
        'name',
        get_choice_text('性别', 'gender'),
        get_choice_text('班级', 'classes'),
        'age', 'email', 'department',
        StarkHandler.display_edit,
        StarkHandler.display_delete,

    ]


site.register(models.Department, DepartmentHandler) 
site.register(models.UserInfo, UserInfoHandler)

四、引入静态文件

引入了bootstrap

stark/templates/layout.html

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Strak组件</title>
    <link rel="shortcut icon" href="{% static 'stark/imgs/luffy-study-logo.png' %} ">
    <link rel="stylesheet" href="{% static 'stark/plugins/bootstrap/css/bootstrap.css' %} "/>
    <link rel="stylesheet" href="{% static 'stark/plugins/font-awesome/css/font-awesome.css' %} "/>
    <link rel="stylesheet" href="{% static 'stark/css/commons.css' %} "/>
    <link rel="stylesheet" href="{% static 'stark/css/nav.css' %} "/>
    <style>
        body {
            margin: 0;
        }

        .no-radius {
            border-radius: 0;
        }

        .no-margin {
            margin: 0;
        }

        .pg-body > .left-menu {
            background-color: #EAEDF1;
            position: absolute;
            left: 1px;
            top: 48px;
            bottom: 0;
            width: 220px;
            border: 1px solid #EAEDF1;
            overflow: auto;
        }

        .pg-body > .right-body {
            position: absolute;
            left: 225px;
            right: 0;
            top: 48px;
            bottom: 0;
            overflow: scroll;
            border: 1px solid #ddd;
            border-top: 0;
            font-size: 13px;
            min-width: 755px;
        }

        .navbar-right {
            float: right !important;
            margin-right: -15px;
        }

        .custom-container {
            padding: 15px;
        }


    </style>

    {% block css %}{% endblock %}
</head>
<body>

<div class="pg-header">
    <div class="nav">
        <div class="logo-area left ">
            <a href="#">
                <img class="logo" src="{% static 'stark/imgs/logo.svg' %}">
                <span style="font-size: 18px;">Strak组件</span>
            </a>
        </div>

        <div class="left-menu left">
            <a class="menu-item">学生管理</a>
            <a class="menu-item">教师管理</a>
            <a class="menu-item">班级管理</a>
            <div class="menu-item">
                <span>使用说明</span>
                <i class="fa fa-caret-down" aria-hidden="true"></i>
                <div class="more-info">
                    <a href="#" class="more-item">管他什么菜单</a>
                    <a href="#" class="more-item">实在是编不了</a>
                </div>
            </div>
        </div>

        <div class="right-menu right clearfix">

            <div class="user-info right">
                <a href="#" class="avatar">
                    <img class="img-circle" src="{% static 'stark/imgs/default.png' %}">
                </a>

                <div class="more-info">
                    <a href="#" class="more-item">个人信息</a>
                    <a href="#" class="more-item">注销</a>
                </div>
            </div>

            <a class="user-menu right">
                消息
                <i class="fa fa-commenting-o" aria-hidden="true"></i>
                <span class="badge bg-success">2</span>
            </a>

            <a class="user-menu right">
                通知
                <i class="fa fa-envelope-o" aria-hidden="true"></i>
                <span class="badge bg-success">2</span>
            </a>

            <a class="user-menu right">
                任务
                <i class="fa fa-bell-o" aria-hidden="true"></i>
                <span class="badge bg-danger">4</span>
            </a>
        </div>

    </div>
</div>
<div class="pg-body">
    <div class="left-menu">
        <div class="menu-body">

        </div>
    </div>
    <div class="right-body">
        <div>

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


<script src="{% static 'stark/js/jquery-3.3.1.min.js' %} "></script>
<script src="{% static 'stark/plugins/bootstrap/js/bootstrap.js' %} "></script>

{% block js %} {% endblock %}
</body>
</html>

stark/templates/stark/data_list.html

{% extends 'layout.html' %}


{% block content %}
    <div class="custom-container">
        <table class="table table-bordered">
            <thead>
            <tr>
                {% for item in header_list %}
                    <th>{{ item }}</th>
                {% endfor %}
            </tr>
            </thead>
            <tbody>
            {% for row in body_list %}
                <tr>
                    {% for ele in row %}
                        <td>{{ ele }}</td>
                    {% endfor %}

                </tr>
            {% endfor %}

            </tbody>
        </table>
    </div>
{% endblock content %}

原文地址:https://www.cnblogs.com/lshedward/p/10566501.html