Supprimer "ajouter un autre" dans L'écran d'administration de Django

chaque fois que je édite l'objet A avec une clé étrangère à l'objet B, l'option "Ajouter un autre" est disponible à côté des choix de l'objet B. Comment puis-je supprimer cette option?

j'ai configuré un utilisateur sans droits pour ajouter un objet B. Le signe plus est toujours disponible, mais quand je clique dessus, il dit"Autorisation refusée". C'est laid.

J'utilise Django 1.0.2

23
demandé sur Jack Ha 2009-11-12 12:35:36

9 réponses

RÉPONSE DÉPRÉCIÉE

Django a depuis rendu cela possible.


avez-vous plutôt envisagé d'utiliser CSS pour ne pas afficher le bouton? C'est peut-être un peu trop hacky.

ce n'est pas testé, mais je pense...

non-addanother-bouton.css

#_addanother { display: none }

admin.py

class YourAdmin(admin.ModelAdmin):
    # ...
    class Media:
        # edit this path to wherever
        css = { 'all' : ('css/no-addanother-button.css',) }

Django Doc pour le faire -- les Médias comme une statique de la définition de

Note/modifier: la documentation dit que les fichiers seront préprogrammés avec le MEDIA_URL mais dans mon expérimentation ce n'est pas le cas. Votre kilométrage peut varier.

Si vous trouvez que c'est le cas pour vous, il ya une solution rapide pour cela...

class YourAdmin(admin.ModelAdmin):
    # ...
    class Media:
        from django.conf import settings
        media_url = getattr(settings, 'MEDIA_URL', '/media/')
        # edit this path to wherever
        css = { 'all' : (media_url+'css/no-addanother-button.css',) }
4
répondu T. Stone 2017-05-12 15:13:44

