父对象的子对象

时间:2017-04-27 20:21:54

标签: python django

这是交易,我有三个班级:

class Interaction(models.Model):

    user = models.ForeignKey(
       User,
       verbose_name="Usuário"
    )

    created = models.DateTimeField(
       verbose_name="Criado em",
       auto_now_add=True
    )

    value = models.FloatField(
       verbose_name="Valor",
       default=0
    )

class PostInteraction(Interaction):
     #some atributes
class NewsInteraction(Interaction):
     #some atributes

我提出查询:

interactions = Interaction.objects.all()
for interaction in interactions:
     #???

如何在不进行查询的情况下通过父类判断哪个子类?

2 个答案:

答案 0 :(得分:1)

Interaction个对象将具有postinteractionnewsinteraction属性,该属性将指向正确类型的对象。

或者,您可以使用django-model-utils及其InheritanceManager等库来执行此操作:

from model_utils.managers import InheritanceManager

class Interaction(models.Model):
    ...
    objects = InheritanceManager()
    ...

Interaction.objects.all().select_subclasses()

这将为您提供正确的对象类型。

答案 1 :(得分:0)

您询问如何在不进行查询的情况下告诉Interaction对象的子类。简短的回答是,你做不到。当您访问Interaction.objects.all()时,它只查询myschema_interaction表,并且该表不会告诉您myschema_postinteraction表或myschema_newsinteraction表中是否存在匹配记录。

要查看子类是什么,您可以查看postinteractionnewsinteraction属性。要进行一次查询而不是为每条记录单独进行查询,可以使用prefetch_related() method

这是一个可运行的示例,显示了这两种技术。

# Tested with Django 1.9.2
import logging
import sys

import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.db.models.base import ModelBase

NAME = 'udjango'


def main():
    setup()

    class Interaction(models.Model):
        # user = models.ForeignKey(
        #     User,
        #     verbose_name="Usuario"
        # )

        created = models.DateTimeField(
            verbose_name="Criado em",
            auto_now_add=True
        )

        value = models.FloatField(
            verbose_name="Valor",
            default=0
        )

    class PostInteraction(Interaction):
        body = models.CharField(max_length=1000)

    class NewsInteraction(Interaction):
        headline = models.CharField(max_length=30)

    syncdb(Interaction)
    syncdb(PostInteraction)
    syncdb(NewsInteraction)

    PostInteraction.objects.create(body="I ate breakfast.", value=1)
    NewsInteraction.objects.create(headline="No lunch today!", value=2)
    PostInteraction.objects.create(body="I ate dinner.", value=3)

    logging.info('All interaction values: {}'.format(
        [interaction.value
         for interaction in Interaction.objects.all()]))
    logging.info('Interaction values and posts: {}'.format(
        [(interaction.value, hasattr(interaction, 'postinteraction'))
         for interaction in Interaction.objects.all()]))
    logging.info('Interaction values and posts: {}'.format(
        [(interaction.value, hasattr(interaction, 'postinteraction'))
         for interaction in Interaction.objects.prefetch_related('postinteraction')]))


def setup():
    DB_FILE = NAME + '.db'
    with open(DB_FILE, 'w'):
        pass  # wipe the database
    settings.configure(
        DEBUG=True,
        DATABASES={
            DEFAULT_DB_ALIAS: {
                'ENGINE': 'django.db.backends.sqlite3',
                'NAME': DB_FILE}},
        LOGGING={'version': 1,
                 'disable_existing_loggers': False,
                 'formatters': {
                    'debug': {
                        'format': '%(asctime)s[%(levelname)s]'
                                  '%(name)s.%(funcName)s(): %(message)s',
                        'datefmt': '%Y-%m-%d %H:%M:%S'}},
                 'handlers': {
                    'console': {
                        'level': 'DEBUG',
                        'class': 'logging.StreamHandler',
                        'formatter': 'debug'}},
                 'root': {
                    'handlers': ['console'],
                    'level': 'INFO'},
                 'loggers': {
                    "django.db": {"level": "DEBUG"}}})
    app_config = AppConfig(NAME, sys.modules['__main__'])
    apps.populate([app_config])
    django.setup()
    original_new_func = ModelBase.__new__

    @staticmethod
    def patched_new(cls, name, bases, attrs):
        if 'Meta' not in attrs:
            class Meta:
                app_label = NAME
            attrs['Meta'] = Meta
        return original_new_func(cls, name, bases, attrs)
    ModelBase.__new__ = patched_new


