I want to create a client, with country, province, city selected based on 3 different models :
class Country(models.Model):
Country = models.CharField(max_length=100, unique=True)
def __str__(self):
return self.Country
class Province(models.Model):
province = models.CharField(max_length=100, unique=True)
Country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='province', null=True)
def __str__(self):
return self.province
class City(models.Model):
city = models.CharField(max_length=100, unique=True)
Province = models.ForeignKey(Province, on_delete=models.CASCADE, related_name='city', null=True)
def __str__(self):
return self.city
When the user selects a country, province list is updated with country's province and same thing for cities.
I create urls for that and code in my views.py:
class GetProvincesView(View):
def get(self, request, *args, **kwargs):
country_id = request.GET.get('country_id')
provinces = Province.objects.filter(Country_id=country_id)
data = [{'id': province.id, 'name': province.province} for province in provinces]
return JsonResponse(data, safe=False)
class GetCitiesView(View):
def get(self, request, *args, **kwargs):
province_id = request.GET.get('province_id')
cities = City.objects.filter(Province_id=province_id)
data = [{'id': city.id, 'name': city.city} for city in cities]
return JsonResponse(data, safe=False)
My template is:
<!DOCTYPE html>
<html lang="fr">
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h2>Ajouter un client</h2>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Enregistrer</button>
</form>
{% endblock %}
{% block scripts %}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
$(document).ready(function() {
console.log('Document ready');
// Code pour filtrer les provinces en fonction du pays sélectionné
$("#id_adresse_country").change(function() {
console.log('Country changed');
var country_id = $(this).val();
if (country_id) {
axios.get("{% url 'get_provinces' %}", {params: {"country_id": country_id}})
.then(function(response) {
$("#id_adresse_province").html(response.data);
$("#id_adresse_city").html("<option value=''>---------</option>");
})
.catch(function(error) {
console.log(error);
});
debugger;
} else {
$("#id_adresse_province").html("<option value=''>---------</option>");
$("#id_adresse_city").html("<option value=''>---------</option>");
}
});
// Code pour filtrer les villes en fonction de la province sélectionnée
$("#id_adresse_province").change(function() {
console.log('Province changed');
var province_id = $(this).val();
if (province_id) {
axios.get("{% url 'get_cities' %}", {params: {"province_id": province_id}})
.then(function(response) {
$("#id_adresse_city").html(response.data);
})
.catch(function(error) {
console.log(error);
});
} else {
$("#id_adresse_city").html("<option value=''>---------</option>");
}
});
});
</script>
{% endblock %}
my client model:
class Client(models.Model):
nom = models.CharField(max_length=100)
email = models.EmailField()
telephone = models.CharField(max_length=20, validators=[
RegexValidator(
regex=r'^\+?[0-9]{9,15}$',
message='Le numéro de téléphone doit être au format international (par exemple +33612345678)',
)])
adresse_country = models.ForeignKey(Country, on_delete=models.CASCADE)
adresse_province = models.ForeignKey(Province, on_delete=models.CASCADE)
adresse_city = models.ForeignKey(City, on_delete=models.CASCADE)
adresse_zip = models.CharField(max_length=200)
adresse_street = models.CharField(max_length=200)
status = models.ForeignKey(ClientStatus, on_delete=models.CASCADE, related_name='clients',default=1)
category = models.ForeignKey(ClientCategory, on_delete=models.CASCADE, related_name='clients', null=True)
tax_group = models.ForeignKey(Tax, on_delete=models.CASCADE, related_name='clients', null=True)
payment_term = models.ForeignKey(PaymentTerm, on_delete=models.CASCADE, related_name='clients', null=True)
my form:
class ClientForm(forms.ModelForm):
# afin de trier et selectionner un champ selon la 1ere lettre du mot
adresse_province = forms.ModelChoiceField(queryset=Province.objects.order_by('province'),
empty_label="Sélectionnez une province")
adresse_country = forms.ModelChoiceField(queryset=Country.objects.order_by('Country'),
empty_label="Sélectionnez un pays")
adresse_city = forms.ModelChoiceField(queryset=City.objects.order_by('city'), empty_label="Sélectionnez une ville")
# ne pas rendre obligatoire la saisie
email = forms.EmailField(required=False)
telephone = forms.CharField(required=False)
class Meta:
model = Client
fields = ['nom', 'email', 'telephone','adresse_country', 'adresse_province', 'adresse_street', 'adresse_city', 'adresse_zip',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.layout = Layout(
Row(
Column('nom', css_class='form-group col-md-6 mb-0'),
Column('email', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
Row(
Column('telephone', css_class='form-group col-md-6 mb-0'),
Column('adresse_street', css_class='form-group col-md-6 mb-0'),
css_class='form-row'
),
Row(
Column('adresse_city', css_class='form-group col-md-4 mb-0'),
Column('adresse_zip', css_class='form-group col-md-4 mb-0'),
),
Row(
Column('adresse_province', css_class='form-group col-md-4 mb-0'),
Column('adresse_country', css_class='form-group col-md-4 mb-0'),
css_class='form-row'
),
Submit('submit', 'Enregistrer')
)
self.fields['adresse_province'].widget.attrs.update(
{'class': 'form-control select2', 'data-minimum-input-length': '2'})
self.fields['adresse_country'].widget.attrs.update(
{'class': 'form-control select2', 'data-minimum-input-length': '2'})
self.fields['adresse_city'].widget.attrs.update(
{'class': 'form-control select2', 'data-minimum-input-length': '2'})
My issue is when I select a country, nothing changes in my province field. I look a the console and put console.logs in my code but no log appears in chrome tools...
I'm using Cookiecutter. Does the standard base.html should make my script not working in my page ?
I find out the issue I think. As Base.html already define blocks for javascript:
{% block inline_javascript %}
{% comment %}
Script tags with only code, no src (defer by default). To run
with a "defer" so that you run inline code:
<script>
window.addEventListener('DOMContentLoaded', () => {/* Run whatever you want */});
</script>
{% endcomment %}
{% endblock inline_javascript %}
I m trying to replace {% block scripts %} by {% block inline_javascript %} in my code. Now I've an error that means that my javascript is running.. I've another issue but I will try to solve it :-) (it is a code issue in my javascript)