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
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',) }
(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):
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
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
.
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 ?
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
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
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
.
- Copiez ce fichier html et collez à votre projet comme si
your_project\templates\admin\submit_line.html
. - 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.
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')))