Esta es la respuesta más válida que te podemos compartir, pero estúdiala detenidamente y valora si se adapta a tu trabajo.
Solución:
Para eliminar la opción “Agregar otro”, agregue el siguiente método en la clase en línea de administración.
def has_add_permission(self, request):
return False
Del mismo modo, si desea deshabilitar “¿Eliminar?” opción, agregue el siguiente método en la clase en línea de administración.
def has_delete_permission(self, request, obj=None):
return False
Creo que esta es una solución menos complicada que la que terminaste. Funcionó para mí, de todos modos.
Básicamente, es el equivalente en línea de lo que sugirió hacer con la anulación del obtener_formulario método de ModelAdmin. Aquí anulamos get_formset en la clase en línea, saque el formulario del formset y haga exactamente lo mismo. Parece funcionar bien, al menos en 1.9, que estoy usando.
class VersionEntryInline(admin.TabularInline):
template = 'admin/edit_inline/tabular_versionentry.html'
model = VersionEntry
extra = 0
def get_formset(self, request, obj=None, **kwargs):
"""
Override the formset function in order to remove the add and change buttons beside the foreign key pull-down
menus in the inline.
"""
formset = super(VersionEntryInline, self).get_formset(request, obj, **kwargs)
form = formset.form
widget = form.base_fields['project'].widget
widget.can_add_related = False
widget.can_change_related = False
widget = form.base_fields['version'].widget
widget.can_add_related = False
widget.can_change_related = False
return formset
Después de un par de días intensos, finalmente logré encontrar la manera de lograrlo.
Un truco simple como este es más que suficiente cuando se trata de este problema dentro de las subclases de ModelAdmin (ver ClienteAdmin en mi código anterior), así que aquí está la versión de clase sin agregar capacidades para el campo “Prodotto”:
@admin.register(Cliente)
class ClienteAdmin(admin.ModelAdmin):
list_display = [
'ragione_sociale', 'forma_societaria', 'titolare', 'partita_iva', ]
list_filter = ['forma_societaria', ]
search_fields = ['ragione_sociale', ]
inlines = [RecapitoInline, SedeInline]
def get_form(self, request, obj=None, **kwargs): # Just added this override
form = super(ClienteAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['prodotto'].widget.can_add_related = False
return form
El verdadero problema surge cuando se trata de clases en línea (TabularInline, StackedInline), ya que parece que la función get_form() no se llama en absoluto, por lo que la forma anterior no funcionará.
Explicar todos mis intentos anteriores llevaría demasiado tiempo, y probablemente ni siquiera soy lo suficientemente bueno con Django para decir por qué no funcionaron. Así que vayamos directamente a la solución, que de hecho ni siquiera es tan complicada.
yo subclasificaba django.contrib.admin.widgets.RelatedFieldWidgetWrapper widget y anuló su método de representación, de modo que no agregue el ancla “agregar otro” a la salida. Se hace fácilmente comentando algunas líneas. Después de hacerlo, parcheé el RelatedFieldWidgetWrapper original con mi propia versión (django.contrib.admin.widgets.RelatedFieldWidgetWrapper = Sin agregarRelatedFieldWidgetWrapper) hizo el truco.
Claramente, para que funcionara, tuve que agregar la línea de importación en el administrador.py:
de .widgets importar NoAddingRelatedFieldWidgetWrapper
widgets.py
import django.contrib.admin.widgets
from django.utils.safestring import mark_safe
class NoAddingRelatedFieldWidgetWrapper(django.contrib.admin.widgets.RelatedFieldWidgetWrapper):
def render(self, name, value, *args, **kwargs):
from django.contrib.admin.views.main import TO_FIELD_VAR
rel_to = self.rel.to
info = (rel_to._meta.app_label, rel_to._meta.model_name)
self.widget.choices = self.choices
output = [self.widget.render(name, value, *args, **kwargs)]
'''
if self.can_add_related:
related_url = reverse('admin:%s_%s_add' % info, current_app=self.admin_site.name)
url_params = '?%s=%s' % (TO_FIELD_VAR, self.rel.get_related_field().name)
# TODO: "add_id_" is hard-coded here. This should instead use the
# correct API to determine the ID dynamically.
output.append(' '
% (related_url, url_params, name))
output.append('
'
% (static('admin/img/icon_addlink.gif'), _('Add Another')))
'''
return mark_safe(''.join(output))
# Monkeypatch
django.contrib.admin.widgets.RelatedFieldWidgetWrapper = NoAddingRelatedFieldWidgetWrapper
En aras de completar, aquí está la versión final del admin.py relacionado:
administrador.py
from django.contrib import admin
import django.contrib.admin.widgets
from django.db import models
from .models import Cliente, Prodotto, Sede
from apps.recapito.models import RecapitoCliente
from .widgets import NoAddingRelatedFieldWidgetWrapper
class SedeInline(admin.TabularInline):
model = Sede
extra = 1
def provincia(self, obj):
return obj.comune.provincia
readonly_fields = ['provincia', ]
class RecapitoInline(admin.TabularInline):
model = RecapitoCliente
extra = 1
readonly_fields = ['cliente', 'tipo', 'recapito', ]
@admin.register(Cliente)
class ClienteAdmin(admin.ModelAdmin):
list_display = [
'ragione_sociale', 'forma_societaria', 'titolare', 'partita_iva', ]
list_filter = ['forma_societaria', ]
search_fields = ['ragione_sociale', ]
inlines = [RecapitoInline, SedeInline]
def get_form(self, request, obj=None, **kwargs):
form = super(ClienteAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['prodotto'].widget.can_add_related = False
return form
Si alguien presenta una solución mejor, con gusto la aceptaré en lugar de la mía.
No se te olvide mostrar esta reseña si te ayudó.