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?
ForeignKey is a Django ORM field-to-column mapping for creating and working with relationships between tables in relational databases.
Nope. Django filters operate at the database level, generating SQL. To filter based on Python properties, you have to load the object into Python to evaluate the property--and at that point, you've already done all the work to load it.
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)
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
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)
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With