[FIXED] Die Zusammenfassung der Django-Meta-Klasse ändert sich von True zu False

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.abstractist 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)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like