我希望根据formset工厂中的其他选择进行选择 但是AJAX异步请求仅适用于第一个表单集。
每次用户添加大学时,我都希望动态地使用选区填写选区(不是所有的选区,而是仅属于所选大学的选区。
这是我的代码 models.py
class universite (models.Model):
gouvernorat= models.CharField(max_length=250)
universite = models.CharField(max_length=250)
class Meta:
unique_together = ('gouvernorat', 'universite')
def __str__(self):
return self.universite
class etablissement(models.Model):
etablissement = models.CharField(max_length=250)
univ = models.ForeignKey(universite,related_name='etab_universites')
def __str__(self):
return "{} de l'université {}".format(self.etablissement,self.univ)
class session(models.Model):
annee_session = models.CharField(max_length=4)
active= models.BooleanField(default=True)
def __str__(self):
return self.annee_session
class choix(models.Model):
demandeur = models.ForeignKey(Profile, related_name='profile_choice')
session = models.ForeignKey(session, related_name='session_choice')
universite_demande = models.CharField(max_length=250)
etablissement_demande = models.CharField(max_length=250)
class Meta:
unique_together = ('demandeur', 'session','etablissement_demande')
def __str__(self):
return '{} pour session {} choix {}'.format(self.demandeur.user.username,self.session.annee_session,self.etablissement_demande.etablissement)
forms.py
class univForm(forms.Form):
universite = forms.ModelChoiceField(label='Choix de la university', queryset=universite.objects.all().distinct(),required=True)
class BaseLinkFormSet(BaseFormSet):
def clean(self):
if any(self.errors):
return
universites = []
etablissements = []
duplicates = False
for form in self.forms:
if form.cleaned_data:
universite = form.cleaned_data['universite']
etablissement= form.cleaned_data['etablissement']
if universite and etablissement:
if etablissement in etablissements:
duplicates = True
etablissements.append(etablissement)
if duplicates:
raise forms.ValidationError(
'Veuillez ne pas répeter les établissements choisis.', code='duplicate_etablissements' )
if universite and not etablissement:
raise forms.ValidationError(
'Vous devez choisir pour chaque université un établissement.', code='missing_etablissement' )
elif etablissement and not universite:
raise forms.ValidationError(
'Vous devez choisir une université.',
code='missing_university'
)
class ChoixForm(forms.ModelForm):
session = forms.ModelChoiceField(label='Choix de la session', queryset=session.objects.all().filter(active = True).distinct())
class Meta:
model = choix
fields = ()
edit.html
{% extends "base.html" %}
{% load static %}
{% block content %}
{% include 'ajax_fct.html' %}
{% if user_form.errors %}
<div class="alert alert-danger">
{% for key,value in user_form.errors.items %}
<li>{{ key|escape }} : {{ value|escape }}</li>
{% endfor %}
</div>
{% endif %}
<form method="post">
{% csrf_token %}
{{ profile_form.as_p }}
{{ link_formset.management_form }}
{% for link_form in link_formset %}
<div class="link-formset">
{{ link_form.as_table }}
{% if link_form.anchor.errors %}
{% for error in link_form.anchor.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<p> <div id = "results"></div></p>
{% if link_form.etablissement.errors %}
{% for error in link_form.etablissement.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
{% if link_formset.non_form_errors %}
{% for error in link_formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<p> <input type="submit" class="btn btn-success" value="Valider choix"></p>
<script>
$('.link-formset').formset({
addText: 'Ajouter choix',
deleteText: 'Supprimer choix'
});
</script>
{% endblock %}
ajax_fct.html
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#id_form-0-universite" ).change(function () {
var e = document.getElementById("id_form-0-universite");
var value = e.options[e.selectedIndex].value;
$.ajax({
url: "/demande/fajax",
type: "POST", // or "get".
dataType: "json",
data: { the_post : value },
success: function(data) {
data.req = $.parseJSON(data.req);
var data_length = data.req.length;
for (var i = 0; i < data_length; i++) {
console.log(data.req[i]["fields"]["etablissement"] );
}
$('#results').empty();
$('#results').append('<p>');
$('#results').append('Choisir votre établissement: <select name = "etablissement" id ="etablissement" required><option value="">--- choisir établissement ---</option>');
for (var i = 0; i < data_length; i++) {
$('#etablissement').append('<option value="'+ data.req[i]["fields"] ["etablissement"] +'">'+ data.req[i]["fields"]["etablissement"] +'</option>');
}
$('#etablissement').append('</select></p>');
},
error : function(xhr,errmsg,err) {
$('#results').html("<div class='alert-box alert radius' data- alert>Erreur durant la requête asynchrone "+errmsg+
" <a href='#' class='close'>×</a></div>"); // add the error to the dom
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
})
})
</script>
view.py
@login_required
def test_profile_settings(request):
profile = request.user.profile
LinkFormSet = formset_factory(univForm, formset=BaseLinkFormSet)
bcl = choix.objects.all()
link_data = [{'universite': l.universite}
for l in bcl]
if request.method == 'POST':
profile_form = ChoixForm(request.POST, demandeur=profile,session=request.POST['session'])
link_formset = LinkFormSet(request.POST)
if profile_form.is_valid() and link_formset.is_valid():
new_links = []
for link_form in link_formset:
universite = link_form.cleaned_data.get('universite')
etablissement= link_form.cleaned_data.get('etablissement')
if universite and etablissement:
new_links.append(choix(demandeur = profile,session=session, universite=universite, etablissement=etablissement))
try:
with transaction.atomic():
# Replace the old with the new
choix.objects.filter(demandeur = profile).delete()
choix.objects.bulk_create(new_links)
# And notify our users that it worked
messages.success(request, 'You have updated your profile.')
return redirect(reverse('blog:post_list'))
except IntegrityError: # If the transaction failed
messages.error(request, 'There was an error saving your profile.')
return redirect(reverse('blog:post_list'))
else:
profile_form = ChoixForm()
link_formset = LinkFormSet(initial=link_data)
context = {
'profile_form': ChoixForm,
'link_formset': link_formset,
}
return render(request, 'edit_profile.html', context)
def fajax(request):
if request.is_ajax() and request.POST:
argument = request.POST.get('the_post')
auto_type = etablissement.objects.filter(univ__id=argument)
response_data = {}
response_data['req'] = serializers.serialize('json', auto_type, fields=('etablissement'))
return JsonResponse(response_data)
else:
return JsonResponse('Erreur innattendu')