DJANGO与抽象基类投掷错误后添加后的规则

发布于 2025-02-06 17:51:24 字数 2474 浏览 0 评论 0原文

django-rules添加到我的django项目中,我遇到以下问题:我想在我的抽象基类中添加默认权限,并在需要时覆盖它们。在基类和继承类的示例下:

class BaseModel(RulesModelBaseMixin):
    company_id = models.ForeignKey('company.Company', on_delete=models.CASCADE)
    created_by = models.ForeignKey(
        'user.User', on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        abstract = True
        rules_permissions = {
            "can_create": can_create_in_company | is_superuser,
            "can_view": can_view_in_company | is_author | is_superuser
        }

class Ticket(RulesModelMixin, BaseModel, metaclass=RulesModelBase):
    name = models.CharField(max_length=512, null=True, blank=True)

添加此抽象基类后,有一个看似无关的错误消息:

Traceback (most recent call last):
    File "REPO_PATH/.venv/lib/python3.10/site-packages/django/utils/module_loading.py", line 30, in import_string
    return cached_import(module_path, class_name)
    File "REPO_PATH/.venv/lib/python3.10/site-packages/django/utils/module_loading.py", line 15, in cached_import
    import_module(module_path)
    File "/opt/homebrew/Cellar/[email protected]/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
    File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 883, in exec_module
    File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
    File "REPO_PATH/app/api/pagination.py", line 10, in <module>
    from ticket.models import Ticket, TicketStatus, TicketType
    File "REPO_PATH/app/ticket/models.py", line 106, in <module>
    class Ticket(RulesModelMixin, BaseModel, metaclass=RulesModelBase):
    File "REPO_PATH/.venv/lib/python3.10/site-packages/rules/contrib/models.py", line 36, in __new__
    new_class._meta.rules_permissions = perms
AttributeError: type object 'Ticket' has no attribute '_meta'. Did you mean: 'Meta'?

它似乎与以后的自定义分页有关,但我不认为这是问题的原因,就像以前起作用一样。甚至在

Adding django-rules to my Django project I am encountering the following issue: I want to add default permissions to my abstract base class and overwrite them, if needed. Below an example of a base class and the inheriting class:

class BaseModel(RulesModelBaseMixin):
    company_id = models.ForeignKey('company.Company', on_delete=models.CASCADE)
    created_by = models.ForeignKey(
        'user.User', on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        abstract = True
        rules_permissions = {
            "can_create": can_create_in_company | is_superuser,
            "can_view": can_view_in_company | is_author | is_superuser
        }

class Ticket(RulesModelMixin, BaseModel, metaclass=RulesModelBase):
    name = models.CharField(max_length=512, null=True, blank=True)

After adding this abstract base class, there is this seemingly unrelated error message:

Traceback (most recent call last):
    File "REPO_PATH/.venv/lib/python3.10/site-packages/django/utils/module_loading.py", line 30, in import_string
    return cached_import(module_path, class_name)
    File "REPO_PATH/.venv/lib/python3.10/site-packages/django/utils/module_loading.py", line 15, in cached_import
    import_module(module_path)
    File "/opt/homebrew/Cellar/[email protected]/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
    File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 883, in exec_module
    File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
    File "REPO_PATH/app/api/pagination.py", line 10, in <module>
    from ticket.models import Ticket, TicketStatus, TicketType
    File "REPO_PATH/app/ticket/models.py", line 106, in <module>
    class Ticket(RulesModelMixin, BaseModel, metaclass=RulesModelBase):
    File "REPO_PATH/.venv/lib/python3.10/site-packages/rules/contrib/models.py", line 36, in __new__
    new_class._meta.rules_permissions = perms
AttributeError: type object 'Ticket' has no attribute '_meta'. Did you mean: 'Meta'?

It seems to have something to do with the custom pagination later on, but I don't think that this is the cause of the problem, as this worked before. The base class case is even mentioned in the docs, but it doesn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娜些时光,永不杰束 2025-02-13 17:51:24
  1. basemodel不应子类rulesmodelbasemixin,该用作metaclassbasemodel不需要metaclass = rulesmodelbasemixin,因为ticket has metaClass = pruremodelbaseprure modelbase子类RulesModelBasemixin
  2. basemodel应该子类模型,因为它定义了要继承的模型字段。 模型还提供了您可能期望的许多功能。
  3. Ticket需要为具有Metaclass = ModelBase(例如model)的类子类次级类在问题中显示)。由于票证子类basemodel,我们将更改为子类model ,它无需明确的子类Model> Model
  4. django-rules不支持Abstract Model Meta中的定义rules_permissions。您可以实现preprocess_rules_permissions类方法,以在子类上动态定义该方法。您还需要将baseModel放在pruremodelmixin ticket 中以覆盖该类方法。
# class BaseModel(RulesModelBaseMixin):
class BaseModel(Model):
    ...

    class Meta:
        abstract = True
        # rules_permissions = {
        #     "can_create": can_create_in_company | is_superuser,
        #     "can_view": can_view_in_company | is_author | is_superuser
        # }

    @classmethod
    def preprocess_rules_permissions(cls, perms):
        perms.update({
            "can_create": can_create_in_company | is_superuser,
            "can_view": can_view_in_company | is_author | is_superuser,
        })


# class Ticket(RulesModelMixin, BaseModel, metaclass=RulesModelBase):
class Ticket(BaseModel, RulesModelMixin, metaclass=RulesModelBase):
    ...

您可以通过制作basemodel子类rulesmodel

class BaseModel(RulesModel):
    ...

    class Meta:
        abstract = True

    @classmethod
    def preprocess_rules_permissions(cls, perms):
        perms.update({
            "can_create": can_create_in_company | is_superuser,
            "can_view": can_view_in_company | is_author | is_superuser,
        })


class Ticket(BaseModel):
    ...
  1. BaseModel should not subclass RulesModelBaseMixin, which is used as a metaclass. BaseModel doesn't need metaclass=RulesModelBaseMixin though, since Ticket has metaclass=RulesModelBase, and RulesModelBase subclasses RulesModelBaseMixin.
  2. BaseModel should subclass Model since it defines model fields meant to be inherited. Model also provides a lot of functionality that you might expect.
  3. Ticket needs to subclass a class that has metaclass=ModelBase (e.g. Model) to get _meta set (the error shown in the question). Since Ticket subclasses BaseModel, which we will change to subclass Model, it does not need to explicitly subclass Model again.
  4. django-rules does not support defining rules_permissions in abstract model Meta. You can implement preprocess_rules_permissions class method to dynamically define that on subclasses. You also need to put BaseModel before RulesModelMixin in Ticket to override that class method.
# class BaseModel(RulesModelBaseMixin):
class BaseModel(Model):
    ...

    class Meta:
        abstract = True
        # rules_permissions = {
        #     "can_create": can_create_in_company | is_superuser,
        #     "can_view": can_view_in_company | is_author | is_superuser
        # }

    @classmethod
    def preprocess_rules_permissions(cls, perms):
        perms.update({
            "can_create": can_create_in_company | is_superuser,
            "can_view": can_view_in_company | is_author | is_superuser,
        })


# class Ticket(RulesModelMixin, BaseModel, metaclass=RulesModelBase):
class Ticket(BaseModel, RulesModelMixin, metaclass=RulesModelBase):
    ...

You can simplify all that by making BaseModel subclass RulesModel:

class BaseModel(RulesModel):
    ...

    class Meta:
        abstract = True

    @classmethod
    def preprocess_rules_permissions(cls, perms):
        perms.update({
            "can_create": can_create_in_company | is_superuser,
            "can_view": can_view_in_company | is_author | is_superuser,
        })


class Ticket(BaseModel):
    ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文