113 votes

Un meilleur widget de champ ManyToMany pour l'administration de Django

Je trouve que la valeur par défaut de l'Admin de Django est models.ManyToManyField est encombrant à utiliser. C'est le Sélection HTML et si vous avez beaucoup d'objets du modèle "autre", il n'est pas très pratique de trouver les "autres" objets que vous voulez associer à "cet" objet. Et si vous avez a d'objets du modèle "other", il semble même que le rendu de la page d'administration soit ralenti.

Je sais que je peux créer mon propre widget d'administration personnalisé et l'appliquer à mon site Web. ManyToManyFields comme je l'entends, mais existe-t-il des modèles préfabriqués que je pourrais utiliser à la place ? Dans mes rêves, j'imagine un widget HTML de saisie automatique de texte. Est-ce que c'est même pratique/possible à faire dans le cadre d'administration de Django ?

Merci.

192voto

Blair Points 6090

Essayez d'utiliser le filter_horizontal sur votre classe d'administration, par exemple :

class SomeModelAdmin(admin.ModelAdmin):
    filter_horizontal = ('users',)

Comme indiqué dans la documentation , "l'ajout d'un champ ManyToManyField à cette liste utilisera à la place une interface de "filtre" JavaScript astucieuse et discrète qui permet d'effectuer une recherche parmi les options". filter_vertical fait la même chose avec une présentation légèrement différente.

0 votes

Excellent ! C'est exactement ce que je recherche, je vais essayer.

0 votes

Cela fonctionne mais comment faire pour que ce fichier soit en lecture seule. J'essaie read only_fields = ('users',) . Mais il s'affiche sur une seule ligne séparée par une virgule. Je veux qu'il s'affiche avec un saut de ligne...

0 votes

Je craignais de devoir écrire mon propre widget, mais c'est parfait ! Merci pour cela ! ;P

7voto

mrfunyon Points 59

Vous pouvez essayer d'utiliser un identifiant brut dans l'admin. et les docs de django : http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields

Si vous cherchez quelque chose avec une fonction d'auto-complétion, vous pouvez vous inspirer de ce qui suit http://code.djangoproject.com/wiki/AutoCompleteSolutions

et enfin un exemple en ligne très simpliste :

models.py

class SomeModel(models.Model):
    users = models.ManyToMany(User)

admin.py :

class SomeModelAdmin(admin.ModelAdmin):
    raw_id_fields = ("users",)

4voto

Coderer Points 5099

Je n'ai pas encore joué avec, mais j'ai constaté que cette bibliothèque prometteuse référencée ailleurs.

Il semble faire exactement ce que je voulais. Plutôt que de charger la liste complète des objets associés (quel que soit leur nombre !) et de vous présenter un sélecteur permettant d'en sélectionner quelques-uns, comme le fait filter_horizontal il présente une boîte de recherche/filtre et utilise les appels de typeahead/autocomplete pour récupérer les résultats de manière dynamique. C'est idéal pour le cas où vous avez peut-être 5000 utilisateurs et que vous voulez en sélectionner 3 ou 4 sans attendre 5k. <option> à télécharger et à restituer.

0voto

kloddant Points 327

C'est une vieille question, mais je veux ajouter une réponse ici pour les personnes qui trouvent cela comme je l'ai fait : cette situation est exactement la raison d'être des administrateurs en ligne de Django. Plus précisément, j'utilise des lignes tabulaires avec des champs d'identification bruts pour les relations de plusieurs à plusieurs qui ont trop de choix.

https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.TabularInline

0voto

Sumit Badsara Points 463

Vous pouvez essayer d'utiliser le modèle Inline comme suit -

class ManyToManyInline(TabularInline): 
    model = MyModel.many_to_many_field_name.through 
    raw_id_fields = ("render_raw_id_using_this",) 

@register(MyModel) 
class YourAdminClass(AnyBaseClass): 
    exclude = ("many_to_many_field_name",) 
    inlines = (ManyToManyInline,) 

J'ai maintenant un autre problème, celui de trouver le nom du champ "render_raw_id_using_this".

Je suis donc passé à l'interpréteur de commandes et j'ai essayé de trouver des champs dans le modèle through comme suit -

In [1]: MyModel.many_to_many_field_name.through._meta.fields 
Out [1]: (<django.db.models.fields.AutoField: id>, <django.db.models.fields.related.ForeignKey: fieldname1>, <django.db.models.fields.related.ForeignKey: fieldname2>) 

J'ai donc remplacé render_raw_id_using_this con fieldname1

De même, vous pouvez utiliser ces noms de champs pour afficher l'identifiant brut au lieu de la liste déroulante dans le modèle en ligne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X