在Django模型中添加代码和方法会破坏它

use*_*014 2 python django model python-3.x

我有一个类似于以下的Django模型:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.TextField(unique=False)
Run Code Online (Sandbox Code Playgroud)

我想在models.py文件之外向一个人添加代码。所以我尝试导入它,从中继承并添加代码:例如:

class MyPerson(db.Person):
    def __init__(self, person_name):
        super(MyPerson, self).__init__(name=person_name)

    def print_person_info(self):
        print(self.name)
Run Code Online (Sandbox Code Playgroud)

我收到类似于此错误:

RuntimeError:模型类db.persons.models.Person没有声明显式的app_label,并且不在INSTALLED_APPS中的应用程序中。

尽管当然在我的settings.py文件中,但我确实将我的persons应用添加到了INSTALLED_APPS

我想我可以直接在内部添加代码,models.py但是这似乎非常不方便,因为我想在其中添加更多的代码,并且要针对多个模型添加代码。

有任何想法吗?

通常可以从模型继承吗?

Wil*_*sem 5

我想在models.py文件之外向一个人添加代码。所以我尝试导入它,从中继承并添加代码。

如果您继承 Django模型。Django将此视为额外的模型(继承)。因此,它必须在数据库侧构造一个额外的表,该表具有对“父对象”的引用,并且在某些情况下,您的额外字段会指定这些表。但是由于您可能在之外 定义了此类models.py,因此找不到app_label,因此无法执行许多任务。

通常可以从模型继承吗?

不,仅来自抽象模型,但这是这里的另一个用例。可以从非抽象模型继承,但是我仍然不建议这样做,因为它在数据库级别上会带来很多额外的麻烦。

通常,如果要添加行为,则可以直接在模型类上执行此操作,例如:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.TextField(unique=False)

    def print_person_info(self):
        print(self.name)
Run Code Online (Sandbox Code Playgroud)

或者如果行为与您已定义的行为不同,则可以使用代理模型 [Django-doc]让两个模型类在同一个数据库表上工作,每个模型类都有其行为,例如:

class MyPerson(db.Person):

    class Meta:
        proxy = True

    def print_person_info(self):
        print(self.name)
Run Code Online (Sandbox Code Playgroud)

但是代理也可能带来很多额外的“复杂性”,因此建议仅将其用作“最后的手段”。

确实建议不要修补该__init__功能,并且绝对不要更改参数(如果这样做,请使用*args,并**kwargs传递所有参数),例如:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.TextField(unique=False)

    def __init__(self, *args, **kwargs):
        # ... (do something) ...
        super(Person, self).__init__(*args, **kwargs)
        # ... (do something) ...

    def print_person_info(self):
        print(self.name)
Run Code Online (Sandbox Code Playgroud)

在Django中,许多类都假定它们可以通过调用不带参数的构造函数或通过将字段名称与值一起传递来创建模型实例。通过更改此行为,将需要重写许多类,以便您可以在表单,基于类的视图等中使用模型。