tutorial theme template superusuario startapp personalizar password manage crear python django django-admin

python - theme - personalizar admin django



Diferentes campos para agregar y cambiar páginas en admin. (8)

Así es como se hace en Django 1.10. Simplemente anule get_form y devuelva add_form cuando el objeto sea Ninguno:

class FoobarAddForm(forms.ModelForm): class Meta: model = Foobar fields = [''some_field'',] @register(Foobar) class AdminFoobar(admin.ModelAdmin): add_form = FoobarAddForm def get_form(self, request, obj=None, **kwargs): defaults = {} if obj is None: defaults[''form''] = self.add_form defaults.update(kwargs) return super(AdminFoobar, self).get_form(request, obj, **defaults)

Tengo una aplicación django con la siguiente clase en mi admin.py:

class SoftwareVersionAdmin(ModelAdmin): fields = ("product", "version_number", "description", "media", "relative_url", "current_version") list_display = ["product", "version_number", "size", "current_version", "number_of_clients", "percent_of_clients"] list_display_links = ("version_number",) list_filter = [''product'',]

Quiero tener estos archivos para la página de agregar pero diferentes campos para cambiar de página. ¿Cómo puedo hacer eso?


Esta es una pregunta antigua, pero quería agregar que los métodos add_view y change_view se pueden modificar para este propósito:

class SoftwareVersionAdmin(ModelAdmin): ... def add_view(self,request,extra_content=None): self.exclude = (''product'',''version_number'',) return super(SoftwareVersionAdmin,self).add_view(request) def change_view(self,request,object_id,extra_content=None): self.exclude = (''product'',''description'',) return super(SoftwareVersionAdmin,self).change_view(request,object_id)


Este código específico no funcionó para mí. Simplemente lo cambio un poco:

if obj: # obj is not None, so this is a change page #kwargs[''exclude''] = [''owner''] self.fields = [''id'', ''family_name'', ''status'', ''owner''] else: # obj is None, so this is an add page #kwargs[''fields''] = [''id'', ''family_name'', ''status''] self.fields = [''id'', ''family_name'', ''status''] return super(YourAdmin, self).get_form(request, obj, **kwargs)


La solución de dpawlows anterior es la más clara, creo.

Sin embargo, me encontré con un problema adicional en ese tipo de estructura.

Si change_view() realiza cambios en el modelo, por ejemplo, especifica readonly_fields que se completaron en add_view() , estos cambios persisten en add_view() después de change_view() . Por ejemplo:

def add_view(self, request, extra_context=None): return super().add_view(request) def change_view(self, request, object_id, extra_context=None): self.readonly_fields = [''name''] # this change persists in add_view() return super().change_view(self, request, object_id)

En este caso, después de change_view() en cualquier instancia, al invocar a add_view() se mostrará readonly_fields ("nombre", en este caso) establecido por change_view() y, por lo tanto, protegerá estos campos para que no se change_view() .

Esto se puede resolver agregando una asignación de ''retroceso'' en add_view() :

def add_view(self, request, extra_context=None): self.readonly_fields = [] # ''roll back'' for changes made by change_view() return super().add_view(request)


No creo que sea una buena idea anular los fields o exclude o form , porque son atributos de configuración, por lo que no se inicializarían para cada solicitud.
Creo que la respuesta aceptada por Shanyu es una buena solución.

O podemos usar el método de UserAdmin:

def get_fieldsets(self, request, obj=None): if not obj: return self.add_fieldsets return super(UserAdmin, self).get_fieldsets(request, obj)

Recuerde asignar los add_fieldsets usted mismo. Lamentablemente no se ajusta a mi caso de uso.

Para Django 1.7. No sé cómo se implementan en otras versiones.


No pude hacer que esto funcionara en django 1.6.5 usando las soluciones anteriores. Así que intenté crear formularios y hacer que get_form sirva esos formularios predefinidos dependiendo de si el objeto existe o no:

modelos.py:

from django.db import models class Project(models.Model): name = models.CharField(''Project Name'', max_length=255) slug = models.SlugField(''Project Slug'', max_length=255, unique=True)

forms.py: desde django importar formularios desde modelos importar proyecto

class ProjectAddForm(forms.ModelForm): test = forms.Field() class Meta: model = Project class ProjectEditForm(forms.ModelForm): class Meta: model = Project fields = ("name", ''slug'')

admin.py

from django.contrib import admin from models import Project from forms import ProjectAddForm, ProjectEditForm class ProjectAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): # Proper kwargs are form, fields, exclude, formfield_callback if obj: self.form = ProjectEditForm else: self.form = ProjectAddForm return super(ProjectAdmin, self).get_form(request, obj, **kwargs) admin.site.register(Project, ProjectAdmin)

Ahora puedo interceptar el campo de prueba no persistente en los formularios de limpieza y hacer lo que deseo con él, simplemente sobrescribir limpio en el ProjectAddForm:

def clean(self): cleaned_data = super(ProjectAddForm, self).clean() test = cleaned_data.get("test") # Do logic here #raise forms.ValidationError("Passwords don''t match.") return cleaned_data


Primero eche un vistazo a la fuente de los métodos get_form y get_formsets clase get_formsets ubicados en django.contrib.admin.options.py . Puede anular esos métodos y usar kwargs para obtener el comportamiento que desea. Por ejemplo:

class SoftwareVersionAdmin(ModelAdmin): def get_form(self, request, obj=None, **kwargs): # Proper kwargs are form, fields, exclude, formfield_callback if obj: # obj is not None, so this is a change page kwargs[''exclude''] = [''foo'', ''bar'',] else: # obj is None, so this is an add page kwargs[''fields''] = [''foo'',] return super(SoftwareVersionAdmin, self).get_form(request, obj, **kwargs)


Usando formularios en Django 1.6 terminé con lo siguiente:

def get_formsets(self, request, obj=None): if obj is None: # It''s a new object for field, fieldset in {''hide_me_from_the_first_fieldset'': 0, ''me_from_the_second'': 1, ''and_me_too'': 1}.items(): self.fieldsets[fieldset][1][''fields''].remove(field) return super().get_formsets(request, obj)

EDITAR: Quizás una forma más intuitiva es especificar una propiedad add_fieldsets separada y hacer:

def get_formsets(self, request, obj=None): if obj is None: self.fieldsets = self.add_fieldsets return super().get_formsets(request, obj)