简体   繁体   English

Django 管理员列表过滤器使用 model 属性

[英]Django admin list filter using a model property

I have a model such as below:我有一个 model,如下所示:

class Order(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    number = models.CharField(max_length=36, blank=True, null=True)
    external_number = models.CharField(default=None, blank=True, null=True, max_length=250)

    @property
    def is_external(self) -> bool:
        return self.external_number is not None

And I register my model like below:我注册了我的 model,如下所示:

@admin.register(Order)
class OrderAdmin(ReadOnlyIDAdminClass):
    list_filter = ["number", "is_external"]
    list_display = ["id", "is_external"]

But since is_external is not a db field, I get the following error:但由于is_external不是 db 字段,我收到以下错误:

(admin.E116) The value of 'list_filter[1]' refers to 'is_external', which does not refer to a Field

I have tried something like creating a custom filter:我尝试过创建自定义过滤器之类的方法:

class IsExternal(admin.FieldListFilter):

    # Human-readable title which will be displayed in the
    # right admin sidebar just above the filter options.
    title = 'is external'

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'is_external'

    def lookups(self, request, model_admin):
        return (
            ('True', True), 
            ('False', False)
        )

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(external_number__isnull=False)
        return queryset.filter(external_number__isnull=True)

and then update my Admin:然后更新我的管理员:

@admin.register(Order)
class OrderAdmin(ReadOnlyIDAdminClass):
    list_filter = ["number", ("is_external", IsExternal)]
    list_display = ["id", "is_external"]

But it raises:但它提出了:

Order has no field named 'is_external' which I think makes sense, but is there anyway to do this? Order has no field named 'is_external' ,我认为这是有道理的,但有没有办法做到这一点? I feel like I am messing on something.我觉得我在搞砸什么。

I think after hours of trying to fix this, only now I found a working solution.我认为经过数小时的尝试解决此问题,直到现在我才找到了可行的解决方案。 We make use of the custom filter above, but we use it directly such as:我们使用了上面的自定义过滤器,但我们直接使用它,例如:

@admin.register(Order)
class OrderAdmin(ReadOnlyIDAdminClass):
    list_filter = ["number",  IsExternal]
    list_display = ["id", "is_external"]

This should work now;现在应该可以了; also please notice that in self.value() of our filter queryset, it is returning a string, so we should cast/ parse our values accordingly, in my filter above, I will be getting the values True or False as string.还请注意,在我们的过滤器查询集的self.value()中,它返回一个字符串,所以我们应该相应地转换/解析我们的值,在我上面的过滤器中,我将把值True or False作为字符串。

Edit: I have updated my custom filter to function like Django's, where we make use of values 1 and 0 for True and False .编辑:我已经将我的自定义过滤器更新为 function ,就像 Django 的一样,我们将值10用于TrueFalse

class IsExternal(SimpleListFilter):

    # Human-readable title which will be displayed in the
    # right admin sidebar just above the filter options.
    title = 'is external'

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'is_external'

    def lookups(self, request, model_admin):
        return (
            (1, 'yes'), 
            (0, 'no')
        )

    def queryset(self, request, queryset):
        if self.value() == "1":
            return queryset.filter(external_number__isnull=False)
        elif self.value() == "0":
            return queryset.filter(external_number__isnull=True)
        return queryset

Please notice that this is now using same logic defined in the model property (but not the property itself) but on the database level.请注意,这现在使用在 model 属性(但不是属性本身)中定义的相同逻辑,但在数据库级别。 If there is any way to make use directly of properties, I would love if you could share!如果有任何方法可以直接使用属性,如果你能分享,我会很高兴!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM