从ABC和django.db.models.Model继承都会引发元类异常 [英] Inheriting from both ABC and django.db.models.Model raises metaclass exception

查看:177
本文介绍了从ABC和django.db.models.Model继承都会引发元类异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Python 3实现Django数据模型类,这也是一个接口类。这样做的原因是,我正在为我的同事编写一个基类,并且需要他实现三种方法在所有课程中,他都是我的。我正在尝试为他提供一种简化的方式来使用我设计的系统的功能。但是,他必须重写一些方法,以便为系统提供足够的信息以执行其继承的类中的代码。

I am trying to implement a Django data model class, which is also an interface class, using Python 3. My reason for doing so is, I'm writing a base class for my colleague, and need him to implement three methods in all of the classes he derives from mine. I am trying to give him a simplified way to use the functionality of a system I've designed. But, he must override a few methods to supply the system with enough information to execute the code in his inherited classes.

我知道这是错误的,因为它会引发异常,但是我想拥有一个类似以下示例的类:

I know this is wrong, because it's throwing exceptions, but I'd like to have a class like the following example:

from django.db import models
from abc import ABC, abstractmethod

class AlgorithmTemplate(ABC, models.Model):
    name = models.CharField(max_length=32)

    @abstractmethod
    def data_subscriptions(self):
        """
        This method returns a list of topics this class will subscribe to using websockets

        NOTE: This method MUST be overriden!

        :rtype: list
        """

我知道我可以避免从 ABC 类继承,但是我想使用它是出于我在这里不会厌烦您的原因。

I understand I could avoid inheriting from the ABC class, but I'd like to use it for reasons I won't bore you with here.

在加入一个类之后,例如上面的一个,进入我的项目并运行 python manage.py makemigrations ,我得到以下错误: TypeError:metaclass冲突:派生类的元类必须是它所有基元的元类的(非严格)子类。我已经搜索了堆栈溢出,但是只找到了以下解决方案:

After including a class, like the one above, into my project and running python manage.py makemigrations I get the error: TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases. I have searched Stack Overflow, but have only find solutions like the following one:

class M_A(type): pass
class M_B(type): pass
class A(metaclass=M_A): pass
class B(metaclass=M_B): pass

class M_C(M_A, M_B): pass
class C:(A, B, metaclass=M_C): pass

I' ve阅读了以下帖子:

I've read the following posts:

使用ABC,PolymorphicModel,django-models会产生元类冲突

解决元类冲突

并且我尝试了这些解决方案的许多变体,但仍然遇到了令人恐惧的 metaclass 异常。帮我Obi-Wan Kenobi,您是我唯一的希望。 :-)

And I've tried many variations of those solutions, but I still get the dreaded metaclass exception. Help me Obi-Wan Kenobi, you're my only hope. :-)

推荐答案

我找到了一个对我有用的解决方案,所以我想将其发布在这里,以防它对其他人有所帮助。我决定不继承 ABC 类,而只是在抽象方法(派生类必须实现的方法)中引发异常。我确实在Django文档中找到了有用的信息,描述了将Django数据模型用作Abstract基类以及多表继承。


I found a solution that worked for me, so thought I would post it here in case it helps someone else. I decided to not inherit from the ABC class, and instead just raise an exception in the "abstract" methods (the ones the derived class must implement). I did find helpful information in the Django docs, describing using Django data models as an Abstract base class and also Multi-table inheritance.

引用自文档


抽象基类在要将一些常见信息放入许多其他模型时非常有用。您编写基类,并将abstract = True放在Meta类中。这样,该模型将不会用于创建任何数据库表。相反,当将其用作其他模型的基类时,会将其字段添加到子类的字段中。

Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class. This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class.

示例:

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

Student模型将具有三个字段:名称,年龄和家庭组。
CommonInfo模型不能用作普通的Django模型,因为它是抽象基类。它不会生成数据库表或
具有管理器,并且不能被实例化或直接保存。

The Student model will have three fields: name, age and home_group. The CommonInfo model cannot be used as a normal Django model, since it is an abstract base class. It does not generate a database table or have a manager, and cannot be instantiated or saved directly.

从抽象基类继承的字段可以用$覆盖。 b $ b是另一个字段或值,或者用None删除。

Fields inherited from abstract base classes can be overridden with another field or value, or be removed with None.


我对多表继承的理解是,您可以定义一个数据模型,然后将其用作第二个数据模型的基类。第二个数据模型将继承第一个模型的所有字段,以及其自己的字段。

My understanding of "multi-table inheritance" is, you can define a data model and then also use it as a base class for a second data model. The second data model will inherit all the fields from the 1st model, plus its own fields.

引自文档


Django支持的第二种模型继承是当每个$ b $层次结构中的b模型本身就是一个模型。每个模型
都对应于其自己的数据库表,可以单独查询和创建
。继承关系在子模型
及其每个父模型之间引入链接(通过自动创建的
OneToOneField)。例如:

The second type of model inheritance supported by Django is when each model in the hierarchy is a model all by itself. Each model corresponds to its own database table and can be queried and created individually. The inheritance relationship introduces links between the child model and each of its parents (via an automatically-created OneToOneField). For example:

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

所有尽管数据将存储在其他数据库表中,但餐厅(
)中也会提供位置字段。因此,这些
都是可能的:

All of the fields of Place will also be available in Restaurant, although the data will reside in a different database table. So these are both possible:

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")


这篇关于从ABC和django.db.models.Model继承都会引发元类异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