我有一个类似于以下的双向外国关系
class Parent(models.Model):
name = models.CharField(max_length=255)
favoritechild = models.ForeignKey("Child", blank=True, null=True)
class Child(models.Model):
name = models.CharField(max_length=255)
myparent = models.ForeignKey(Parent)
Run Code Online (Sandbox Code Playgroud)
如何将Parent.favoritechild的选择仅限于父母本身的子女?我试过了
class Parent(models.Model):
name = models.CharField(max_length=255)
favoritechild = models.ForeignKey("Child", blank=True, null=True, limit_choices_to = {"myparent": "self"})
Run Code Online (Sandbox Code Playgroud)
但这会导致管理界面不列出任何子项.
我在网上商店应用程序中有一个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
Run Code Online (Sandbox Code Playgroud)
我已经为管理站点注册了OrderAdmin类.对于详细视图,我已经包含parent_order在fieldsets属性中.当然,默认情况下,它会列出选择框中的所有订单,但这不是所需的行为.相反,对于没有父订单的订单(即未从另一个订单拆分; parent_order是NULL/None),不应显示任何订单.对于已拆分的订单,此应仅显示单个父订单.
有一个相当新的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)
Run Code Online (Sandbox Code Playgroud)
注释行在Python shell中运行时返回,返回单项查询集,其中包含#11234的#11208订单以及可能已从中拆分的所有其他订单.
当然,我们不能在那里硬编码订单号.我们需要引用ordernumber订单实例的字段,我们正在查看其详细信息页面.像这样:
kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=?????)
Run Code Online (Sandbox Code Playgroud)
我发现没有办法替换????? 参考"当前"订单实例,我挖得很深.selfinside formfield_for_foreignkey指的是ModelAdmin实例,虽然它确实有一个model属性,但它不是订单模型实例(它是ModelBase引用; self.model()返回一个实例,但它的ordernumber是None).
一个解决方案可能是从request.path(/ admin/orders/order/11234 /)中提取订单号,但这真的很难看.我真的希望有更好的方法.
我试图根据父窗体/实例的属性在内联中设置选择字段的默认值.
在伪代码中,它看起来像:
def get_form(self, ***):
if self.parent.instance && self.parent.instance.field_x == "y":
self.field_name.choices = ...
Run Code Online (Sandbox Code Playgroud)
我在Google上搜索过,但似乎无法找到任何有关在内联中引用父表单的信息.
也许我必须以相反的方式做到这一点,并从父母内部访问内联?
def get_form(self, ***):
if self.instance:
for inline in self.inlines:
if instanceof(inline, MyInline):
inline.field_name.choices = ...
Run Code Online (Sandbox Code Playgroud)
以上任何一种都可能吗?