Reputation: 10454
I have some chained foreign key relationships like this:
class Continent(models.Model):
continent = models.CharField(max_length=30)
class Country(models.Model):
country = models.CharField(max_length=30)
continent = models.ForeignKey(Continent)
class City(models.Model):
city = models.CharField(max_length=30)
country = models.ForeignKey(Country)
class Person(models.Model):
name = models.CharField(max_length=30)
continent = models.ForeignKey(Continent)
country = models.ForeignKey(Country)
city = models.ForeignKey(City)
and in the person admin create new item view, I want the lists of countries and cities to be changed based on what continent is selected, etc. I tried LinkedSelect of django suit but I think that is not meant for this. I read a bit about django select2 but I don't see any support for that. Any ideas whether there is a package that can help?
update: I came across this
which suggests django smart selects. I tried it. There are 2 problems: - it requires you to modify the model so that's a red sign. - it shows the list in a form of categories, but it still allows you to select the wrong item which is not desirable. (show_all does not work for the GroupedForeignKey)
I have a great idea. Since I want to use autocompletion using django-autocomplete-light, if I can add an event handler that says when you select the first list, then modify the autocomplete url of the second list to pass in an additional parameter, then the whole chain will work. The thing I'm stuck at is that when I change the url (data-autocomplete-light-url), it is not taking effect. I don't know how to trigger it to reload.
Upvotes: 3
Views: 778
Reputation: 34942
Fortunately, this is actually part of django-autocomplete-light.
You will have to create your own form (if not already done):
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = ('__all__')
widgets = {
'country': autocomplete.ModelSelect2(url='country-autocomplete'
forward=['continent']),
'city': autocomplete.ModelSelect2(url='city-autocomplete'
forward=['country']),
}
Update your autocompletes:
class CountryAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.is_authenticated():
return Country.objects.none()
qs = Country.objects.all()
continent = self.forwarded.get('continent', None)
if continent:
qs = qs.filter(continent=continent)
if self.q:
qs = qs.filter(country__istartswith=self.q)
return qs
class CityAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.is_authenticated():
return City.objects.none()
qs = City.objects.all()
country = self.forwarded.get('country', None)
if country:
qs = qs.filter(country=country)
if self.q:
qs = qs.filter(city__istartswith=self.q)
return qs
And use the new form in your ModelAdmin:
class PersonAdmin(admin.ModelAdmin):
form = PersonForm
Upvotes: 1