【问题标题】:How to dynamically add custom class variables without a constructor in Python如何在没有构造函数的情况下在 Python 中动态添加自定义类变量
【发布时间】:2021-05-29 03:38:33
【问题描述】:

如何在不调用构造函数的情况下将类变量动态添加到 Python 类中?在自定义 Django 石墨烯中继节点过滤器中添加自定义查询字段时,这是必需的。

在下面的示例代码中,is_controller 类变量是静态定义的。不使用类外的构造函数或代码,如何动态生成 BooleanFilter 的变量名和参数?

这是运行 GraphQL 查询所必需的,例如 allSiteEntities(is_controller: true) { ... }

class SiteEntityFilter(FilterSet):
    """Filter for SiteEntityNode that includes component filters"""

    is_controller = BooleanFilter(
        field_name=controller_component, lookup_expr="isnull", exclude=True
    )

    class Meta:
        model = SiteEntity
        fields = {
            "site": ["exact"],
            "name": ["exact", "icontains", "istartswith"],
            "modified_at": ["exact", "gt", "lt"],
        }


class SiteEntityNode(DjangoObjectType):
    class Meta:
        model = SiteEntity
        filterset_class = SiteEntityFilter
        fields = [
            "id",
            "site",
            "name",
            "controller_component",
            "created_at",
            "modified_at",
        ]
        interfaces = (relay.Node,)

【问题讨论】:

    标签: python django graphene-django


    【解决方案1】:

    通过将动态数据添加到设置中,可以为 GraphQL 查询动态添加过滤器和字段。问题是构造函数没有被调用,这就是为什么不能使用__init__()函数并且类定义后的setattr()也不起作用的原因。但是,当使用locals() 时,可以添加也被 Graphene Relay 接口代码拾取的类变量。

    自定义过滤器对于检查是否存在具有用户友好名称的反向 ForeignKey 很有用。

    # my_project/settings.py
    SITE_ENTITY_COMPONENTS = [
        "controller_component",
        "peripheral_component", 
        "hydroponic_system_component",
        "water_cycle_component",
    ]
    
    
    # my_app/graphql.py
    class SiteEntityFilter(FilterSet):
        """Filter for SiteEntityNode that includes component filters"""
    
        for component in settings.SITE_ENTITY_COMPONENTS:
            # controller_component --> is_controller
            attribute_name = f"is_{component.split('_component')[0]}"
            locals()[attribute_name] = BooleanFilter(
                field_name=component, lookup_expr="isnull", exclude=True
            )
    
        class Meta:
            model = SiteEntity
            fields = {
                "site": ["exact"],
                "name": ["exact", "icontains", "istartswith"],
                "modified_at": ["exact", "gt", "lt"],
            }
    
    class SiteEntityNode(DjangoObjectType):
        class Meta:
            model = SiteEntity
            filterset_class = SiteEntityFilter
            fields = [
                "id",
                "site",
                "name",
                "created_at",
                "modified_at",
            ].extend(settings.SITE_ENTITY_COMPONENTS)
            interfaces = (relay.Node,)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-27
      • 1970-01-01
      • 2017-09-18
      • 2013-08-12
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多