Django: accessing the model instance from within ModelAdmin?
我在webshop应用程序中有一个订单模型,它有一个自动递增的主键和一个外键,因为订单可以拆分为多个订单,但是必须保持与原始订单的关系。
1 2 3 4 | 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类。对于详细视图,我在
有一个非常新的modeladmin方法,
1 2 3 4 5 | 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中运行时,注释行起作用,返回包含order 11208 for 11234和所有其他可能已从中拆分的订单的单个项查询集。
当然,我们不能在那里硬编码订单号。我们需要一个订单实例的
1 | kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=?????) |
我找不到替代的工作方式???????关于"当前"订单实例,我已经挖得很深了。
一种解决方案可能是从request.path中提取订单号(/admin/orders/order/11234/),但这确实很难看。我真希望有更好的方法。
我认为您可能需要以稍微不同的方式来处理这个问题——通过修改ModelForm,而不是管理类。像这样:
1 2 3 4 5 6 7 8 9 | 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 |
我已经用这种方式模拟了我的内联类。它在如何获取父表单ID来过滤内联数据方面有点难看,但是它可以工作。它从父窗体中按公司筛选单位。
原始概念解释如下:http://www.stereoplex.com/blog/filtering下拉列表in the django admin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class CompanyOccupationInline(admin.TabularInline): model = Occupation # max_num = 1 extra = 0 can_delete = False formset = RequiredInlineFormSet def formfield_for_dbfield(self, field, **kwargs): if field.name == 'unit': parent_company = self.get_object(kwargs['request'], Company) units = Unit.objects.filter(company=parent_company) return forms.ModelChoiceField(queryset=units) return super(CompanyOccupationInline, self).formfield_for_dbfield(field, **kwargs) def get_object(self, request, model): object_id = resolve(request.path).args[0] try: object_id = int(object_id) except ValueError: return None return model.objects.get(pk=object_id) |
号
上面来自欧文·朱利叶斯的回答对我很有效,但我发现"get-uobject"这个名称与django函数冲突,所以将函数命名为"my-get-uobject"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class CompanyOccupationInline(admin.TabularInline): model = Occupation # max_num = 1 extra = 0 can_delete = False formset = RequiredInlineFormSet def formfield_for_dbfield(self, field, **kwargs): if field.name == 'unit': parent_company = self.my_get_object(kwargs['request'], Company) units = Unit.objects.filter(company=parent_company) return forms.ModelChoiceField(queryset=units) return super(CompanyOccupationInline, self).formfield_for_dbfield(field, **kwargs) def my_get_object(self, request, model): object_id = request.META['PATH_INFO'].strip('/').split('/')[-1] try: object_id = int(object_id) except ValueError: return None return model.objects.get(pk=object_id) |
它告诉我不要"回应"别人的回答,但我还不能"回复",我已经找了一段时间了,所以希望这对别人有帮助。我也不被允许上票,否则我会的!