19👍
To filter the choices available for a foreign key field in an admin inline, I override the form so that I can update the form field’s queryset
attribute. That way you have access to self.instance
which is the object being edited in the form. So something like this:
class ProjectGroupMembershipInlineForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['group'].queryset = Group.objects.filter(
some_filtering_here=self.instance
)
You don’t need to use formfield_for_foreignkey
if you do the above and it should accomplish what you described.
26👍
Another way, that, IMHO, feels cleaner than, but is similar to @erichonkanen’s answer is something like this:
class ProjectGroupMembershipInline(admin.StackedInline):
# irrelevant bits....
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "group":
try:
parent_id = request.resolver_match.args[0]
kwargs["queryset"] = Group.objects.filter(some_column=parent_id)
except IndexError:
pass
return super().formfield_for_foreignkey(db_field, request, **kwargs)
- [Django]-How to unit test file upload in django
- [Django]-Paginate relationship in Django REST Framework?
- [Django]-How to use curl with Django, csrf tokens and POST requests
13👍
The answer provided by @mkoistinen is great but django stores parent id in kwargs and not args so it would be correct to extract it like this.
parent_id = request.resolver_match.kwargs.get('object_id')
- [Django]-Can't find msguniq. Make sure you have GNU gettext tools 0.15 or newer installed. (Django 1.8 and OSX ElCapitan)
- [Django]-Default image for ImageField in Django's ORM
- [Django]-How to filter (or replace) unicode characters that would take more than 3 bytes in UTF-8?
7👍
I was able to solve it by using the formfield_for_foreignkey and stripping the object ID from the url. It’s not the sexiest way to get the ID but Django doesn’t provide access to the object ID on the admin object yet (it should).
class ObjectAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
obj_id = request.META['PATH_INFO'].rstrip('/').split('/')[-1]
if db_field.name == 'my_field' and obj_id.isdigit():
obj = self.get_object(request, obj_id)
if obj:
kwargs['queryset'] = models.Object.objects.filter(field=obj)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
- [Django]-How to customize default auth login form in Django?
- [Django]-Temporarily disable auto_now / auto_now_add
- [Django]-Django fix Admin plural
4👍
This is the solution I came up with, which seems pretty clean
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "group":
parent_id = request.resolver_match.kwargs['object_id']
kwargs["queryset"] = Group.objects.filter(some_column=parent_id)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
- [Django]-Can you perform multi-threaded tasks within Django?
- [Django]-Python format datetime with "st", "nd", "rd", "th" (english ordinal suffix) like PHP's "S"
- [Django]-How can I embed django csrf token straight into HTML?
0👍
If you are working with an older Django version, it may not yet support the resolver_match
attribute.
In that case i found following solution:
def formfield_for_foreignkey(self, db_field, request, *args, **kwargs):
field = super(ProjectGroupMembershipInline, self).formfield_for_foreignkey(db_field, request, *args, **kwargs)
if db_field.name == 'group':
resolved_url = resolve(request.path.replace('/{}/'.format(get_language()), '/')) # remove localisation of url
if resolved_url and resolved_url.args: # check we are not in changelist view
field.queryset = field.queryset.filter(pk=resolved_url.args[0])) # obj id first and only arg for view.
return field
- [Django]-Django: Want to display an empty field as blank rather displaying None
- [Django]-Python regex for integer?
- [Django]-How do you run a worker with AWS Elastic Beanstalk?