2013-06-12 1 views
2

J'ai donc des modèles comme ceci:Comment Dynamiquement Accès Les champs de clé étrangère dans Django admin

class Celebrity(models.Model): 
    #30+ fields here ... 

class HoneyBadger(models.Model): 
    name = models.CharField(max_length=10) 
    celebrity_owner = models.ForeignKey(Celebrity) 

Maintenant, je veux l'interface d'administration pour Honeybadger pour afficher le nom de la créature ainsi que les champs de propriétaire de la célébrité.

Je sais que le conseil standard est de faire quelque chose comme ceci:

class HoneyBadger(models.Model): 
    name = models.CharField(max_length=10) 
    celebrity_owner = models.ForeignKey(Celebrity) 

    def owner_birth_date(self): 
     return self.celebrity_owner.birth_date 
    #And so on for every other field in celebrity_owner 

Et puis ces méthodes dans la référence à l'administrateur.

Au lieu de cela, je veux un moyen de me sauver tout ce tapant!

Voilà ma première tentative un raccourci paresseux:

class HoneyBadger(models.Model): 
    name = models.CharField(max_length=10) 
    celebrity_owner = models.ForeignKey(Celebrity) 

    def __getattr__(self, name): 
     """Dynamically make derived fields for celebrity_owner fields so I don't have to type out""" 
     field_lookup_prefix = 'celebrity_owner_field_' 
     if name.startswith(field_lookup_prefix): 
      field_name = name[len(field_lookup_prefix):] 
      def wrapper(*args, **kwargs): 
       return getattr(self.celebrity_owner, field_name) 
      return wrapper 
     else: 
      raise AttributeError('%s not found' % name) 

qui fonctionne quand je le lance dans le shell, mais l'administrateur Django ne pas l'aimer. Je reçois cette erreur:

ImproperlyConfigured at /admin/tracker/ 

HoneyBadgerAdmin.list_display[5], 'celebrity_owner_field_birth_date' is not a callable or an attribute of 'HoneyBadgerAdmin' or found in the model 'HoneyBadger'. 

Est-ce que quelqu'un sait comment je peux faire mon travail de code avec l'administrateur ou s'il y a une autre façon de sauver taper une méthode pour chaque champ de célébrité unique? (Peut-être une sorte de patch de singe runtime?)

+0

si elle est juste pour afficher les champs que vous pouvez utiliser la méthode __unicode __() – maazza

Répondre

1

Il semble que vous vouliez étendre la classe Celebrity avec un champ de nom? Pourquoi ne pas hériter de cette classe dans la classe HoneyBadger?

class HoneyBadger(Celebrity): 
    name = models.CharField(max_length=10) 

(Vous devrez peut-être supprimer l'ancienne table Honeybadger de la première base de données pour que cela fonctionne.)

+0

Ne pas faire l'héritage d'un champ onetoone implicite liant les deux? Une célébrité peut posséder plusieurs blaireaux, ce qui ne fonctionnerait pas. – Greg

+0

Non, l'héritage fait une copie de tous les champs de la classe parente dans la classe enfant, donc HoneyBadger aura tous les champs Celebrity dans sa table. C'est ce qu'on appelle une relation «est-un», où HoneyBadger est-une célébrité. –

+0

Si vous voulez plutôt une relation "has-a", où Celebrity a un HoneyBadger, alors votre design original fonctionnera. Il suffit de laisser de côté les méthodes HoneyBadger et de les référencer avec honey_badger.celebrity_owner.birthdate. Django va chercher les clés étrangères pour vous. –

2

Il existe deux solutions de contournement possibles pour atteindre ce que vous voulez.

  1. fournir un lien vers l'objet Celebrity Honeybadger Admin:

    def celebrity_link(self): 
        return '<a href="%s">%s</a>' % (reverse('admin:appname_celebrity_change',args=(self.celebrity_owner.id,)), self.celebrity_owner.celeb_name) 
    
    celebrity_link.allow_tags = True 
    celebrity_link.short_description = u'Celebrity' 
    
    class HoneyBadgerAdmin(admin.ModelAdmin): 
        list_display = [..., celebrity_link, ...] 
    
  2. solution suivante qui est un peu complexe, mais fera exactement ce que nous voulons est: Définir votre modèle d'administration personnalisé. Fondamentalement, copiez le formulaire de modification à partir de la source django et ajoutez un code personnalisé pour afficher les informations sur Celebrity. Voir ceci documentation.

+0

Je l'ai essayé.Je ne pense pas que les inlines fonctionnent pour les clés étrangères, seulement manytomany. (Peut-être aussi pour 1to1?) – Greg

+0

@Greg Oui, j'ai réalisé que cette solution ne fonctionnera pas car les Inlines sont conçus pour suivre les relations à rebours. Donc, si vous faites exactement le contraire de la solution fournie; c'est-à-dire faire HoneyBadgerInline et CelebrityAdmin, alors vous pouvez avoir tous les HoneyBadgers liés apparaissant dans la page d'admin Celebrity. Mais c'est ce que nous voulons ici. Le meilleur substitut serait de fournir un lien vers l'objet Celebrity. Je vais modifier la solution pour le montrer. – Sudipta

Questions connexes