我正在尝试创建一个表单,其中当从下拉菜单中选择另一个字段title
时,会预先填充某个字段checkin_type
。我正在尝试遵循Django: How to pre-populate FormView with dynamic (non-model) data?中概述的方法,并在此处设置了“概念验证”项目:https://github.com/khpeek/django-dynamic-form。
在视图的模板中,我已经这样做了,当checkin_type
字段有.change()
时,会发送一个AJAX POST请求,其中包含所选签入的id
类型:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
<script>
$(document).ready(function(){
var csrftoken = Cookies.get('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$(".auto-submit").change(function() {
$.post({
url: "{% url 'checkin-create' %}",
data: {id: $(".auto-submit option:selected").val()}
})
});
});
</script>
<form action="" method="post">{% csrf_token %}
{% for field in form %}
<div class="{% if field.name == 'checkin_type' %}auto-submit{% endif %}">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<input type="submit" value="Send message" />
</form>
在views.py
中,我尝试了以下内容:
import logging
import sys
from django.views import generic
from .models import CheckIn, CheckInType
from django.http import HttpResponse
def get_stdout_logger(name, level):
logger = logging.getLogger(name)
logger.setLevel(level)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(level)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
logger = get_stdout_logger(__name__, level=logging.DEBUG)
class CheckInCreate(generic.CreateView):
model = CheckIn
fields = '__all__'
def post(self, request, *args, **kwargs):
if request.is_ajax():
logger.debug(f"Received AJAX POST request with the following request.POST data: {request.POST}")
self.checkin_type = CheckInType.objects.get(pk=request.POST['id'])
return super().post(request, *args, **kwargs)
def get_initial(self):
initial = super().get_initial()
if hasattr(self, 'checkin_type'):
initial.update(title=self.checkin_type.title)
logger.debug(f"Getting initial: {initial}")
return initial
def form_valid(self, *args, **kwargs):
logger.debug("The form is valid!")
return super().form_valid(*args, **kwargs)
def form_invalid(self, form):
logger.debug("The form is invalid!")
if hasattr(self, 'checkin_type'):
form['title'].initial = self.checkin_type.title
logger.debug(f"The form's initial title is now {form['title'].initial}")
return super().form_invalid(form)
现在,如果我python manage.py runserver
,请导航至localhost:8000/checkins/new
,然后从checkin_type
下拉菜单中选择一个选项,我会看到预期的记录结果:
System check identified no issues (0 silenced).
March 01, 2018 - 21:02:14
Django version 2.0.1, using settings 'my_project.settings'
Starting development server at http://127.0.0.1:9000/
Quit the server with CONTROL-C.
2018-03-01 21:02:18,595 - dashboard.views - DEBUG - Getting initial: {}
[01/Mar/2018 21:02:18] "GET /checkins/new HTTP/1.1" 200 2200
2018-03-01 21:02:26,015 - dashboard.views - DEBUG - Received AJAX POST request with the following request.POST data: <QueryDict: {'id': ['2']}>
2018-03-01 21:02:26,018 - dashboard.views - DEBUG - Getting initial: {'title': '2-week check-in'}
2018-03-01 21:02:26,018 - dashboard.views - DEBUG - The form is invalid!
2018-03-01 21:02:26,018 - dashboard.views - DEBUG - The form's initial title is now 2-week check-in
[01/Mar/2018 21:02:26] "POST /checkins/new HTTP/1.1" 200 2259
但是,我没有看到表格中的变化!调用super().form_invalid(form)
是否应该重新呈现修改后的表单?