Die Metaklasse eines erbenden Django-Modells kann nicht zum Konfigurieren eines Felds verwendet werden, das in einem geerbten abstrakten Modell definiert ist

StackOverflow https://stackoverflow.com/questions/1361791

Frage

Ich möchte Eigenschaften aus der Meta-Klasse eines erbenden Modells verwenden, um ein Feld zu konfigurieren, das in einem abstrakten Modell weiter oben im Vererbungsbaum definiert ist:

class NamedModel(models.Model):
    class Meta:
        abstract = True
        verbose_name = 'object'

    name = models.CharField("Name",
        max_length=200,
        db_index=True,
        help_text="A meaningful name for this %s." % Meta.verbose_name)
        # see what I'm trying to do here?
    )
    ...

class OwnedModel(NamedModel):
    class Meta(NamedModel.Meta):
        verbose_name = 'owned object'

Ich möchte, dass der Hilfetext im Namensfeld von OwnedModel-Formularen lautet: „Ein aussagekräftiger Name für dieses eigene Objekt“. Aber das ist nicht der Fall:Das Wort „owned“ fehlt, was darauf hindeutet, dass der verbose_name aus NamedModel.Meta beim Einrichten des Modells verwendet wird, nicht OwnedModel.Meta.

Das ist nicht ganz das, was ich aus vererbungstechnischer Sicht erwarte:Gibt es eine Möglichkeit, das Feld zu erstellen, wobei Meta.verbose_name auf den Wert der nicht abstrakten Modellklasse verweist, nicht auf den abstrakten Wert, für den das Feld definiert wurde?

Oder bin ich dumm?

(Dies mag wie ein triviales Beispiel erscheinen, und es ist:aber es dient nur dazu, den Sinn von etwas Wichtigerem und Komplexerem zu veranschaulichen, das ich zu tun versuche)

Vielen Dank im Voraus.

War es hilfreich?

Lösung

Ich denke, das passiert, weil Meta.verbose_name verwendet wird und NamedModel.name erstellt wird, wenn die Klasse NamedModel analysiert wird.Wenn also die Klasse OwnedModel später analysiert wird, gibt es keine Möglichkeit, etwas zu ändern.

Möglicherweise können Sie später die Eigenschaft „help_text“ für OwnedModel.name festlegen, dies kann jedoch auch NamedModel.name ändern.

In ähnlichen Situationen habe ich die variablen Teile in das Klassenattribut des Modells (nicht in Meta) eingefügt und dann die Laufzeitmethoden/-eigenschaften verwendet, um die benötigten Texte zu generieren.

Andere Tipps

Warum versuchst du nicht, einen Kurs zu machen?

class BaseNamedModelMeta:
    abstract = True
    verbose_name = "your text"

Und dann erben und überschreiben Sie, was Sie wollen, so:

class OwnedModel(NamedModel):
    class Meta(BaseNamedModelMeta):
        verbose_name = 'owned object'

Tatsächlich habe ich am Ende Folgendes getan.Das Basismodell erhält eine dynamische_field_definition()-Klassenmethode, die zum Flicken der Felder verwendet werden kann, wobei das cls-Argument die richtige (erbende) Klasse ist.Das bedeutet, dass die Metaattribute von cls vom richtigen untergeordneten Element und nicht von der ursprünglichen Basis stammen.

Anschließend verbinde ich diese Methode so, dass sie über das Signal „class_prepared“ aufgerufen wird, sodass Sie wissen, dass ansonsten alles bereit ist.

class NamedModel(models.Model):
    ...
    @classmethod
    def dynamic_field_definition(cls):
        pass

def dynamic_field_definition(sender, **kwargs):
    if issubclass(sender, NamedModel):
        sender.dynamic_field_definition()
class_prepared.connect(dynamic_field_definition)

Dann werden die Feldeigenschaften, die je nach Modellklasse variieren, einfach von dieser Klassenmethode (oder wahrscheinlicher von der Methode, die in abgeleiteten Klassen überschrieben wird) neu konfiguriert.

Es ist ein etwas kniffliger Weg, den Django-Modellen ein letztes bisschen OO-Charakter zu verleihen, aber für meinen Zweck funktioniert es gut.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top