def syncdb(model):
    """ Standard syncdb expects models to be in reliable locations.

    Based on https://github.com/django/django/blob/1.9.3
    /django/core/management/commands/migrate.py#L285
    """
    connection = connections[DEFAULT_DB_ALIAS]
    with connection.schema_editor() as editor:
        editor.create_model(model)

main()

这是包含执行的SQL的日志输出:

2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.schema.execute(): CREATE TABLE "udjango_interaction" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "value" real NOT NULL); (params None)
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) CREATE TABLE "udjango_interaction" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "value" real NOT NULL); args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.schema.execute(): CREATE TABLE "udjango_postinteraction" ("interaction_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "udjango_interaction" ("id"), "body" varchar(1000) NOT NULL); (params None)
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) CREATE TABLE "udjango_postinteraction" ("interaction_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "udjango_interaction" ("id"), "body" varchar(1000) NOT NULL); args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.schema.execute(): CREATE TABLE "udjango_newsinteraction" ("interaction_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "udjango_interaction" ("id"), "headline" varchar(30) NOT NULL); (params None)
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) CREATE TABLE "udjango_newsinteraction" ("interaction_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "udjango_interaction" ("id"), "headline" varchar(30) NOT NULL); args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_interaction" ("created", "value") VALUES ('2017-04-27 15:02:20.729660', 1.0); args=['2017-04-27 15:02:20.729660', 1.0]
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_postinteraction" ("interaction_ptr_id", "body") SELECT 1, 'I ate breakfast.'; args=(1, 'I ate breakfast.')
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_interaction" ("created", "value") VALUES ('2017-04-27 15:02:20.754687', 2.0); args=['2017-04-27 15:02:20.754687', 2.0]
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_newsinteraction" ("interaction_ptr_id", "headline") SELECT 2, 'No lunch today!'; args=(2, 'No lunch today!')
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_interaction" ("created", "value") VALUES ('2017-04-27 15:02:20.778166', 3.0); args=['2017-04-27 15:02:20.778166', 3.0]
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_postinteraction" ("interaction_ptr_id", "body") SELECT 3, 'I ate dinner.'; args=(3, 'I ate dinner.')
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value" FROM "udjango_interaction"; args=()
2017-04-27 15:02:20[INFO]root.main(): All interaction values: [1.0, 2.0, 3.0]
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value" FROM "udjango_interaction"; args=()
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value", "udjango_postinteraction"."interaction_ptr_id", "udjango_postinteraction"."body" FROM "udjango_postinteraction" INNER JOIN "udjango_interaction" ON ("udjango_postinteraction"."interaction_ptr_id" = "udjango_interaction"."id") WHERE "udjango_postinteraction"."interaction_ptr_id" = 1; args=(1,)
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value", "udjango_postinteraction"."interaction_ptr_id", "udjango_postinteraction"."body" FROM "udjango_postinteraction" INNER JOIN "udjango_interaction" ON ("udjango_postinteraction"."interaction_ptr_id" = "udjango_interaction"."id") WHERE "udjango_postinteraction"."interaction_ptr_id" = 2; args=(2,)
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value", "udjango_postinteraction"."interaction_ptr_id", "udjango_postinteraction"."body" FROM "udjango_postinteraction" INNER JOIN "udjango_interaction" ON ("udjango_postinteraction"."interaction_ptr_id" = "udjango_interaction"."id") WHERE "udjango_postinteraction"."interaction_ptr_id" = 3; args=(3,)
2017-04-27 15:02:20[INFO]root.main(): Interaction values and posts: [(1.0, True), (2.0, False), (3.0, True)]
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value" FROM "udjango_interaction"; args=()
2017-04-27 15:02:20[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_interaction"."id", "udjango_interaction"."created", "udjango_interaction"."value", "udjango_postinteraction"."interaction_ptr_id", "udjango_postinteraction"."body" FROM "udjango_postinteraction" INNER JOIN "udjango_interaction" ON ("udjango_postinteraction"."interaction_ptr_id" = "udjango_interaction"."id") WHERE "udjango_postinteraction"."interaction_ptr_id" IN (1, 2, 3); args=(1, 2, 3)
2017-04-27 15:02:20[INFO]root.main(): Interaction values and posts: [(1.0, True), (2.0, False), (3.0, True)]