首页 > 解决方案 > 将类的属性转换为 django 模型子类

问题描述

我有一堆类,我现在正试图将它们合并到django.

例如,我有一个Base类,我的所有其他类都派生自:

class Base:
    def __init__(self, label: str = 'Base'):
        self.label = label

sublcas 的一个例子是一个Person类:

from typing import Any, Dict

class Person(Base):
    def __init__(self, name: str, attributes_to_options: Dict[str, Any], **kwargs):
        super().__init__(**kwargs)
        self.name = name
        self.attributes_to_options = attributes_to_options

我将其用作:

alex = Person(name='Alex', attributes_to_options={'age': 10, 'is_happy': True}, label='Person:Alex')

我的问题是,我如何将这样的课程纳入django它像继承一样简单models.Model吗?例如

from django.db import models

class Person(Base, models.Model):
    def __init__(self, name: str, attributes_to_options: Dict[str, Any], **kwargs):
        super().__init__(**kwargs)
        self.name = name
        self.attributes_to_options = attributes_to_options

但是,我该如何models.CharField为这两个属性指定nameattributes_to_options

感谢您在这里的任何帮助。

标签: djangopython-3.xclasssubclass

解决方案


请记住,一般来说,任何 DjangoModel子类都对应一个数据库表。从这样的类继承(“具体继承”)意味着将创建另一个数据库表,并在行之间建立一对一的链接,并且每个查询都将隐式地在数据库中执行连接。这对性能不利。但是对于行数不多的表或不经常查询的表,您可能不需要关心。

Django 提供了两种特殊情况,可以通过子Meta类中的Model类来定义。第一个是“抽象基类”,它允许您定义一堆将出现在任何派生模型中的东西。在字段的情况下,它们被“复制”到继承它们的类中,而不是拥有自己的数据库表。第二个是“代理”类,它允许您在现有数据库表的顶部放置一组新方法,这在某种程度上允许多态模型。仔细阅读 Django 文档。是个好主意。

我已经通过实验确定,人们也可以使用混合类,就像使用基于类的视图一样。换句话说,

class ExtraMethodsMixin( object): # NB must inherit from object
    # NB no model field definitions allowed here
    @property
    def something_or_other(self):
         return something_based_on_model_fields_defined_elsewhere
    #etc.

接着

class Foo( ExtraMethodsMixin, models.Model): # NB mixin goes first
    # define names and fields that the ExtraMethodsMixin uses
    #   (and anything else that a Foo needs)
    ...

我发现的一个问题是迁移确实记住了 on 的依赖,Foo因此 ExtraMethodsMixin如果您希望在以后完全删除 mixin,它是一个 PITA。但是,您可以将它存入单个pass语句而不会出现任何问题,因此这可能不是一个大问题。我的另一个担心是这种用法完全没有记录(除了作为标准 Python 之外),所以它很可能以我尚未发现的一些非常微妙的方式践踏 Django 内部。所以我肯定有点缺乏推荐这种技术。


推荐阅读