Django:如何组织这个大型模型/经理/设计混乱?

时间:2010-01-25 18:23:56

标签: django django-models django-managers

在我遇到错误的例子之前总结一下,等等:我正在尝试创建一个应用程序,我不必在所有模型中编写代码来限制当前登录帐户的选择(我'我没有使用Auth或内置功能进行帐户或登录。)

即,我想要做这样的事情:

class Ticket(models.Model):
        account = models.ForeignKey(Account)
        client = models.ForeignKey(Client)  # A client will be owned by one account.
        content = models.CharField(max_length=255)

class TicketForm(forms.ModelForm):
        class Meta:
                model = Ticket
                exclude = ('account',)  #First sign of bad design?

        def __init__(self, *args, **kwargs):
                super(OrderForm, self).__init__(*args, **kwargs)
                if self.initial.get('account'):
                        # Here's where it gets ugly IMHO. This seems almost
                        # as bad as hard coding data. It's not DRY either.
                        self.fields['client'].queryset = Client.objects.filter(account=self.initial.get('account'))

我的想法是使用以下自定义管理器创建Account(models.Model)模型,并使用所有模型的多表继承对其进行子类化。它给了我一个巨大的脑痛。我还需要在每个型号上使用account外键吗?我可以访问某个模型实例的父类帐户吗?

class TicketManager(models.Manager):
    def get_query_set(self):
        return super(TicketManager, self).get_query_set().filter(account=Account.objects.get(id=1))
        # Obviously I don't want to hard code the account like this.
        # I want to do something like this:
        # return super(ProductManager, self).get_query_set().filter(account=self.account)
        # Self being the current model that's using this manager
        # (obviously this is wrong because you're not inside a model
        # instance , but this is where the confusion comes in for me.
        # How would I do this?).

请忽略任何明显的语法错误。我在这里输入了这一切。

我有理由这样做:Django Namespace project

3 个答案:

答案 0 :(得分:7)

Django有两个密切相关的问题。

一个是行级权限,其中用户/帐户需要特定权限才能查看表中的特定行(对象),而不是具有表级权限的普通Django auth框架< / em>的

您链接到的项目是尝试实现行权限的几个项目之一。 django-granular-permissions是另一个,第三个(我最喜欢,最活跃/最常用)是django-authority

即将发布的Django 1.2将有一些钩子可以让行级权限更容易实现,author of django-authority will work on integrating his project

第二个相关问题是称为多租户数据库,它是行权限的变体。在此方案中,您可能拥有来自单个公司的多个用户,例如,所有用户都可以访问该公司的数据,但不能访问其他公司(租户)。

我认为这不是你想要的,但你可以使用一些相同的技术。请参阅how to enforce account separation in Djangomulti-tenant django applications。两者都有非常稀疏的答案,但它们是一个起点,同时也是Rails应用和this article的多租户架构。

至于您问题的更具体的答案,我认为您应该使用django-authority或编写自定义管理器并在开发期间使用record ownership screener来验证您的查询是否绕过自定义管理器。

答案 1 :(得分:2)

这里的基本问题是,即使您不使用django.contrib.auth,有关当前登录用户的信息仅在视图中可用,也从不在模型中,因为此信息绑定到请求。所以你总是要在视图中做这样的事情:

def some_view(request):
    account = get_account_by_request(request)

然后您可以使用该帐户过滤模型。你总是可以通过使用中间件或装饰器使这种方法更加优雅,但要注意它不会太棘手。您的设计可能会在意外点(在我身上发生)中断,因为与继承的管理器等有太多的遗传。保持简单和可预测。

答案 2 :(得分:1)

为了让当前用户进入您的代码,您可以使用threadlocals middleware,但没有任何关于这一点,只有一个大黑客,所以请注意:)

就个人而言,我认为将这种逻辑放入模型中是不好的,因为它们只是数据,不应该知道这些事情。