(arrêtez d'encourager cette mauvaise réponse!!!)

ERRATA : cette réponse est fondamentalement fausse, et ne répond pas à la question de L'OP. Voir ci-dessous.

(ceci ne s'applique qu'aux formulaires en ligne, pas aux champs clés étrangers comme OP demandé)

solution la plus Simple, pas de CSS hack, pas de modification de Django codebase :

ajoutez ceci à votre classe en ligne:

max_num=0

mise à JOUR

cela ne répond pas à la question de OP, et est seulement utile pour cacher le bouton" Ajouter lié " pour les formulaires en ligne, et pas les clés étrangères comme demandé.

quand j'ai écrit cette réponse, IIRC la réponse acceptée Cacher les deux, ce qui est pourquoi je me suis confus.

les liens suivants semblent fournir une solution (bien que se cacher en utilisant CSS semble le plus faisable choses à faire, en particulier si le" Ajouter un autre "boutons de FKs dans les formes en ligne):

Django 1.7 suppression du bouton Ajouter du formulaire

47
répondu pistache 2016-08-12 15:42:32

bien que la plupart des solutions mentionnées ici fonctionnent, il y a une autre façon plus propre de le faire. Il a probablement été introduit dans une version ultérieure de Django, après que les autres solutions ont été présentées. (J'utilise actuellement Django 1.7)

pour supprimer l'option" Ajouter un autre",

class ... #(Your inline class)

    def has_add_permission(self, request):
        return False

de même si vous voulez désactiver" supprimer?"option, Ajouter la méthode suivante dans la classe Inline.

    def has_delete_permission(self, request, obj=None):
        return False
15
répondu Sudipta 2015-04-27 09:21:30

N.B. travaille pour DJango 1.5.2 et peut-être plus ancien. Le can_add_related propriété est apparu Il ya environ 2 ans.

la meilleure façon que j'ai trouvée est de surcharger la fonction Get_form de votre ModelAdmin. Dans mon cas, j'ai voulu forcer l'auteur d'un post à l'utilisateur actuellement connecté. Coder ci-dessous avec de nombreux commentaires. Le plus important est le réglage de widget.can_add_related :

def get_form(self,request, obj=None, **kwargs):
    # get base form object    
    form = super(BlogPostAdmin,self).get_form(request, obj, **kwargs)

    # get the foreign key field I want to restrict
    author = form.base_fields["author"]

    # remove the green + by setting can_add_related to False on the widget
    author.widget.can_add_related = False

    # restrict queryset for field to just the current user
    author.queryset = User.objects.filter(pk=request.user.pk)

    # set the initial value of the field to current user. Redundant as there will
    # only be one option anyway.
    author.initial = request.user.pk

    # set the field's empty_label to None to remove the "------" null 
    # field from the select. 
    author.empty_label = None

    # return our now modified form.
    return form

la partie intéressante de faire les changements ici dans get_form est que author.widget est une instance de django.contrib.admin.widgets.RelatedFieldWidgetWrapper où comme si vous essayez de faire des changements dans l'une des fonctions formfield_for_xxxxx , le widget est une instance de la forme actuelle widget, dans ce cas typique de ForeignKey c'est un django.forms.widgets.Select .

12
répondu Endophage 2013-08-26 06:21:19

regardez django.contrib.admin.options.py et vérifiez la classe BaseModelAdmin , la méthode formfield_for_dbfield .

Vous verrez ceci:

# For non-raw_id fields, wrap the widget with a wrapper that adds
# extra HTML -- the "add other" interface -- to the end of the
# rendered output. formfield can be None if it came from a
# OneToOneField with parent_link=True or a M2M intermediary.
if formfield and db_field.name not in self.raw_id_fields:
    formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site)

je pense que votre meilleur pari est de créer la sous-classe de ModelAdmin (qui à son tour est une sous-classe de BaseModelAdmin ), basez votre modèle sur cette nouvelle classe, outrepassez formfield_fo_dbfield et faites en sorte qu'il ne sera pas/ou sera conditionnellement envelopper le widget dans RelatedFieldWidgetWrapper .

on pourrait soutenir que si vous avez un utilisateur qui n'a pas le droit d'ajouter des objets liés, le RelatedFieldWidgetWrapper ne devrait pas afficher le lien add? Peut-être que c'est quelque chose qui mérite d'être mentionné dans Django trac ?

5
répondu cethegeek 2009-11-12 19:15:42

basé sur la réponse de cethegeek j'ai fait ceci:

class SomeAdmin(admin.ModelAdmin):
    form = SomeForm

    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(SomeAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'some_m2m_field':
            request = kwargs.pop("request", None)
            formfield = self.formfield_for_manytomany(db_field, request, **kwargs)  # for foreignkey: .formfield_for_foreignkey
            wrapper_kwargs = {'can_add_related': False, 'can_change_related': False, 'can_delete_related': False}
            formfield.widget = admin.widgets.RelatedFieldWidgetWrapper(
                formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs
            )
        return formfield
0
répondu mirek 2018-05-14 14:01:21

j'utilise les approches suivantes pour formes et InlineForm

Django 2.0, Python 3+

formulaire

class MyModelAdmin(admin.ModelAdmin):
    #...
    def get_form(self,request, obj=None, **kwargs):

        form = super().get_form(request, obj, **kwargs)
        user = form.base_fields["user"]

        user.widget.can_add_related = False
        user.widget.can_delete_related = False
        user.widget.can_change_related = False

        return form  

Inline "Formulaire De 151940920"

class MyModelInline(admin.TabularInline):
    #...
    def get_formset(self, request, obj=None, **kwargs):

        formset = super().get_formset(request, obj, **kwargs)
        user = formset.form.base_fields['user']

        user.widget.can_add_related = False
        user.widget.can_delete_related = False
        user.widget.can_change_related = False

        return formset
0
répondu Slipstream 2018-06-20 09:52:05

J'utilise Django 2.x et je crois que j'ai trouvé la meilleure solution, au moins pour mon cas.

le fichier HTML du bouton" Enregistrer et Ajouter un autre "est sur your_python_installation\Lib\site-packages\django\contrib\admin\templates\admin\subtmit_line.html .

  1. Copiez ce fichier html et collez à votre projet comme si your_project\templates\admin\submit_line.html .
  2. ouvrir et commenter / supprimer le code de bouton comme désiré:

{#{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}#}

je sais que ce problème est déjà répondre. Mais peut-être quelqu'un dans le futur avoir un cas similaire avec moi.

0
répondu Rahmat Nazali S 2018-07-10 08:23:16

django.contrib.admin.widgets.py

(Django Install Dir)/django/contrib/admin/widgets.py: commentaire everything between Line 239 & Line 244:

 if rel_to in self.admin_site._registry: # If the related object has an admin interface:
        # TODO: "id_" is hard-coded here. This should instead use the correct
        # API to determine the ID dynamically.
        output.append(u'<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \
            (related_url, name))
        output.append(u'<img src="%simg/admin/icon_addlink.gif" width="10" height="10" alt="%s"/></a>' % (settings.ADMIN_MEDIA_PREFIX, _('Add Another')))
-1
répondu sgiob 2010-11-06 21:18:06