pythondjangodjango-templatesmodelchoicefield

How do I set a foreignkey field in Django models to return no values?


I have a Django model like:

class hotel(models.Model):
   name = models.CharField(max_length=60)
   city = models.ForeignKey('city', on_delete=models.DO_NOTHING)
   state = models.ForeignKey('state', on_delete=models.DO_NOTHING)
   country = models.ForeignKey('country', on_delete=models.DO_NOTHING)
   def __str__(self):
       return self.name
   class Meta:
       verbose_name_plural = "hotels"

class city(models.Model):
   name = models.CharField(max_length=60)
   state = models.ForeignKey('state', on_delete=models.DO_NOTHING)
   def __str__(self):
       return self.name
   class Meta:
       verbose_name_plural = "cities"

class state(models.Model):
   name = models.CharField(max_length=60)
   country = models.ForeignKey('country', on_delete=models.DO_NOTHING)
   def __str__(self):
       return self.name
   class Meta:
       verbose_name_plural = "states"

class country(models.Model):
   name = models.CharField(max_length=60)
   code = models.CharField(max_length=160)
   def __str__(self):
       return self.name
   class Meta:
       verbose_name_plural = "countries"

And the ModelForm like:


class Hotel(ModelForm):
    class Meta:
        model = hotel
        fields = '__all__'

[EDIT] When creating form object from Hotel ModelForm, Django automatically fills values of foreignkey fields. I want to stop that.

For example:

form = Hotel() (Django auto-populates city, state and country values)

I want my Django template to return all country values in dropdown, but not for state and city dropdowns (so I want state and city dropdowns to remain empty in Django template). How can I do that?

PS - The purpose to do this is to load country values first, and as per the user selection of a country, I will load state and then cities accordingly.


Solution

  • You can override the choices either in the form __init__ method or you can use a little trick with setting choices just after the field has been defined

    class Hotel(ModelForm):
    
        class Meta:
            model = hotel
            fields = '__all__'
    
        # Like this
        state = forms.ModelChoiceField(state.objects.all())
        state.choices = []
        city = forms.ModelChoiceField(city.objects.all())
        city.choices = []
    
        # Or like this...
        def __init__(self, data=None, *args, **kwargs):
            super().__init__(data=data, *args, **kwargs)
            if not data:
                self.fields['state'].queryset = state.objects.none()
                self.fields['city'].queryset = state.objects.none()