Ausgabe
Ich verstehe, dass eine Klasse, wenn sie von einem abstrakten Django-Modell erbt, das meta-Attribut nicht erbt abstract = True
, was sinnvoll ist.
Im folgenden Beispiel wurde jedoch nichts davon geerbt, aber es Meta.abstract
ist dennoch False
, obwohl es als definiert ist True
:
from django.db import models
from django.db.models.base import ModelBase
class MyMeta(ModelBase):
def __new__(cls, name, bases, attrs, **kwargs):
"""Check that all implemented (not abstract) classes have a foo attribute"""
Class = super().__new__(cls, name, bases, attrs, **kwargs)
if not Class.Meta.abstract:
print(Class)
print('Class.Meta.ordering:', Class.Meta.ordering) # Sanity check
print('Class.Meta.abstract:', Class.Meta.abstract)
if not hasattr(Class, 'foo'):
raise NotImplementedError('Please add a foo attribute')
return Class
class MyAbstractModel(models.Model, metaclass=MyMeta):
name = models.CharField(max_length=250)
class Meta:
abstract = True
ordering = ('-name',)
Drucke:
<class 'myapp.models.base.MyAbstractModel'>
Class.Meta.ordering: -name
Class.Meta.abstract: False
Erhöhungen hinzufügen (obwohl es keine Erhöhungen geben sollte, da es sich um eine abstrakte Klasse handelt):
NotImplementedError: Please add a foo attribute
Lösung
Sie greifen auf das falsche Attribut zu, nämlich Class.Meta
. Da dieses Attribut von allen untergeordneten Klassen geerbt wird, modifiziert Django [GitHub] es tatsächlich für abstrakte Modelle:
if abstract: # Abstract base models can't be instantiated and don't appear in # the list of models for an app. We do the final setup for them a # little differently from normal models. attr_meta.abstract = False new_class.Meta = attr_meta return new_class
Das Attribut, das Django tatsächlich hinter den Kulissen verwendet (alle Attribute werden ordnungsgemäß kopiert) ist _meta
. Wenn Sie also Folgendes schreiben, erhalten Sie das erwartete Ergebnis:
if not Class._meta.abstract:
...
Beantwortet von – Abdul Aziz Barkat
Antwort geprüft von – Willingham (FixError Volunteer)