2010-05-11 5 views
5

J'ai une application utilisant raw_id sur ForeignKeyField et ManyToManyField. L'administrateur affiche la valeur de la clé étrangère à droite de la zone d'édition.Comment afficher la valeur raw_id d'une relation ManyToMany dans l'admin Django?

Malheureusement, cela ne fonctionne pas avec ManyToMany. J'ai vérifié le code et je pense que c'est le comportement normal. Cependant, j'aimerais savoir si quelqu'un a un conseil facile pour changer ce comportement?

Merci à l'avance

Mise à jour: J'ai essayé de sous-classe le ManyToManyRawIdWidget mais je ne sais pas comment dire que les raw_id_fields devraient utiliser mon widget personnalisé. formfield_overrides ne semble pas fonctionner avec les champs raw_id

Répondre

8

Enfin, je réussis à le faire fonctionner.

from django.contrib.admin.widgets import ManyToManyRawIdWidget 

class VerboseManyToManyRawIdWidget(ManyToManyRawIdWidget): 
    def __init__(self, rel, attrs=None): 
     super(VerboseManyToManyRawIdWidget, self).__init__(rel, attrs) 

    def label_for_value(self, value): 
     values = value.split(',') 
     str_values = [] 
     key = self.rel.get_related_field().name 
     for v in values: 
      try: 
       obj = self.rel.to._default_manager.using(self.db).get(**{key: v}) 
       str_values += [escape(u'%s' % obj)] 
      except self.rel.to.DoesNotExist: 
       str_values += [u'???'] 
     return u'&nbsp;<strong>%s</strong>' % (u',&nbsp;'.join(str_values)) 


class MyAdmin(admin.ModelAdmin): 
    def formfield_for_dbfield(self, db_field, **kwargs): 
     if db_field.name in ('foo', 'bar'): 
      try: 
       del kwargs['request'] 
      except KeyError: 
       pass 
      kwargs['widget'] = VerboseManyToManyRawIdWidget(db_field.rel) 
      return db_field.formfield(**kwargs) 
     return super(MyAdmin,self).formfield_for_dbfield(db_field,**kwargs) 

Malheureusement, j'ai passé une prime pour rien ;-)

MISE À JOUR: J'ai créé un extrait de django pour cela: http://djangosnippets.org/snippets/2108/

0

Cela fonctionne pour Django 1.11

from django.contrib.admin.sites import site 
from django.contrib.admin.widgets import ManyToManyRawIdWidget 
from django.core.urlresolvers import reverse, NoReverseMatch 
from django.utils.safestring import mark_safe 


class VerboseManyToManyRawIdWidget(ManyToManyRawIdWidget): 

    def label_and_url_for_value(self, value): 
     result = [] 
     for v in value: 
      key = self.rel.get_related_field().name 
      try: 
       obj = self.rel.model._default_manager.using(self.db).get(**{key: v}) 
      except (ValueError, self.rel.model.DoesNotExist): 
       return '', '' 

      try: 
       url = reverse(
        '{}:{}_{}_change'.format(self.admin_site.name, obj._meta.app_label, 
              obj._meta.object_name.lower()), 
        args=(obj.pk,)) 
      except NoReverseMatch: 
       url = '' # Admin not registered for target model. 

      result.append('<strong><a href="{}">{}</a></strong>'.format(url, str(obj))) 

     return mark_safe('; '.join(result)), '' 


class VerboseRawIdManyToManyAdminMixin: 
    def formfield_for_dbfield(self, db_field, **kwargs): 
     if db_field.name in self.raw_id_fields: 
      kwargs.pop('request', None) 
      if db_field.rel.__class__.__name__ == 'ManyToManyRel': 
       kwargs['widget'] = VerboseManyToManyRawIdWidget(db_field.rel, site) 
      return db_field.formfield(**kwargs) 
     return super().formfield_for_dbfield(db_field, **kwargs) 

Il y a aussi l'application Django à cet effetdjango-salmonella

Questions connexes