【问题标题】:Django: limiting model dataDjango:限制模型数据
【发布时间】:2011-03-20 20:48:09
【问题描述】:

我正在寻找一种方法来限制我可以通过模型获得的查询集。

假设我有以下模型(有依赖关系):

Company
 |- Section
 |   |- Employee
 |   |- Task
 |   `- more models...
 |- Customer
 |   |- Contract
 |   |- Accounts
 |   `- other great models ...
 `- some more models...

应该注意的是,我的真实模型要深得多,而且与业务无关。

使用上下文处理器,我添加了一个公司实例来请求:

def magic_view(request):
    request.company # is a instance of Company model

现在我的问题是将 Company 的子模型的访问权限限制为 company 的请求实例的最佳方法是什么?

我可以把它变成task = Task.objects.get(pk=4,section__task=task),但如果我的模型结构越来越深,这是一个不好的方法。

编辑:我可以给其他模型一个公司的外键,但这是存储冗余关系的好习惯吗? 编辑 2: 不,不是。见Is it bad to use redundant relationships?

【问题讨论】:

  • “但是如果我的模型结构越来越深,这是一个不好的方法”?你的模型是关系型的。不分层。它不需要遵循严格的层次结构。你为什么要强加一个很深的等级制度?关系数据库并不是为了这个原因而使用的。为什么要这样做?
  • 公司、部门、员工等都是模型。所以 Section 有一个 Company 的外键。我可以给其他模型一个公司的外键,但这样关系被保存了两次..
  • "我可以给其他模型一个公司的外键" 你为什么不呢?员工在不改变公司的情况下从一个部门转移到另一个部门。
  • 嗯...我想避免在database normalization 中存储冗余关系,但似乎不是。

标签: python django database-design django-models


【解决方案1】:

我通过以下方式解决了它:

首先我创建了一个 CurrentCompanyManager。

class CurrentCompanyManager(models.Manager):
    def __init__(self,field,*args,**kwargs):
        super(CurrentCompanyManager,self).__init__(*args,**kwargs)
        self.__field_name = field

    def on(self,company):
        return self.filter( **{  self.__field_name + '__id__exact':company.id } )

然后我将管理器添加到我需要它的所有模型中。

class Employee(models.Model):
    # some fields and relationships
    objects = CurrentCompanyManager("section__company")

class Accounts(models.Model):
    # some fields and relationships
    objects = CurrentCompanyManager("customer__company")

现在我可以轻松地限制视图中的模型数据了。

def magic_view(request):
    Employee.objects.on(request.company).all()

它应该是不言自明的。如果没有,那就问我。

【讨论】:

    【解决方案2】:

    将您的层次结构视为图表。让所有模型扩展 Node 类:

    class Node(models.Model):
    parent = models.ForeignKey("Node", blah blah...)
    def get_root(self):
        n = self
        while ((n = n.parent) != None): pass
        return n
    

    然后你可以像这样限制你的查询集:

    qset = Task.objects.filter(blah...)
    result = []
    for row in qset:
        if row.get_root() == request.company:
            result += row
    

    这很慢,但我只能在凌晨 2:00 赶上来

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      相关资源
      最近更新 更多