2011-04-15 2 views
6

Tout d'abord un peu d'arrière-plan:Remplacer les URL d'administration Django pour un modèle spécifique?

J'ai un modèle Event qui a divers event_type s. Je veux casser un de ces types d'événements, 'Film', dans son propre admin. J'ai la fonctionnalité de base en place: un modèle de proxy héritant de Event, nommé Film, un gestionnaire personnalisé pour ce modèle de proxy qui le filtre uniquement pour les types d'événements «film», et son propre ModelAdmin.

Le problème est avec l'inverse. J'ai maintenant besoin de filtrer les films de l'administrateur principal Event. Je ne veux pas modifier le modèle Event ou son gestionnaire par défaut, car l'impact serait trop répandu. Donc, j'ai essayé de créer un autre modèle de proxy, EventAdminProxy, dans le seul but de fournir une liste filtrée des événements dans l'admin. Je puis enregistrer ce modèle, au lieu de Event, avec le ModelAdmin existant.

Cela fonctionne évidemment, mais il a le malheureux effet secondaire de modifier les URL dans l'admin. Au lieu que la liste des modifications se trouve dans "/ admin/event/event /", elle est maintenant dans "/ admin/event/eventadminproxy /". Ce que j'essaye de faire est de garder cette configuration, mais garde également l'ancienne URL. J'ai essayé de surcharger la méthode get_urls de ModelAdmin, mais d'après ce que je peux dire, vous ne pouvez pas contrôler l'URL complète là, seulement ce qui vient après la partie "/ app_label/model_class /". J'ai pensé à l'ignorer dans l'urls.py principal, mais je n'arrive pas à trouver une vue acceptable pour l'attacher. Les vues réelles sont uniquement disponibles sur l'objet ModelAdmin instancié, pas la classe elle-même.

Des idées sur la façon dont remplacer l'URL utilisée dans l'admin?

Répondre

6

Vous pouvez remplacer le queryset-method de votre EventModelAdmin et filtrer le jeu de requête afin d'exclure les événements film.

Quelque chose de semblable à ceci:

class EventAdmin(admin.ModelAdmin): 

    def queryset(self, request): 
     qs = super(EventAdmin, self).queryset(request) 
     return qs.exclude(event_type='film') 
+0

Ok. Ajoutez-le à la catégorie "Je suis un idiot".Je ne peux pas croire que je n'y ai pas pensé. Merci! –

8

regardant la source Django, les URL d'administration sont construites en deux endroits, dans les cas ModelAdmin, et dans les cas AdminSite.

La pièce que vous souhaitez modifier est créée dans l'instance AdminSite (django.contrib.admin.sites.AdminSite), vous pouvez la sous-classer et remplacer la méthode get_urls. Si vous regardez la deuxième moitié de la méthode que vous verrez ceci:

# Add in each model's views. 
    for model, model_admin in self._registry.iteritems(): 
     urlpatterns += patterns('', 
      url(r'^%s/%s/' % (model._meta.app_label, model._meta.module_name), 
       include(model_admin.urls)) 
     ) 

Là, il ajoute le ._meta.module_name de modèle qui est juste le nom du modèle en minuscules (django.db.models.options.Options.contribute_to_class).

Un moyen facile est de passer outre la méthode get_urls du site et ajouter un dict ou cas particulier pour le modèle Proxy il utilise une autre url au lieu de model._meta.module_name, quelque chose le long des lignes:

classe MyAdminSite (AdminSite):

module_name_dict = { 
    EventAdminProxy: 'myfunkymodulename' 
} 

def get_urls(self): 
    base_patterns = super(MyAdminSite, self).get_urls() 
    my_patterns = patterns('',) 

    for model, model_admin in self._registry.iteritems(): 
     if model in self.module_name_dict: 
      module_name = self.module_name_dict[model] 
      my_patterns += patterns('', 
       url(r'^%s/%s/' % (model._meta.app_label, module_name), 
        include(model_admin.urls)) 
      ) 

    return my_patterns + base_patterns 
Questions connexes