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=dict(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.