zoukankan      html  css  js  c++  java
  • Django

    Django 自带的 admin 组件可以自定义配置,本文实现 Xadmin 对自定义显示数据列 (list_display) 的配置。

    构建表单数据

    模板层

    从视图函数传来的数据变量是双层列表,第一层是数据库当中的每一条数据,第二层是每一条数据的各个字段值。

    类似于

    [
    	["1","King","益达出版社",12],
    	["2","Fight","西湖出版社",22],
    ]
    

    所以在模板层通过双循环来取数据。

    
    <tbody>
    	{% for new_data in new_data_list %}
    		<tr>
    			{% for data in new_data %}
    				<td>{{ data }}</td>
    			{% endfor %}
    
    		</tr>
    	{% endfor %}
    </tbody>
    

    ModelXadmin 类

    首先,设置一个列表变量 list_display 存储要显示数据表列信息。该变量不能再视图函数中设置,应该作为类的一个成员变量。该变量需要设置默认值 list_display = ["__str__", ] ,使在没有 Model 配置类的 model 中数据也能正常显示。

    显示的列字段分为两种,一种是数据表自带的,一种是个人在配置类中设置的函数。

    自带的列字段的处理

    判断 list_display 中的元素是否为 str 类型,如果是代表为自带列字段,对每个数据对象用 getattr 函数获取相应的字段值。

    # 取数据对象相应的字段
    if isinstance(field, str):
    	val = getattr(data_obj, field)
    

    配置类中函数的处理

    如果是函数,就执行该函数,添加的是该函数的返回值。

    val = field(self, data_obj)
    

    完整代码:

    # 处理表单数据的列表
    new_data_list = []
    
    for data_obj in data_list:
    	temp = []
    	for field in self.list_display:
    		# 取数据对象相应的字段
    		if isinstance(field, str):
    			val = getattr(data_obj, field)
    		else:
    			val = field(self, data_obj)
    		temp.append(val)
    
    	new_data_list.append(temp)
    

    Model 配置类

    在每个 app 下面的 Xadmin.py 文件中对数据表进行注册和配置。

    list_play 变量

    更改自己的 list_display 变量,将想显示的数据表中的字段加入进去。也可以加入函数字段。

    函数作为列字段

    当作为表单内容时,函数返回的是字符串,字符串可以是 HTML 标签。如果是 HTML 标签,则返回值需要经过 mark_safe 处理。

    如果返回的是 a 标签,其中的 href 属性所用链接应当设置为相对路径,并且此处会用到 url 反向解析的内容。

    def edit(self, obj=None):
    
    	url = reverse('change', args=(obj.pk, ))
    	return mark_safe('<a href="'+url+'">编辑</a>')
    
    

    构建表头

    模板层

    传表头的数据时使用的是一维列表,即每个列字段的名称,所以只需要一个循环。

    <thead>
    <tr>
    	{% for item in header_list %}
    		<td>{{ item }}</td>
    	{% endfor %}
    </tr>
    </thead>
    

    ModelXadmin 类

    为 list_display 的每个字段都添加相应的表头。分为三种情况,一是默认 list_display 列表,二是自定义的 list_display 列表,三是为函数列字段添加表头。

    默认 list_display

    若判断 list_display 中的元素为 __str__ 则认为是为默认的 list_display 添加表头,这里我们将 model_name 全部大写作为表头。

    if isinstance(field, str):
    	# 默认list_display
    	if field == '__str__':
    		val = self.model._meta.model_name.upper()
    

    自定义 list_display

    通过数据表类中的 meta 对象获取相应的字段值,若想显示中文,则应在数据表类中添加 verbose_name 属性。

     # 字段为数据表自带
    if isinstance(field, str):
    	# 默认list_display
    	if field == '__str__':
    		val = self.model._meta.model_name.upper()
    	else:
    		field_obj = self.model._meta.get_field(field)
    		val = field_obj.verbose_name
    

    函数列字段

    传回作为表头的确认信息,由 Model 配置类进行处理。

    # is_header判断是否在传表头时调用
    	val = field(self, is_header=True)
    

    完整添加表头代码:

    # 处理表头
    header_list = []
    
    # 为list_display的每个字段都添加相应的表头
    for field in self.list_display:
    
    	# 字段为数据表自带
    	if isinstance(field, str):
    		# 默认list_display
    		if field == '__str__':
    			val = self.model._meta.model_name.upper()
    		else:
    			field_obj = self.model._meta.get_field(field)
    			val = field_obj.verbose_name
    	# 字段为自添加函数
    	else:
    		# is_header判断是否在传表头时调用
    		val = field(self, is_header=True)
    	header_list.append(val)
    

    Model 配置类

    别的地方不需要动,在判断传回的是表头时返回自定义表头。

    # 用在传表头的时候
    if is_header is True:
    	return "操作"
    

    完整 ModelXadmin 代码:

    class ModelXadmin(object):
        # 存放要显示哪些字段的列表
        list_display = ["__str__", ]
    
        def __init__(self, model, site):
            self.model = model
            self.site = site
    
        def list_view(self, request):
            # 所有的数据
            data_list = self.model.objects.all()
            # 数据表的名称
            model_name = self.model._meta.model_name
    
            # 处理表头
            header_list = []
    
            # 为list_display的每个字段都添加相应的表头
            for field in self.list_display:
    
                # 字段为数据表自带
                if isinstance(field, str):
                    # 默认list_display
                    if field == '__str__':
                        val = self.model._meta.model_name.upper()
                    else:
                        field_obj = self.model._meta.get_field(field)
                        val = field_obj.verbose_name
                # 字段为自添加函数
                else:
                    # is_header判断是否在传表头时调用
                    val = field(self, is_header=True)
                header_list.append(val)
    
            # 处理表单数据的列表
            new_data_list = []
    
            for data_obj in data_list:
                temp = []
                for field in self.list_display:
                    # 取数据对象相应的字段
                    if isinstance(field, str):
                        val = getattr(data_obj, field)
                    else:
                        val = field(self, data_obj)
                    temp.append(val)
    
                new_data_list.append(temp)
    
            return render(request,
                          "list_view.html",
                          {
                              "data_list": data_list,
                              "model_name": model_name,
                              "new_data_list": new_data_list,
                              "header_list": header_list,
                          }
                          )
    

    完整 Model 配置类 BookConfig 代码:

    class BookConfig(ModelXadmin):
    
        def edit(self, obj=None, is_header=False):
    
            # 用在传表头的时候
            if is_header is True:
                return "操作"
    
            url = reverse('change', args=(obj.pk, ))
            return mark_safe('<a href="'+url+'">编辑</a>')
    
        def delete(self, obj=None, is_header=False):
    
            # 用在传表头的时候
            if is_header is True:
                return "操作"
    
            url = reverse('delete', args=(obj.pk,))
            return mark_safe('<a href="'+url+'">删除</a>')
    
        def check(self, obj=None, is_header=False):
    
            # 用在传表头的时候
            if is_header is True:
                return "操作"
    
            return mark_safe('<input type="checkbox">')
    
        list_display = [check, "nid", "title", "price", "publish", edit, delete]
    
    
    

    完整模板代码:

    <h3>查看{{ model_name }}数据</h3>
    
    <div class="container">
        <div class="row">
            <div class="col-md-9">
                <table class="table table-bordered table-striped">
                    <thead>
                    <tr>
                        {% for item in header_list %}
                            <td>{{ item }}</td>
                        {% endfor %}
    
                    </tr>
                    </thead>
                    <tbody>
                    {% for new_data in new_data_list %}
                        <tr>
                            {% for data in new_data %}
                                <td>{{ data }}</td>
                            {% endfor %}
    
                        </tr>
                    {% endfor %}
    
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    

    完成效果

    1540366987256

    GitHub 地址:https://github.com/protea-ban/oldboy/tree/master/s9day84/Xadmindemo

  • 相关阅读:
    jquery跨域3
    juery的跨域请求2
    jquery的跨域请求
    synchronized与Lock的区别
    springboot之启动原理解析及源码阅读
    java中Number类理解
    springboot中配置文件application.properties的理解
    restTemplate设置访问超时
    BigDecimal.setScale 处理java小数点
    NIO之FileChannel类的理解和使用
  • 原文地址:https://www.cnblogs.com/banshaohuan/p/9843861.html
Copyright © 2011-2022 走看看