Django:从 ModelAdmin 中访问模型实例? [英] Django: accessing the model instance from within ModelAdmin?

查看:28
本文介绍了Django:从 ModelAdmin 中访问模型实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网上商店应用程序中的订单模型,具有自动递增的主键和自身的外键,因为订单可以拆分为多个订单,但必须保持与原始订单的关系.

I've got a model for Orders in a webshop application, with an auto-incrementing primary key and a foreign key to itself, since orders can be split into multiple orders, but the relationship to the original order must be maintained.

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

我已经为管理站点注册了一个 OrderAdmin 类.对于详细视图,我在 fieldsets 属性中包含了 parent_order.当然,默认情况下,这会在选择框中列出所有订单,但这不是所需的行为.相反,对于没有父订单的订单(即没有从另一个订单拆分;parent_order 为 NULL/None),不应显示任何订单.对于已拆分的订单,这应该只显示单父订单.

I've registered an OrderAdmin class for the admin site. For the detail view, I've included parent_order in the fieldsets attribute. Of course, by default this lists all the orders in a select box, but this is not the desired behaviour. Instead, for orders that don't have a parent order (i.e. have not been split from another order; parent_order is NULL/None), no orders should be displayed. For orders that have been split, this should only display the single parent order.

有一个相当新的 ModelAdmin 方法可用,formfield_for_foreignkey,这似乎是完美的,因为可以在其中过滤查询集.假设我们正在查看订单#11234 的详细视图,该订单已从订单#11208 中拆分出来.代码如下

There's a rather new ModelAdmin method available, formfield_for_foreignkey, that seems perfect for this, since the queryset can be filtered inside it. Imagine we're looking at the detail view of order #11234, which has been split from order #11208. The code is below

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)

注释行在 Python shell 中运行时有效,返回一个单项查询集,其中包含订单 #11208 和 #11234 以及所有其他可能已从中拆分的订单.

The commented row works when run in a Python shell, returning a single-item queryset containing order #11208 for #11234 and all other orders that may have been split from it.

当然,我们不能在那里对订单号进行硬编码.我们需要引用我们正在查看其详细信息页面的订单实例的 ordernumber 字段.像这样:

Of course, we can't hard-code the order number there. We need a reference to the ordernumber field of the order instance whose detail page we're looking at. Like this:

kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=?????)

我没有找到替换的有效方法??????参考当前" Order 实例,我已经深入挖掘了.formfield_for_foreignkey 中的 self 指的是 ModelAdmin 实例,虽然它确实具有 model 属性,但它不是订单模型实例(它是 ModelBase 引用; self.model() 返回一个实例,但它的 ordernumber 是 None).

I've found no working way to replace ????? with a reference to the "current" Order instance, and I've dug pretty deep. self inside formfield_for_foreignkey refers to the ModelAdmin instance, and while that does have a model attribute, it's not the order model instance (it's a ModelBase reference; self.model() returns an instance, but its ordernumber is None).

一种解决方案可能是从 request.path (/admin/orders/order/11234/) 中提取订单号,但这真的很难看.我真的希望有更好的方法.

One solution might be to pull the order number from request.path (/admin/orders/order/11234/), but that is really ugly. I really wish there is a better way.

推荐答案

我认为您可能需要以稍微不同的方式来解决这个问题 - 通过修改 ModelForm 而不是管理类.像这样的:

I think you might need to approach this in a slightly different way - by modifying the ModelForm, rather than the admin class. Something like this:

class OrderForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(OrderForm, self).__init__(*args, **kwargs)
        self.fields['parent_order'].queryset = Order.objects.filter(
            child_orders__ordernumber__exact=self.instance.pk)

class OrderAdmin(admin.ModelAdmin):
    form = OrderForm

这篇关于Django:从 ModelAdmin 中访问模型实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