django 内置admin管理页自定义数据表格列
amdin管理页中的数据表格修改方式我这里想到了两种,在这里分享给大家。通常我们在注册模型的时候,会创建一个模型管理类,通过这个类的属性list_display来设置需要展示的字段。所以想要数据表格展示哪些列就在这个list_display变量中添加对应的数据字段名即可。下面交大家两种创建模型中没有的列并展示的方法
方法一:在模型中创建属性化方法
首先我们要知道的是,django ORM在将数据库的数据获取出来之后,是把每一条数据都实例化成对应模型类的对象的,我们看到的数据表格中的数据,实际上就是django把这些对象作为模板变量传递给django内置的表格模板,再渲染出来的。也就是说,前面提到的list_display中的元素实际上就是这些实例对象的属性,那么我直接在模型的类中添加一个方法,利用property方法属性化,不就可以直接用了么?
上代码:
# models.py
# 定义不同的设备
class MachineA(models.Model):
class Meta:
verbose_name = "A设备"
name = models.CharField("设备名称",max_length=90)
def __str__(self):
return self.name
class MachineB(models.Model):
class Meta:
verbose_name = "B设备"
name = models.CharField("设备名称",max_length=90)
def __str__(self):
return self.name
# 定义设备任务
class MachineOrder(models.Model):
class Meta:
verbose_name = "设备工作任务"
machine_type = models.CharField("设备类型",max_length=1,choices=(("A","A设备"),("B","B设备")))
machine_ID = models.IntegerField("设备ID")
order_name = models.CharField("任务名称",max_length=90)
start_time = models.DateTime("任务开始时间")
# 属性化方法
@property
def get_machine(self):
if self.machine_type == "A":
this_machine = MachineA.objects.get(id=self.machine_ID)
else:
this_machine = MachineB.objects.get(id=self.machine_ID)
return str(this_machine)
# admin.py
# 模型注册
@admin.register(MachineOrder)
class MachineOrderAdmin(admin.ModelAdmin):
# 使用模型原本就有的字段作为列
# list_display = ["machine_type","machine_ID","order_name","start_time"]
# 使用自定义的方法作为列
list_display = ["machine_type","get_machine","order_name","start_time"]
前后效果如下:
这里有一个弊端,就是数据表格显示的列名直接就是模型的方法名,而且不能像真正字段那样添加verbose_name参数来设置名称。想要设置自定义列的列名就只有使用第二种方法
第二种方法:模型注册类中添加方法
# 模型注册
@admin.register(MachineOrder)
class MachineOrderAdmin(admin.ModelAdmin):
# 使用模型原本就有的字段作为列
# list_display = ["machine_type","machine_ID","order_name","start_time"]
# 使用自定义的方法作为列
# list_display = ["machine_type","get_machine","order_name","start_time"]
# 使用当前管理类中的方法作为列
list_display = ["machine_type","get_machine_func","order_name","start_time"]
# 自定义一个方法,新的列的值就是这个方法的返回值
def get_machine_func(self,instance):
"""
参数:
instance 模型的实例对象
"""
this_type = instance.machine_type
this_machine_id = instance.machine_ID
if this_type == "A":
this_machine = MachineA.objects.get(id=this_machine_id)
else:
this_machine = MachineB.objects.get(id=this_machine_id)
return str(this_machine)
# 自定义列名
get_machine_func.short_description = "设备"
效果:
上面这种方法在admin页面展示时就是有中文列名的,列名也是我们自己定义的。换成pandas的代码可能更容易理解一些:
# apply里映射的函数就是我们定义的新列取值的方法,大致就是这个意思。最后得到的效果是一样的
df["get_machine_func"] = df.apply(lambda df:get_machine_func(instance=df),axis=1)
df.rename(columns={"get_machine_func":"设备"},inplace=True)
当然,如果有多个表使用的相同的列,获取值的逻辑也是一样的,那么也可以扩展一下这个方法抽取出来。
def get_machine_function(self,instance):
this_type = instance.machine_type
this_machine_id = instance.machine_ID
if this_type == "A":
this_machine = MachineA.objects.get(id=this_machine_id)
else:
this_machine = MachineB.objects.get(id=this_machine_id)
return str(this_machine)
# 模型注册
@admin.register(MachineOrder)
class MachineOrderAdmin(admin.ModelAdmin):
# 使用模型原本就有的字段作为列
# list_display = ["machine_type","machine_ID","order_name","start_time"]
# 使用自定义的方法作为列
# list_display = ["machine_type","get_machine","order_name","start_time"]
# 使用当前管理类中的方法作为列
list_display = ["machine_type","get_machine_func","order_name","start_time"]
# 自定义列
get_machine_func = get_machine_function
get_machine_func.short_description = "设备"