在使用jQuery更新文本输入后,如何使用不同的QuerySet更改ModelChoiceField?

在使用jQuery更新文本输入后,如何使用不同的QuerySet更改ModelChoiceField?,jquery,django,Jquery,Django,我有一个django报告表,基本上与这里的一样: class EntryForm(ModelForm): year = forms.IntegerField() month = forms.ModelChoiceField(queryset = ... ) report_category = form.ModelChoiceField(queryset = ... ) # FKey to some category model report_text = form

我有一个django报告表,基本上与这里的一样:

class EntryForm(ModelForm):
    year = forms.IntegerField()
    month = forms.ModelChoiceField(queryset = ... )
    report_category = form.ModelChoiceField(queryset = ... ) # FKey to some category model
    report_text = forms.CharField()
最初,用户将在文本输入框中键入年值,选择月,然后选择类别并键入报告

现在,我希望在月份下拉列表中填充尚未报告的月份列表。2014年1月报告提交后,下一次在2014年输入用户类型时,下拉列表将只填充11个月(减去1月)


我知道如何完成查询集,但在文本输入失去焦点后,我仍然不知道如何使jQuery/AJAX成为更改下拉列表的一部分。

下面是一个工作示例:

models.py forms.py url.py views.py index.html
现在,如果我访问页面
http://127.0.0.1:8000/so_23711764/
(django开发服务器),我得到:

使用此entrymodel表:

如果我输入2014年,当控件失去焦点时,我得到:

希望有帮助:)

from django.db import models
#min and max values for integer fields
from django.core.validators import MinValueValidator, MaxValueValidator

class CategoryModel(models.Model):
    category = models.CharField(max_length=20, unique=True)

    def __unicode__(self):
        return u"%s" % self.category


class EntryModel(models.Model):
    year = models.IntegerField(validators=[MinValueValidator(1900), MaxValueValidator(2100)])
    month = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(12)])
    report_category = models.ForeignKey(CategoryModel, blank=True, null=True, on_delete=models.SET_NULL)
    report_text = models.CharField(max_length=100, blank=True, null=True, default=None)
from django import forms
from models import CategoryModel, EntryModel


class EntryForm(forms.ModelForm):
    months = (
        ('1','January'),
        ('2','February'),
        ('3','March'),
        ('4','April'),
        ('5','May'),
        ('6','June'),
        ('7','July'),
        ('8','August'),
        ('9','September'),
        ('10','October'),
        ('11','November'),
        ('12','December'),
    )

    month = forms.ChoiceField(choices=months)
    #hidden control used to populate the month drop down list
    month_hidden=forms.ChoiceField(choices=months)
    report_category = forms.ModelChoiceField(queryset = CategoryModel.objects.all())

    class Meta:
        model=EntryModel
from django.conf.urls import patterns, url
from views import EntryCreateView


urlpatterns=patterns('so_23711764.views',
    url(r'^/?$', EntryCreateView.as_view(), name='display_entry'),
    url(r'^reload_controls.html$', 'reload_controls_view', name='reload_controls'),

)
# Create your views here.
from django.views.generic.edit import CreateView
from models import EntryModel
from forms import EntryForm
#use json for the ajax request
from django.http import HttpResponse
from django.utils import simplejson


class EntryCreateView(CreateView):
    model = EntryModel
    form_class=EntryForm
    template_name = "so_23711764/index.html"
    #~ fields = ['name']

#view called with ajax to reload the month drop down list
def reload_controls_view(request):
    context={}
    #get the year that the user has typed
    year=request.POST["year"]
    #get months without reports (months to be displayed in the drop down list)
    context["months_to_display"]=list(EntryModel.objects.filter(year=year, report_category__isnull=True).values_list('month', flat=True).distinct())

    return HttpResponse(simplejson.dumps(context), mimetype="application/json")
<!-- css of the application -->
<link rel="stylesheet" href="{{STATIC_URL}}css/so_23711764.css?{% now 'U' %}" />

<form id="entry_form" method="post" action="{% url display_entry %}">
    {% csrf_token %}

    {{ form.as_p }}

    <!-- in urls.py, set the path to the view reload_controls -->
    <div id="reload_controls_view" style="display: none;">{% url reload_controls %}</div>
</form>


<!-- jquery -->
<script type="text/javascript" src="{{ STATIC_URL }}jquery.min.js"></script>
<!-- csrf file to avoid 403 (FORBIDDEN) on ajax views -->
<script type="text/javascript" src="{{ STATIC_URL }}csrf.js"></script>
<!-- js related to the application -->
<script type="text/javascript" src="{{ STATIC_URL }}js/so_23711764.js?{% now 'U' %}"></script>
/* bind the event to the form, so it still works after controls are reloaded with ajax */
$('#entry_form').on('blur', '#id_year', function()
{
    reload_controls(this.value);
});


/* update the month drop down list with ajax */
function reload_controls(year)
{
    $.ajax
    ({
        type: 'POST',
        url: $("#reload_controls_view").text(),
        dataType: 'json',
        data: "year="+year,
        success: function(result)
        {
            //empty month drop down list
            $("#id_month").empty()

            //add months with no report
            $.each( result.months_to_display, function( index, value )
            {
                //use the hidden drop down list to populate the month field
                month=$("#id_month_hidden option[value='" + value + "']").text()
                //add months to the drop down list
                $('#id_month').append('<option value="'+value+'">'+month+'</option>')
            });
        },
        error: function(xhr, status, error) 
        {
            window.console&&console.log(xhr.responseText);
        }
    });
}
/* hide month_hidden control */
#id_month_hidden, label[for="id_month_hidden"]
{
    display: none;
}