2015-03-13 32 views
8

Dies ist die Lösung kam ich in meinem models.py:Überprüfen Sie, ob Modellfeld in Django existiert

from django.db import models 

@classmethod 
def model_field_exists(cls, field): 
    try: 
     cls._meta.get_field(field) 
     return True 
    except models.FieldDoesNotExist: 
     return False 

models.Model.field_exists = model_field_exists 

Und verwenden Sie es mögen:

Post.field_exists('title') # > True or False 

Das Problem mit Fremdschlüssel kommt, mein Beitrag Modell zu einer Kategorie gehört, diese Überprüfung funktioniert:

Post.field_exists('category') # > True 

Aber dies nicht:

Post.field_exists('category_id') # > False 

Dies ist der tatsächliche Feldname in db und ich muss es so überprüfen. Wie kann ich es im Django machen?

+0

Sollten Sie in diesem Fall das Kategoriemodell selbst prüfen? –

+0

Was meinst du? Ich muss überprüfen, ob "category_id" ein gültiger Feldname für das Modell "Post" ist. – lucaswxp

+0

Wenn 'category' ein Fremdschlüssel ist und' id' zu 'category' gehört, dann hat' Post' dieses Feld nicht, also warum würdest du 'Category.field_exists ('id') nicht aufrufen' ' –

Antwort

1

Warum brauchen Sie das? Die Idee von Object Relational Mappers besteht darin, dass die Klassen die Datenbank beschreiben/definieren. Also, wenn Sie den Typ eines Modells testen wollen, sollten Sie isinstance wie so verwenden:

if isinstance(model, Post): 
    # model is a Post, Post has a publish() 
    model.publish() 
elif isinstance(model, Comment): 
    # model is a Comment, Comment has a foo() 
    model.foo() 

Ihre Modelldefinitionen definieren Ihr Schema. Es sollte keinen Grund geben, auf die Existenz eines Feldes zu testen. Wenn dies der Fall ist, folgen Sie möglicherweise nicht der besten Vorgehensweise, indem Sie Felder mit setattr zuweisen?

5

hasattr (cls, Feld) wird nicht in allen Fällen funktionieren, zum Beispiel wo Mixins verwendet werden. Ein sicherer Test:

  try: 
       model._meta.get_field(field) 
       .. do stuff here 
      except FieldDoesNotExist: 
       pass 

oder

  field = None 
      try: 
       field = model._meta.get_field(field) 
      except FieldDoesNotExist: 
       pass 

      if field: 
       .. do stuff here 
+0

Dies löst sein Problem nicht, dass category_id nicht mit get_field gefunden wird. – RemcoGerlich

1

Sie getattr verwenden können einen Standardwert zurück, wenn das Feld nicht wie .. existiert unter

getattr(table, field, False) 
2

Ihre 'category_id' Feld ist ein ausgeblendet Feld in der Terminologie von https://docs.djangoproject.com/en/1.10/ref/models/meta/. Es kann nicht von get_field abgerufen werden.

Vielleicht Schleife über alle Felder und überprüfen Sie ihre Namen; get_fields kann versteckte Felder zurück:

for field in cls._meta.get_fields(include_hidden=True): 
    if field.name == field: 
     return True 
return False 

Wenn Sie über Felder kümmern, die ihre db_column von ihrem Standard geändert haben, können Sie auch testen field.db_column (aber es ist nicht gesetzt, wenn es nicht explizit gesetzt wurde).

2

Aber dies nicht:

Post.field_exists ('category_id') #> False

Dies ist die eigentlichen Feldnamen in db und ich brauche es wie dies zu überprüfen. Wie kann ich es im Django machen?

Der Fall für alles außer dem _id Teil ist ausreichend in the other answer beantwortet. Für die Behandlung der _id Fälle benötigen Sie grundsätzlich eine spezielle Bedingung zusätzlich zu, die antworten, um mit diesen Fällen angemessen umzugehen.So etwas wie folgt aus:

if field_name.endswith('_id'): 
    try: 
     field = model._meta.get_field(field_name.strip('_id')) 
    except FieldDoesNotExist: 
     return False 
    if not f.is_relation: 
     return False 
    return True 

Die zusätzliche Überprüfung erforderlich ist, um sicherzustellen, dass das Feld minus _id eine ForeignKey zurückgibt, als zu einer anderen Art von Feld entgegengesetzt, die nur den gleichen Namen haben, geschieht, was bedeuten würde, die name_id Feld auf dem Modell ist ungültig.

Verwandte Themen