一尘不染

Django:从ModelAdmin中访问模型实例?

django

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

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类。对于详细视图,我已包含parent_orderfieldsets属性中。当然,默认情况下,这会在选择框中列出所有订单,但这不是所需的行为。相反,对于没有父订单的订单(即未与其他订单拆分;parent_order为NULL /无)的订单不应该显示。对于已拆分的订单,这应仅显示单个父订单。

有一个相当新的ModelAdmin方法可用,formfield_for_foreignkey它似乎很完美,因为可以在其中过滤查询集。想象一下,我们正在查看订单#11234的详细信息视图,该视图已从订单#11208中分离出来。代码如下

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中运行时有效,返回单项查询集,其中包含#11234的订单#11208和可能已经从中拆分的所有其他订单。

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

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

我没有找到替代?????的工作方法 并引用了“当前” Order实例,我对此进行了深入研究。self内部formfield_for_foreignkey是指ModelAdmin实例,尽管它确实具有model属性,但不是订单模型实例(它是ModelBase引用; self.model()返回一个实例,但其订单号为None)。

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


阅读 542

收藏
2020-04-02

共1个答案

一尘不染

我认为你可能需要以稍微不同的方式来实现此目的-通过修改ModelForm而不是admin类。像这样:

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
2020-04-02