如何仅在django中将外键选择限制为相关对象 [英] How do I restrict foreign keys choices to related objects only in django

查看:110
本文介绍了如何仅在django中将外键选择限制为相关对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类似于以下的双向对外关系

  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)

如何将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})

,但这会导致管理界面没有列出任何孩子。

解决方案

发现了 ForeignKey.limit_choices_to 在Django文档中。
不知道这是如何工作的,但这可能是正确的。



更新: ForeignKey.limit_choices_to允许指定常数,可调用或Q对象以限制密钥的允许选择。一个常数显然在这里没有用处,因为它对于所涉及的对象一无所知。



使用可调用(函数或类方法或任何可调用对象)似乎更有希望。问题仍然是如何从HttpRequest对象访问必要的信息。使用线程本地存储可能是一个解决方案。



2。更新:这是为我工作的:



我创建了一个中间件,如上面的链接所述。它从请求的GET部分中提取一个或多个参数,例如product = 1,并将此信息存储在线程本地。



接下来有一个类方法读取线程局部变量并返回ids列表以限制外键字段选择的模型。

  @classmethod 
def _product_list(cls):

返回包含请求URL中包含的一个product_id的列表,
或包含所有有效product_ids的查询,如果不存在id URL

用于限制与当前产品相关的外键对象的选择

id = threadlocals.get_current_product()
如果id为不是没有:
return [id]
else:
return Product.objects.all()。values('pk')。query
/ pre>

重要的是返回一个包含所有可能的ids的查询,如果没有选择,那么普通的管理页面可以正常工作。



然后将外键字段声明为:

  product = models.ForeignKey(
产品,
limit_choices_to = {
id__in = BaseModel._product_list,
},

捕获是您必须提供信息以通过请求限制选择。我没有办法在这里访问自我。


I have a two way foreign relation similar to the following

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)

How do I restrict the choices for Parent.favoritechild to only children whose parent is itself? I tried

class Parent(models.Model):
  name = models.CharField(max_length=255)
  favoritechild = models.ForeignKey("Child", blank=True, null=True, limit_choices_to = {"myparent": "self"})

but that causes the admin interface to not list any children.

解决方案

I just came across ForeignKey.limit_choices_to in the Django docs. Not sure yet how this works, but it might just be the right think here.

Update: ForeignKey.limit_choices_to allows to specify either a constant, a callable or a Q object to restrict the allowable choices for the key. A constant obviously is no use here, since it knows nothing about the objects involved.

Using a callable (function or class method or any callable object) seem more promising. The problem remains how to access the necessary information form the HttpRequest object. Using thread local storage may be a solution.

2. Update: Here is what hast worked for me:

I created a middle ware as described in the link above. It extracts one or more arguments from the request's GET part, such as "product=1" and stores this information in the thread locals.

Next there is a class method in the model that reads the thread local variable and returns a list of ids to limit the choice of a foreign key field.

@classmethod
def _product_list(cls):
    """
    return a list containing the one product_id contained in the request URL,
    or a query containing all valid product_ids if not id present in URL

    used to limit the choice of foreign key object to those related to the current product
    """
    id = threadlocals.get_current_product()
    if id is not None:
        return [id]
    else:
        return Product.objects.all().values('pk').query

It is important to return a query containing all possible ids if none was selected so the normal admin pages work ok.

The foreign key field is then declared as:

product = models.ForeignKey(
    Product,
    limit_choices_to={
        id__in=BaseModel._product_list,
    },
)

The catch is that you have to provide the information to restrict the choices via the request. I don't see a way to access "self" here.

这篇关于如何仅在django中将外键选择限制为相关对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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