0

I have a simple form which lets a user select his country, state and district and redisplays the selected data.

Everything works as expected apart from the fact that what is displayed is not the "text" but "ids" of the selected data.

Expectation: You belong to India, Punjab, Jalandhar. Me too. ;)

Output: You belong to 1, 2, 4. Me too. ;)

# my form

class MyInfoForm(forms.Form):
country = forms.ModelChoiceField(
    queryset=Country.objects.all(),
    widget=autocomplete.ListSelect2(
        url='country-autocomplete',
    )
)
state = forms.ModelChoiceField(
    queryset=State.objects.all(),
    widget=autocomplete.ListSelect2(
        url='state-autocomplete',
        forward=(forward.Field('country'),)
    )
)
district = forms.ModelChoiceField(
    queryset=District.objects.all(),
    widget=autocomplete.ListSelect2(
        url='district-autocomplete',
        forward=(forward.Field('state'),)
    )
)

# my view which handles MyInfoForm

class CountryView(FormView):
template_name = 'home.html'
form_class = MyInfoForm
success_url = '/thanks/'

def form_valid(self, form):
    print("Request :", self.request.POST)
    country = self.request.POST["country"]
    state = self.request.POST["state"]
    district = self.request.POST["district"]
    msg = "You belong to {country}, {state}, {district}. Me too. ;)".format(
        country=country, state=state, district=district)
    return HttpResponse(msg)


# other auto-complete views (similar to official tutorials)

class CountryAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
    # Don't forget to filter out results depending on the visitor !
    if not self.request.user.is_authenticated():
        return Country.objects.none()

    qs = Country.objects.all()

    if self.q:
        qs = qs.filter(country_name__istartswith=self.q)

    return qs


 class StateAutocomplete(autocomplete.Select2QuerySetView):
 def get_queryset(self):
    if not self.request.user.is_authenticated():
        return State.objects.none()

    qs = State.objects.all()

    country = self.forwarded.get('country', None)

    if country:
        qs = qs.filter(country_name=country)

    if self.q:
        qs = qs.filter(state_name__istartswith=self.q)

    return qs


class DistrictAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
    if not self.request.user.is_authenticated():
        return District.objects.none()

    qs = District.objects.all()

    state = self.forwarded.get('state', None)

    if state:
        qs = qs.filter(state_name=state)

    if self.q:
        qs = qs.filter(district_name__istartswith=self.q)

    return qs

 # models 

class Country(models.Model):
country_name = models.CharField(max_length=30)

def __str__(self):
    return self.country_name


class State(models.Model):
country_name = models.ForeignKey(Country)
state_name = models.CharField(max_length=30)

def __str__(self):
    return self.state_name


class District(models.Model):
state_name = models.ForeignKey(State)
district_name = models.CharField(max_length=30)

def __str__(self):
    return self.district_name

I applied what is mentioned in this SO answer but no gain. Applying this solution makes no option to populate in state and district.

inquilabee
  • 713
  • 1
  • 11
  • 23
  • try `get_country_display` in your template where you are displaying choices and in view add `()` like `get_country_display()` – Sumeet Kumar Jan 24 '18 at 18:36

1 Answers1

0

Just call the object, in your form valid. Autocomplete light is configured to return the ID which is the default behaviour of Select widgets.

def form_valid(self, form):)
    country_pk = self.request.POST["country"]
   state_pk = self.request.POST["state"]
   district_pk = self.request.POST["district"]
   country = Country.objects.get(pk = country_pk)
   #--- district
   #---- state
   #if you have defined a str method you can just proceed as
   #as below since the render will call __str__ else
   #you can use country.name, state.name, district.name
   msg = "You belong to {country}, {state}, {district}. Me too. 
   ;)".format(country=country, state=state, district=district)
unlockme
  • 3,897
  • 3
  • 28
  • 42