How do you limit what choices are shown for ForeignKey
fields in Django's admin when they're displayed using the raw_id_fields option?
When rendered as a select box, it's simple to define a custom ModelForm
to set that field's queryset value with the choices to want. However, this queryset appears to be completely ignored when rendered using raw_id_fields
. It generates a link to that ForeignKey
's model, allowing you to select any record from that model via a popup window. You can still filter these values by customizing the URL, but I can't find a way to do this via a ModelAdmin
.
I use similar to FSp approach in my Django 1.8 / Python 3.4 project:
from django.contrib import admin
from django.contrib.admin import widgets
from django.contrib.admin.sites import site
from django import forms
class BlogRawIdWidget(widgets.ForeignKeyRawIdWidget):
def url_parameters(self):
res = super().url_parameters()
res['type__exact'] = 'PROJ'
return res
class ProjectAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['blog'].queryset = Blog.objects.filter(type='PROJ')
self.fields['blog'].widget = BlogRawIdWidget(rel=Project._meta.get_field('blog').remote_field, admin_site=site)
class Meta:
# Django 1.8 convenience:
fields = '__all__'
model = Project
class ProjectAdmin(admin.ModelAdmin):
form = ProjectAdminForm
raw_id_fields = ('blog',)
to select only blog.type == 'PROJ'
as foreign key Project.blog
in django.admin
. Because end-users may and will to select anything, unfortunately.
The method below works for me but it is a queryset that affects every admin that needs to use the Customer model. But if you have another Admin, e.g. Invoice that requires a different queryset, you might want to experiment a bit with model proxy.
Model
class Customer(models.Model):
name = models.CharField(max_length=100)
is_active = models.BooleanField()
class Order(models.Model):
cust = models.ForeignKey(Customer)
Admin
class CustomerAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(CustomerAdmin, self).queryset(request)
return qs.filter(is_active=1)
class OrderAdmin():
raw_id_fields = ('cust', )
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