Tengo un modelo para pedidos en una aplicación de tienda en línea, con una clave principal autoincrementada y una clave externa, ya que las órdenes se pueden dividir en varias órdenes, pero se debe mantener la relación con la orden original.Django: ¿accediendo a la instancia del modelo desde ModelAdmin?
class Order(models.Model):
ordernumber = models.AutoField(primary_key=True)
parent_order = models.ForeignKey('self', null=True, blank=True, related_name='child_orders')
# .. other fields not relevant here
He registrado una clase OrderAdmin para el sitio de administración. Para la vista detallada, he incluido parent_order
en el atributo fieldsets
. Por supuesto, por defecto esto enumera todos los pedidos en un cuadro de selección, pero este no es el comportamiento deseado. En cambio, para pedidos que no tienen un pedido principal (es decir, no se han dividido desde otro pedido; parent_order
es NULL/Ninguno), no se deben mostrar pedidos. Para los pedidos que se han dividido, esto solo debe mostrar el orden principal único.
Hay un método más nuevo de ModelAdmin disponible, formfield_for_foreignkey
, que parece perfecto para esto, ya que el conjunto de consulta puede filtrarse dentro de él. Imagine que estamos viendo la vista detallada de la orden # 11234, que se ha dividido de la orden # 11208. El código está por debajo
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'parent_order':
# kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=11234)
return db_field.formfield(**kwargs)
return super(OrderAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
La fila comentado funciona cuando se ejecuta en un terminal de Python, que devuelve un conjunto de consultas de un solo artículo que contiene la orden # 11208 # 11234 para todas las demás órdenes y que pueden haber sido divididas de ella.
Por supuesto, no podemos codificar el número de pedido allí. Necesitamos una referencia al campo ordernumber
de la instancia de orden cuya página de detalles estamos viendo. De esta manera:
kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=?????)
No he encontrado ninguna manera de trabajo para reemplazar ????? con una referencia a la instancia de pedido "actual", y he cavado bastante profundo. self
dentro de formfield_for_foreignkey
se refiere a la instancia de ModelAdmin, y si bien tiene un atributo model
, no es la instancia del modelo de orden (es una referencia de ModelBase; self.model() devuelve una instancia, pero su número de orden es Ninguno).
Una solución podría ser extraer el número de pedido de request.path (/ admin/orders/order/11234 /), pero eso es realmente feo. Realmente deseo que haya una mejor manera.
¡Funciona! Muchas gracias!Soy completamente nuevo en todo este negocio de ModelForm/ModelAdmin, y estaba buscando en el lugar equivocado. –
Me doy cuenta de que esta publicación es antigua, pero esto también funcionó como una solución decente para get_readonly_fields en una InlineModelAdmin ya que el parámetro obj que se le pasó es actualmente el objeto principal, no el objeto de la instancia en línea. Para todos los efectos, esto hizo que mi objeto fuera solo de lectura al permitirme devolver solo un objeto a mi clave externa. – dgraves
Asegúrate de llamar a super .__ init__ primero. Eso establece self.instance. – yellottyellott