Django Admin 自定义 list_filter list_display
前言:
1、在使用Django Admin的时候,有时候需要根据需求来显示用户所看到的页面,这个时候则需要自定义list_filter,通过自定的搜索栏来搜索对应的数据。
2、在使用ForeignKey或者ManyToManyField字段的时候,在默认的list_display中是无法查询到对应的数据的,简而言之,需要在list_display中自定义一个字段来获取对应的数据。
model类
下面只列举了两个model,项目和应用。当前的关系是一对多,一个项目对应多个应用,一个应用对应一个项目
> models.py
class Project(models.Model):
project_name = models.CharField(max_length=128, verbose_name="项目名称")
def __str__(self):
return self.project_name
class Meta:
db_table = 'project'
verbose_name_plural = verbose_name = "项目信息"
class AppPublish(models.Model):
# Project为要关联的类名
project_name = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name="项目名称")
branch_name = models.CharField(max_length=128, verbose_name="分支名称")
git_addr = models.CharField(max_length=128, verbose_name="GIT仓库地址")
publish_status = models.BooleanField(verbose_name="发布状态")
def __str__(self):
# 用于系统内部调用时返回的项目名称,因为是个外键查不到对应的数据,所以出此下策,通过当前的ID查到Project中的名称
return Project.objects.get(pk=self.project_name_id).project_name
class Meta:
db_table = 'app_publish'
verbose_name_plural = verbose_name = "应用发布"
list_display
在admin.py中去编写对应model的admin类
from .models import AppPublish
class AppPublishAdmin(admin.ModelAdmin):
# project为自定义的字段
list_display = (
"project",
"branch_name",
"git_addr",
"publish_status",
)
# 用于自定义字段返回的值,函数名要和自定义字段相同
def project(self, obj):
return obj.project_name
# 在页面上显示自定义字段的名称
project.short_description = "项目名称"
admin.site.register(AppPublish, AppPublishAdmin)
自定义页面返回的数据
主要通过继承get_queryset这个方法,对返回的数据进行操作。当前展示的是根据不同用户返回不同的数据, 实现的过程应该可以用ORM反向查询的,但是当时有点忘记了。
from .models import AppPublish
from .models import Project
class AppPublishAdmin(admin.ModelAdmin):
# project为自定义的字段
list_display = (
"project",
"branch_name",
"git_addr",
"publish_status",
)
# 用于自定义字段返回的值,函数名要和自定义字段相同
def project(self, obj):
return obj.project_name
# 用于自定义返回页面数据
def get_queryset(self, request):
# 继承get_queryset方法
qs = super().get_queryset(request)
# 判断当前用户是不是超级用户,如果是超级用于返回所有的值
if request.user.is_superuser:
return qs
else:
# 用于获取当前登录用户所属的项目
user_id = People.objects.get(name=request.user.username).id
project_id = Permission.objects.filter(people=user_id)
project_list = [project.project_name.id for project in project_id]
qs = AppPublish.objects.filter(project_name=project_list[0])
# 当列表中只有一个元素,则直接返回上面的qs
if len(project_list) == 1:
return qs
else:
# 当列表中有多个元素的时候,遍历所有的元素,并通过元素获取的queryset全部合并到一起
for p in project_list[1:]:
single_qs = AppPublish.objects.filter(project_name=p)
# 合并所有的qs
qs = qs | single_qs
return qs
# 在页面上显示自定义字段的名称
project.short_description = "项目名称"
admin.site.register(AppPublish, AppPublishAdmin)
list_filter
自定义过滤器,也就是搜索栏上的搜索框 lookups方法实现了搜索栏里面显示的数据 queryset方法实现点击搜索后页面返回的数据
class ProjectFilter(SimpleListFilter):
title = "项目名称"
parameter_name = 'project'
# 注意: 这个方法显示的是搜索栏里面的数据
def lookups(self, request, model_admin):
# 当登录用户为管理员返回的数据
if request.user.is_superuser:
countries = set([c.project_name for c in model_admin.model.objects.all()])
return [(c.project_name,) for c in countries]
# 其他用户登录返回的数据
else:
user_id = People.objects.get(name=request.user.username).id
qs = Permission.objects.filter(people=user_id)
project_qs = set([c.project_name for c in qs])
return [(c.project_name,) for c in project_qs]
# 这个方法是点了搜索之后,根据搜索栏里的参数来返回对应的数据
def queryset(self, request, queryset):
if request.GET.get("project"):
pn = request.GET.get("project")
project_obj = Project.objects.get(project_name=pn)
qs = project_obj.apppublish_set.all()
return qs
class AppPublishAdmin(admin.ModelAdmin):
..........
# ProjectFilter 为上面定义的类
list_filter = (ProjectFilter, "branch_name",)
admin.site.register(AppPublish, AppPublishAdmin)

浙公网安备 33010602011771号