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)
posted @ 2022-06-09 16:01  枸杞泡茶呀  阅读(1267)  评论(0)    收藏  举报