Administrador de Django: deshabilite la acción 'Agregar' para un modelo específico

147

Tengo un sitio de django con muchos modelos y formularios. Tengo muchos formularios y conjuntos de formularios personalizados y conjuntos de formularios en línea y validación personalizada y conjuntos de consultas personalizados. Por lo tanto, la acción de agregar modelo depende de los formularios que necesitan otras cosas, y el 'agregar modelo' en el administrador de django pasa por 500 desde un conjunto de consultas personalizado.

¿Hay alguna forma de deshabilitar la funcionalidad 'Agregar $ MODELO' para ciertos modelos?

Quiero /admin/appname/modelname/add/dar un mensaje de error 404 (o un mensaje de error adecuado de "desaparecer"), no quiero que aparezca el botón "Agregar $ MODELNAME" /admin/appname/modelname.

El administrador de Django proporciona una forma de deshabilitar las acciones de administrador (http://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#disabling-actions), sin embargo, la única acción para este modelo es 'delete_selected'. es decir, las acciones de administrador solo actúan en los modelos existentes. ¿Hay alguna forma de django esque para hacer esto?

Rory
fuente
FYI: 'acciones' en django admin son el menú desplegable que se aplica en la vista de la lista de cambios a cualquier fila marcada en la lista.
Tim Diggins
1
Pregunta relacionada (pero diferente): stackoverflow.com/questions/1721037/…
user9876

Respuestas:

342

Es fácil, solo sobrecarga el has_add_permissionmétodo en tu Adminclase de esta manera:

class MyAdmin(admin.ModelAdmin):
     def has_add_permission(self, request, obj=None):
        return False
Frost.baka
fuente
77
Esto no funcionó para mí. El botón "Agregar modelo" todavía se muestra en la página de lista de cambios del modelo.
Cerin
¿Qué es MyAdmin aquí?
user5319825
1
No olvide registrar también MyAdmin como: admin.site.register(MyModel, MyModelAdmin)Agregar todo a la admin.pycarpeta de aplicaciones de los modelos.
djangonaut
Y esta es exactamente la razón por la que amo tanto a Python y Django. Sencillo. Funcionó muy bien. ¡Gracias!
dxhans5
2
Trabaja en Django 1.11. No hay necesidad deobj parámetro.
fjsj
9

Por defecto, syncdb crea 3 permisos de seguridad para cada modelo:

  1. Crear (también conocido como agregar)
  2. Cambio
  3. Eliminar

Si has iniciado sesión como administrador, obtienes TODO sin importar qué.

Pero si creas un nuevo grupo de usuarios llamado "Acceso general" (por ejemplo), entonces puede asignar SOLO los permisos CAMBIAR y ELIMINAR para todos sus modelos.

Entonces, cualquier usuario conectado que sea miembro de ese grupo no tendrá permiso de "Crear", nada relacionado con él se mostrará en la pantalla.

Richard Cooke
fuente
7

Creo que esto te ayudará ... el siguiente código debe estar en el archivo admin.py

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    list_display = ('name', )
    list_filter = ('name', )
    search_fields = ('name', )
    list_per_page = 20

    # This will help you to disbale add functionality
    def has_add_permission(self, request):
        return False

    # This will help you to disable delete functionaliyt
    def has_delete_permission(self, request, obj=None):
        return False

Además de lo anterior publicado por

    # This will help you to disable change functionality
    def has_change_permission(self, request, obj=None):
        return False
Sandeep Prasad Kushwaha
fuente
Esto funciona con 2.2. y también eliminará los botones Agregar y Eliminar para superusuarios. Exactamente lo que necesito.
Erik Kalkoken
2

Simplemente copie el código de otra respuesta

# In admin
# make the related field can't be added
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        form.base_fields['service'].widget.can_add_related = False
        return form

En mi caso uso inline

# In inline formset e.g. admin.TabularInline
# disable all
    def get_formset(self, request, obj=None, **kwargs):
        formset = super().get_formset(request, obj, **kwargs)
        service = formset.form.base_fields['service']
        service.widget.can_add_related = service.widget.can_change_related = service.widget.can_delete_related = False
        return formset

en service = formset.form.base_fields['service'] base_fieldses los campos definidos en el modelo

si se define en el formulario, use:

product = formset.form.declared_fields['product']

ver también

CK
fuente
Sí, base_fieldsy declared_fieldsson el hallazgo más importante que aprendí de este caso.
CK
0

Esta es una respuesta demasiado tardía; Simplemente publique esto como si alguien estuviera encontrando la misma solución.

En el archivo admin.py puede hacer lo siguiente:

class MyModelForm(forms.ModelForm):

class Meta:
    model = MyModel
    fields = '__all__'


class MyModelAdmin(admin.ModelAdmin):
    form = QuestionTrackAdminForm
    list_display = ['title', 'weight']
    readonly_fields = ['title', 'weight']

admin.site.register(MyModel, MyModelAdmin)

Aquí, "readonly_fields" hace la magia. Gracias.

Mohammad
fuente
44
Esto no evita que aparezca el botón "agregar".
Flimm
Esta solución simplemente deshabilitará los campos de título y peso en el formulario. No evitaría la creación de un nuevo objeto MyModelAdmin, que es lo que creo que estaba pidiendo el OP.
dxhans5