【问题标题】:Converting attributes of class to a django models subclass将类的属性转换为 django 模型子类
【发布时间】:2019-12-13 20:27:20
【问题描述】:

我现在正在尝试将一堆类合并到 django 中。

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

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

子类的一个例子是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

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

感谢您的帮助。

【问题讨论】:

  • 您是否尝试过在 Person 类范围内声明 name = models.CharField(...) 等?重要的是模型字段必须在继承自 models.Model 的类中声明。
  • 你可以有一个abstract base model 来实现一些字段,比如“label”
  • 我不知道你为什么要为 attributes_to_option 属性使用 CharField,因为那是一个字典。如果确实需要,则必须在保存之前将其转换为字符串。如果你使用的是 postgresql,你应该考虑使用 JSONField 而不是 CharField。
  • 将字典作为参数传递几乎总是一个坏主意......字典是键/值存储而不是移动命名空间
  • @alex_lewis 将字典作为对象/命名空间传递的问题是,当您或其他任何人来调试您的代码时,您只会看到传入函数的字典,不知道是什么在其中,然后您必须在堆栈中搜寻,也许可以找到该键设置的位置或未设置的位置,我去过那里,但这并不有趣。函数的显式参数可能会稍有限制,但可以节省大量调试工作

标签: django python-3.x class subclass


【解决方案1】:

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

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

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

【讨论】:

  • s/plugin class/mixin class/g
猜你喜欢
  • 2012-05-25
  • 2014-01-30
  • 2023-02-11
  • 2012-04-14
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
相关资源
最近更新 更多