template password_reset loginview custom abstractuser django permissions django-admin admin

password_reset - Django Admin-Contenido específico del usuario(administrador)



loginview django (4)

Creo que RelatedOnlyFieldListFilter debería ayudarlo. Aquí el enlace a Django Doc: RelatedOnlyFieldListFilter

list_filter puede ser: una tupla, donde el primer elemento es un nombre de campo y el segundo elemento es una clase que hereda de django.contrib.admin.FieldListFilter, por ejemplo:

class PersonAdmin(admin.ModelAdmin): list_filter = ( (''is_staff'', admin.BooleanFieldListFilter), )

Puede limitar las opciones de un modelo relacionado a los objetos implicados en esa relación utilizando RelatedOnlyFieldListFilter: (Vous pouvez limitter les choix d''un modèle lié aux objectivés concernés par la relation en utilisant RelatedOnlyFieldListFilter :)

class BookAdmin(admin.ModelAdmin): list_filter = ( (''author'', admin.RelatedOnlyFieldListFilter), )

Asumiendo que el autor es una ForeignKey para un modelo de usuario, esto limitará las opciones de list_filter a los usuarios que han escrito un libro en lugar de enumerar a todos los usuarios . (En caso de que el autor sea extranjero, ForeignKey vers un modèle Usuario, cela va limitador les choix de list_filter aux utilisateurs qui ont écrit un livre au lieu d''énumérer tous les utilisateurs.)

Estoy empezando a organizar un nuevo proyecto y digamos que tendré algunos modelos como productos y catálogos .

Permitiré que mis clientes (no visitantes, solo clientes específicos) inicien sesión en el sitio de Administración de Django para crear, editar y eliminar sus propios catálogos.

Digamos que creo un modelo llamado "Tienda" , creo cada tienda (nombre, dirección, logotipo, información de contacto, etc.) y creo un usuario administrador vinculado a esa tienda.

Ahora quiero que este nuevo administrador (que no es un administrador del sitio, sino un administrador de la tienda, probablemente un grupo de usuarios ) vea y edite solo los catálogos vinculados con su tienda .

¿Es eso posible?

¿Debería hacer esto dentro de Django Admin o debería crear una nueva aplicación "shop admin"?


Lo siento, sé que es tarde, pero tal vez ayudaría a los demás. Supongo que la aplicación de django-permission podría ayudar a realizar el propósito.


Solo estoy publicando esto aquí porque el comentario principal ya no es la respuesta más actualizada. Estoy usando Django 1.9, no estoy seguro de cuándo se produjo este cambio.

Por ejemplo, tiene diferentes Sedes y diferentes usuarios asociados con cada Venue, el modelo se verá más o menos así:

class Venue(models.Model): user = models.ForeignKey(User) venue_name = models.CharField(max_length=255) area = models.CharField(max_length=255)

Ahora, el estado del personal para el usuario debe ser verdadero si permite iniciar sesión a través del panel de administración de django.

El admin.py se ve algo así como:

class FilterUserAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): if getattr(obj, ''user'', None) is None: obj.user = request.user obj.save() def get_queryset(self, request): qs = super(FilterUserAdmin, self).queryset(request) if request.user.is_superuser: return qs return qs.filter(user=request.user) def has_change_permission(self, request, obj=None): if not obj: return True return obj.user == request.user or request.user.is_superuser @admin.register(Venue) class VenueAdmin(admin.ModelAdmin): pass

el nombre de la función ha cambiado de queryset a get_queryset.

EDIT: quería extender mi respuesta. Hay otra forma de devolver objetos filtrados sin usar la función queryset. Quiero enfatizar que no sé si este método es más eficiente o menos eficiente.

Una implementación alternativa para el método get_queryset es la siguiente:

def get_queryset(self, request): if request.user.is_superuser: return Venue.objects.all() else: return Venue.objects.filter(user=request.user)

Además, también podemos filtrar el contenido porque las relaciones son más profundas.

class VenueDetails(models.Model): venue = models.ForeignKey(Venue) details = models.TextField()

Ahora, si deseo filtrar este modelo que tiene Venue como clave externa pero no tiene User, mi consulta cambia de la siguiente manera:

def get_queryset(self, request): if request.user.is_superuser: return VenueDetails.objects.all() else: return VenueDetails.objects.filter(venue__user=request.user)

Django ORM nos permite acceder a diferentes tipos de relaciones que pueden ser tan profundas como queramos a través de ''__''

Here''s un enlace a los documentos oficiales para lo anterior.


Primero, la advertencia: La filosofía de diseño de administración de Django es que cualquier usuario con acceso al administrador ( is_staff==True ) es un usuario de confianza , por ejemplo, un empleado, de ahí la designación de "personal" para incluso obtener acceso al administrador. Si bien puede personalizar el administrador para restringir áreas, permitir que cualquier persona que no esté dentro de su organización tenga acceso a su administrador se considera arriesgado, y Django no ofrece garantías sobre ningún tipo de seguridad en ese momento.

Ahora, si aún desea continuar, puede restringir la mayoría de las cosas, excepto las tiendas, de la nada simplemente al no asignar esos privilegios al usuario. Deberá otorgar a todos los propietarios de las tiendas los derechos para editar cualquiera de los modelos de la tienda a los que necesitarán acceder, pero todo lo demás debe dejarse fuera de su lista de permisos.

Luego, para cada modelo que debe limitarse únicamente a los ojos del propietario, deberá agregar un campo para almacenar el "propietario" o el usuario tendrá acceso a él. Puede hacer esto con el método save_model en ModelAdmin , que tiene acceso al objeto de solicitud:

class MyModelAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): obj.user = request.user super(MyModelAdmin, self).save_model(request, obj, form, change)

Luego, también deberá limitar el conjunto de consultas del ModelAdmin solo a los elementos que posee el usuario actual:

class MyModelAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super(MyModelAdmin, self).get_queryset(request) if request.user.is_superuser: return qs return qs.filter(owner=request.user)

Sin embargo, eso solo limitará lo que aparece en la lista, el usuario podría seguir jugando con la URL para acceder a otros objetos a los que no tiene acceso, por lo que deberá anular cada una de las vistas vulnerables del ModelAdmin para redirigir si el usuario no está el propietario:

from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse class MyModelAdmin(admin.ModelAdmin): def change_view(self, request, object_id, form_url='''', extra_context=None): if not self.queryset(request).filter(id=object_id).exists(): return HttpResponseRedirect(reverse(''admin:myapp_mymodel_changelist'')) return super(MyModelAdmin, self).change_view(request, object_id, form_url, extra_context) def delete_view(self, request, object_id, extra_context=None): if not self.queryset(request).filter(id=object_id).exists(): return HttpResponseRedirect(reverse(''admin:myapp_mymodel_changelist'')) return super(MyModelAdmin, self).delete_view(request, object_id, extra_context) def history_view(self, request, object_id, extra_context=None): if not self.queryset(request).filter(id=object_id).exists(): return HttpResponseRedirect(reverse(''admin:myapp_mymodel_changelist'')) return super(MyModelAdmin, self).history_view(request, object_id, extra_context)

ACTUALIZACIÓN 06/05/12

Gracias @ christophe31 por señalar que dado que el conjunto de ModelAdmin de ModelAdmin ya está limitado por el usuario, puede usar self.queryset() en las vistas de cambio, eliminación e historial. Esto abstrae muy bien el nombre de clase modelo que hace que el código sea menos frágil. También cambié a usar filter y exists lugar de try...except bloquear con get . Es más racionalizado de esa manera, y en realidad resulta en una consulta más simple también.