I have these models:
class Entity(models.Model):
name=models.CharField(max_length=100)
class Theme(models.Model):
name=models.CharField(max_length=100)
entity=models.OneToOneField(Entity)
class Company(models.Model):
name=models.CharField(max_length=100)
theme=models.OneToOneField(Theme,null=True,blank=True)
I want to filter the theme field when adding a Company in the admin, something like this:
class CompanyAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(CompanyAdmin, self).queryset(request)
qs.theme.queryset = Theme.objects.filter(name__iexact='company')
return qs
admin.site.register(Company, CompanyAdmin)
I’ve tried many things, but nothing worked! How can I do this?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Use the render_change_form method:
class CompanyAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, *args, **kwargs):
context['adminform'].form.fields['theme'].queryset = Theme.objects.filter(name__iexact='company')
return super(CompanyAdmin, self).render_change_form(request, context, *args, **kwargs)
Method 2
I actually prefer to do it in get_form like so:
Django < 2:
class CompanyAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(CompanyAdmin, self).get_form(request, obj, **kwargs)
form.fields['theme'].queryset = Theme.objects.filter(name__iexact='company')
return form
Django >= 2
class CompanyAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(CompanyAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['theme'].queryset = Theme.objects.filter(name__iexact='company')
return form
Method 3
look here http://books.agiliq.com/projects/django-admin-cookbook/en/latest/filter_fk_dropdown.html
@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):
...
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "category":
kwargs["queryset"] = Category.objects.filter(name__in=['God', 'Demi God'])
return super().formfield_for_foreignkey(db_field, request, **kwargs)
Method 4
In Django 3 it is easy :
class CompanyAdmin(admin.ModelAdmin):
list_display = ('name','theme')
list_filter = ('theme__name',)
admin.site.register(Company,CompanyAdmin)
This will show you a filter on the right of your screen with the list of your theme’s name.
Method 5
Another option is to create a custom model form where the queryset attribute of the theme field will be fine tuned to meet your needs.
class CompanyForm(ModelForm):
class Meta:
model = CompanyForm
fields = __all__ # or a tuple of fields
def __init__(self, *args, **kwargs):
super(CompanyForm, self).__init__(*args, **kwargs)
if self.instance: # Editing and existing instance
self.fields['theme'].queryset = Theme.objects.filter(name__iexact='company')
This model form can be also reused outside of the django admin area.
Method 6
I faced with the need to add filter to the foreignKey queryset of the parent ModelAdmin class (which all other ModelAdmins inherit from), that is, I can’t know exactly which model I need, this is my solution: db_field.related_model.objects.filter()
class TSModelAdmin(admin.ModelAdmin):
exclude = ('site',)
...
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.related_model:
kwargs["queryset"] =
db_field.related_model.objects.filter(site=request.user.user_profile.site)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
used django version 2.2.10
Method 7
A bit unrelated, but similar to this so I’ll post this here.
I was looking for a way to remove the NULL choice selection on a ModelForm foreignkey field. I first thought I could filter the queryset as is done in other answers here, but that didn’t work.
I found that I can filter the entry where the pk value is NULL like this in the get_form method:
class CompanyAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
# remove null choice
form.base_fields["theme"].choices = ((pk, display) for pk, display in form.base_fields["theme"].choices if pk)
return form
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0