Tengo un sistema como este en un proyecto que estoy terminando. Habrá mucho trabajo para poner esto juntos, pero aquí están algunos de los componentes que he tenido que hacer mi trabajo del sistema:
Se necesita una manera de definir un editor y un supervisor. Las tres formas en que esto se puede hacer son 1.) al tener un campo M2M que define al supervisor [y suponiendo que todos los demás con permiso para leer/escribir son editores], 2.) crear 2 nuevos modelos de usuario que hereden del usuario [ probablemente más trabajo de lo necesario] o 3.) use la habilidad django.auth para tener una clase UserProfile. El método # 1 es probablemente el más razonable.
Una vez que pueda identificar qué tipo es el usuario, necesita una forma de aplicar genéricamente la autorización que está buscando. Creo que la mejor ruta aquí es probablemente un modelo de administrador genérico.
Por último, necesitará algún tipo de modelo "principal" que tenga los permisos para lo que necesite moderarse. Por ejemplo, si tenía un modelo de Blog y un modelo de BlogPost (suponiendo que hay varios blogs dentro del mismo sitio), Blog es el modelo principal (puede contener los permisos de quién aprueba qué). Sin embargo, si tiene un solo blog y no hay un modelo principal para BlogPost, necesitaremos un lugar donde almacenar los permisos. He encontrado que el ContentType
funciona bien aquí.
Aquí hay algunas ideas en el código (no probadas y más conceptuales que las reales).
Crea una nueva aplicación llamada 'moderada' que contendrá nuestros elementos genéricos.
moderated.models.py
class ModeratedModelParent(models.Model):
"""Class to govern rules for a given model"""
content_type = models.OneToOneField(ContentType)
can_approve = models.ManyToManyField(User)
class ModeratedModel(models.Model):
"""Class to implement a model that is moderated by a supervisor"""
is_approved = models.BooleanField(default=False)
def get_parent_instance(self):
"""
If the model already has a parent, override to return the parent's type
For example, for a BlogPost model it could return self.parent_blog
"""
# Get self's ContentType then return ModeratedModelParent for that type
self_content_type = ContentType.objects.get_for_model(self)
try:
return ModeratedModelParent.objects.get(content_type=self_content_type)
except:
# Create it if it doesn't already exist...
return ModeratedModelParent.objects.create(content_type=self_content_type).save()
class Meta:
abstract = True
Así que ahora debería tener un poco reutilizable genérico, de código que podemos identificar el permiso para un determinado modelo (que se identificará el modelo por su tipo de contenido).
A continuación, se puede poner en práctica nuestras políticas en el admin, de nuevo a través de un modelo genérico:
moderated.admin.py
class ModeratedModelAdmin(admin.ModelAdmin):
# Save our request object for later
def __call__(self, request, url):
self.request = request
return super(ModeratedModelAdmin, self).__call__(request, url)
# Adjust our 'is_approved' widget based on the parent permissions
def formfield_for_dbfield(self, db_field, **kwargs):
if db_field.name == 'is_approved':
if not self.request.user in self.get_parent_instance().can_approve.all():
kwargs['widget'] = forms.CheckboxInput(attrs={ 'disabled':'disabled' })
# Enforce our "unapproved" policy on saves
def save_model(self, *args, **kwargs):
if not self.request.user in self.get_parent_instance().can_approve.all():
self.is_approved = False
return super(ModeratedModelAdmin, self).save_model(*args, **kwargs)
Una vez que estos son de configuración y de trabajo, podemos volver Úselos en muchos modelos como he encontrado una vez que agrega permisos estructurados para algo como esto, lo desea fácilmente para muchas otras cosas.
Digamos, por ejemplo, que tiene un modelo de noticias, simplemente tendría que heredarlo del modelo que acabamos de hacer y está listo.
# in your app's models.py
class NewsItem(ModeratedModel):
title = models.CharField(max_length=200)
text = models.TextField()
# in your app's admin.py
class NewsItemAdmin(ModeratedModelAdmin):
pass
admin.site.register(NewsItem, NewsItemAdmin)
estoy seguro que he cometido algunos errores de código y errores en allí, pero espero que esto le puede dar algunas ideas para actuar como una plataforma de lanzamiento para lo que decida implementar.
Lo último que tienes que hacer, que te dejo, es implementar el filtrado para los artículos is_approved
. (. Es decir, usted no desea que los elementos no aprobados que se enumeran en la sección de noticias, ¿verdad?)
que probablemente significaba self.exclude = [ 'aprobado'] en get_form() y también hay pequeño fallo en changelist_view() ;) Gracias, esto se ve muy bien y se combina con trozos de T. La respuesta de Stone, es exactamente lo que he estado buscando :) – minder
¿y si obtengo 'el objeto no tiene ningún atributo 'COOKIES''? – andi
¿los permisos deben registrarse en algún otro lugar para ser visibles en el módulo de administración? – andi