2010-05-02 29 views
7

Quiero agregar algunos campos a cada modelo en mi aplicación django. Esta vez es created_at, updated_at y notes. Duplicar el código para cada uno de los más de 20 modelos parece tonto. Entonces, decidí usar una clase base abstracta que agregaría estos campos. El problema es que los campos heredados de la clase base abstracta son los primeros en la lista de campos en admin. Declarar el orden de campo para cada clase de ModelAdmin no es una opción, es incluso más código duplicado que con la declaración de campo manual.Reordenando campos en Django modelo

En mi solución final, he modificado constructor de modelo para cambiar el orden de los campos en _meta antes de crear nueva instancia:

class MyModel(models.Model): 
    # Service fields 
    notes = my_fields.NotesField() 
    created_at = models.DateTimeField(auto_now_add=True) 
    updated_at = models.DateTimeField(auto_now=True) 

    class Meta: 
     abstract = True 

    last_fields = ("notes", "created_at", "updated_at") 
    def __init__(self, *args, **kwargs): 
     new_order = [f.name for f in self._meta.fields] 
     for field in self.last_fields: 
      new_order.remove(field) 
      new_order.append(field) 
     self._meta._field_name_cache.sort(key=lambda x: new_order.index(x.name)) 
     super(MyModel, self).__init__(*args, **kwargs) 

class ModelA(MyModel): 
    field1 = models.CharField() 
    field2 = models.CharField() 
    #etc ... 

Se funciona como está previsto, pero me pregunto, ¿existe una mejor manera de acheive mi objetivo ?

Respuesta

5

Si necesita principalmente el pedido del administrador de Django, también puede crear su clase "genérica" ​​-admin subclasificando la clase de administración de Django. Consulte http://docs.djangoproject.com/en/dev/intro/tutorial02/#customize-the-admin-form para personalizar la visualización de campos en el administrador. Puede sobrescribir __init__ del administrador para configurar campos/conjuntos de campos en la creación de la instancia de administrador como desee. P.ej. usted podría hacer algo como:

class MyAdmin(admin.ModelAdmin): 
    def __init__(self, model, admin_site): 
     general_fields = ['notes', 'created_at', 'updated_at'] 
     fields = [f.name for f in self.model._meta.fields if f.name not in general_fields] 
     self.fields = fields + general_fields 
     super(admin.ModelAdmin, self).__init__(model, admin_site) 

Además de eso creo que no es una buena práctica para modificar el (privado) _field_name_cache!

7

que estaba teniendo el mismo problema, pero me encontré con estas soluciones sean problemáticos, por lo que aquí es lo que hice:

class BaseAdmin(admin.ModelAdmin): 
    def get_fieldsets(self, request, obj = None): 
     res = super(BaseAdmin, self).get_fieldsets(request, obj) 
     # I only need to move one field; change the following 
     # line to account for more. 
     res[0][1]['fields'].append(res[0][1]['fields'].pop(0)) 
     return res 

Cambio del conjunto de campos en el admin tiene más sentido para mí, que el cambio de los campos en el modelo.

0

TAMBIÉN no me gustaron las otras soluciones, así que en su lugar solo modifiqué los archivos de migraciones directamente.

Cada vez que cree una nueva tabla en models.py, tendrá que ejecutar "python manage.py makemigrations" (creo esto en Django> = v1.7.5). Una vez hecho esto, abra el archivo de migraciones recién creado en el directorio your_app_path/migrations/ y simplemente mueva las filas al orden en el que desea que estén. Luego ejecute "python manage.py migrate". Voila! Al entrar en "python manage.py dbshell", puede ver que el orden de las columnas es exactamente como lo deseaba.

Desventaja de este método: tiene que hacer esto manualmente para cada tabla que cree, pero afortunadamente la sobrecarga es mínima. Y esto solo se puede hacer cuando estás creando una nueva tabla, no para modificar una existente.

Cuestiones relacionadas