7

次の概念モデルがあります。

class GenericAbstractBase(models.Model):
    name = models.CharField(max_length=255)
    staff = generic.GenericRelation(
        "Staff",
        content_type_field="content_type",
        object_id_field="object_id",
    )

    class Meta:
        abstract = True


class GenericModelA(GenericAbstractBase):
    extra_a = models.CharField(max_length=255)


class GenericModelB(GenericAbstractBase):
    extra_b = models.CharField(max_lenth=10)


class Staff(models.Model):

    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    active = models.CharField(max_length=10, choices = ACTIVE_CHOICES)

    limit = models.Q(app_label='staff', model='genericmodela') | models.Q(app_label='staff', model='genericmodelb')
    content_type = models.ForeignKey(ContentType, limit_choices_to=limit)
    object_id = models.PositiveIntegerField()
    generic_object = generic.GenericForeignKey("content_type", "object_id")

Django v1.4 & Django v1.5 では、次のクエリは正常に機能します。

>>> ctype = ContentType.objects.get_for_model(GenericModelA)
>>> Staff.objects.filter(
        content_type=ctype,
        genericmodela__name__icontains="a"
    )
>>> [<Staff: Abbott, Kaylee>, <Staff: Adams, Kay>, ... ]

生成される SQL (sqlite) は次のようになります。

SELECT 
    "staff_staff"."id", "staff_staff"."first_name","staff_staff"."last_name",
"staff_staff"."active","staff_staff"."content_type_id" ,"staff_staff"."object_id"
FROM "staff_staff"
INNER JOIN "staff_staff" T2 ON ("staff_staff"."id" = T2."id")
INNER JOIN "staff_genericmodela" ON (T2."object_id" = "staff_genericmodela"."id")
WHERE (
"staff_genericmodela"."name" LIKE % a % ESCAPE \ '\\\'
AND "staff_staff"."content_type_id" = 11
)

ただし、Django 1.6 では、クエリは FieldError で失敗します。

FieldError: Cannot resolve keyword 'genericmodela' into field. Choices are: active, content_type, department, first_name, id, last_name, object_id, position

リリース ノートの次の記述が関連している可能性があります。

Django 1.6 には、ORM に対する多くの変更が含まれています。これらの変更は、主に次の 3 つのカテゴリに分類されます。

  1. バグの修正 (例: 一般的なリレーションの適切な結合句、クエリの結合、結合の昇格、および結合のトリミングの修正)

私の質問は、これが壊れる原因となった Django 1.6 の変更点は何ですか? extraPython でこのタイプのフィルタリングを使用または実行することに行き詰まっていますか?

4

2 に答える 2

1

文書化されていない動作のため、これは Django 1.4 でのみ機能したようです。そのため、クエリでCASEステートメントを使用して、必要なextraクエリを実行することにしました。例えば:

cta = ContentType.objects.get_for_model(models.GenericModelA)
ctb = ContentType.objects.get_for_model(models.GenericModelB)

extraq = """
CASE
    WHEN content_type_id = {0}
        THEN (SELECT extra_a from staff_genericmodela WHERE object_id = staff_genericmodela.id)
    WHEN content_type_id = {1}
        THEN (SELECT extra_b from staff_genericmodelb WHERE object_id = staff_genericmodelb.id)
 END
 """.format(cta.pk, ctb.pk)

 Staff.objects.extra(select={'genericname': extraq}).extra(where=["genericname LIKE %s", params=["%{0}%".format("foobar")])

これはこれまでのところうまく機能しており、他の同様のケースにも簡単に拡張できるはずです。

于 2014-11-05T01:48:58.387 に答える