【问题标题】:Django/SQL - Creating a table view that joins a table with an override tableDjango/SQL - 创建一个表视图,将表与覆盖表连接起来
【发布时间】:2016-07-23 22:49:24
【问题描述】:

所以我的 Django 应用程序中有以下模型结构:-

class SuperModel(models.Model):
    f1 = models.CharField()
    f2 = models.CharField()

class Model(SuperModel):
    f3 = models.CharField()

class OverrideModel(models.Model):
    fpk = models.OneToOneField(Model, primary_key=True)
    f1 = models.CharField()
    f2 = models.CharField()

基本上,在我的应用程序中,Model 表中的字段f1f2 包含我输入的用户信息。用户可以覆盖此信息,并且他/她对数据所做的任何更改都存储在OverrideModel 表中(因为我不想丢失我首先输入的信息)。把它想象成我之前创建用户配置文件,而现在我希望用户能够编辑他/她自己的配置文件而不会丢失我输入的关于他们的信息。

现在,由于我的应用程序的其余部分(视图/模板等)使用 Model 类中的字段名称,我想要创建一个获取字段 @ 的数据的 视图从覆盖表中提取 987654326@(如果存在),否则它应该从之前使用的表中提取 f1而不诉诸原始查询集。

我将描述到目前为止我所考虑的所有内容,以便我正在处理的其他一些限制变得清晰:-

  1. Model.objects.annotate(f1=Case(When(overridemodel__f1__isnull=True, then=F('f1')), default=F('overridemodel__f1'))).

    这会抛出注释别名与表中已有字段冲突的错误。

  2. Model.objects.defer('f1').extra(select={'f1': 'CASE WHEN ... END'}, tables=..., where=...).

    无法应用此方法,因为我无法找到使用 extra 应用外连接的方法。覆盖模型可能没有对应于每个模型行的行。在tables 子句中指定覆盖表会执行一个叉积运算,该运算与 where 可用于执行内连接,而不是外连接(尽管我很高兴被证明是错误的)。

    编辑:我已经意识到 select_related 可能能够解决上述问题,但是如果我在字段f1 上过滤由Model.objects.select_related('overridemodel').defer('f1').extra(select={'f1': 'CASE WHEN ... END'}, tables=..., where=...) 生成的查询集,比如qs.filter(f1='Random stuff') where 子句对于过滤器查询,使用Model.f1 字段而不是额外生成的f1 字段。所以这种做法也是徒劳的。

  3. 使用Model.objects.raw() 获取原始查询集。

    这是一个非首发,因为 Django ORM 在使用 raw 后变得无用,我需要能够过滤/排序模型对象作为应用程序的一部分。

  4. Model 类上定义方法/属性。

    同样,我将无法在此处使用相同的字段名称,这涉及在代码中寻找所有用法并进行更改。

  5. 在数据库中创建一个视图以提供我想要的内容,并创建一个非托管模型以从该视图中读取数据。

    这可能是解决我的问题的最佳解决方案,但我之前从未使用过非托管模型,我不知道该怎么做或者我可能会遇到什么陷阱。我能想到的一个问题是,我的视图必须始终与模型保持同步,但与搜索代码库并进行更改然后进行测试相比,这似乎是一个很小的代价。什么都坏了。

所以,你有它。与往常一样,任何帮助/指针将不胜感激。我试图提供尽可能少的例子;所以如果需要更多信息,我很乐意提供。

另外,我正在使用 Django 1.8 和 MySQL。

【问题讨论】:

    标签: mysql django-1.8


    【解决方案1】:

    我意识到没有简单的规范方法可以解决我的问题。即使使用选项 5(使用非托管模型创建由 ORM 操作的视图),我也会丢失原始模型上用于过滤/排序的相关查询名称。

    因此,对于遇到类似问题的其他人,我会推荐我最终采用的方法,它不是保留 OverrideModel,而是保留 OverriddenModel,它保留在用户进行更改时被覆盖的值并使用覆盖更新原始模型值,以便模型始终包含将发生过滤/查询的值

    【讨论】:

      猜你喜欢
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多