我正在编程一个显示事件的网站。每次发生的事件都是其自己的对象。由于许多事件都是重复性的,重新输入所有内容并更改日期很繁琐,因此我添加了一个事件发生器,以便用户可以设置名称,位置和时间,然后为它们选择一堆日期。使用这些属性可以生成哪些事件。
我已将事件发生器的表单集成到事件的管理页面的更改视图中。即使遇到了很多有害的类型错误和与类型相关的崩溃,我什至设法使其正常工作。 (我真的希望Django有类型提示。)
但是,如果提交的出现生成器表单无效,则Django无法正确显示更改视图。它因验证错误['ManagementForm data is missing or has been tampered with']
而崩溃。我尝试查看痕迹,但无法弄清楚是什么原因造成的。我只是将无效表单传递为extra_context
,以使页面向用户显示错误。
admin.py
class EventAdmin(admin.ModelAdmin):
inlines = [OccurrenceInline]
change_form_template = "admin/event_change_form.html"
def change_view(self, request, object_id, form_url="", extra_context={}):
extra_context["generator_form"] = extra_context.get(
"generator_form",
OccurrenceGeneratorForm(initial={"event": Event.objects.get(pk=object_id)}),
)
return super().change_view(request, object_id, form_url, extra_context)
def get_urls(self):
urls = super().get_urls()
extra_urls = [path("<path:object_id>/generator/", self.generator_view)]
return extra_urls + urls
def generator_view(self, request, object_id, *args, **kwargs):
if request.method == "POST":
form = OccurrenceGeneratorForm(request.POST)
if form.is_valid():
self.generate_occurrences(form.cleaned_data)
else:
extra_context = {"generator_form": form}
return self.change_view(request, object_id, extra_context=extra_context)
return self.change_view(request, object_id)
def generate_occurrences(self, data):
Occurrence.objects.bulk_create(
[
Occurrence(
event=data["event"],
location=data["location"],
start_date=date,
start_time=data["start_time"],
duration_in_minutes=data["duration_in_minutes"],
)
for date in data["dates"]
]
)
该模板是标准更改视图模板的复制粘贴,底部添加了我的自定义出现生成器表单。
templates/admin/event_change_form.html
{% extends "admin/change_form.html" %}
{% load i18n admin_urls static admin_modify %}
{% block content %}<div id="content-main">
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_form_object_tools %}
{% endblock %}
</ul>
{% endif %}{% endif %}
{% endblock %}
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post"
id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
<div>
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
{% if errors %}
<p class="errornote">
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
</p>
{{ adminform.form.non_field_errors }}
{% endif %}
{% block field_sets %}
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
{% endblock %}
{% block after_field_sets %}{% endblock %}
{% block inline_field_sets %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
{% endblock %}
{% block after_related_objects %}{% endblock %}
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
{% block admin_change_form_document_ready %}
<script type="text/javascript" id="django-admin-form-add-constants"
src="{% static 'admin/js/change_form.js' %}" {% if adminform and add %}
data-model-name="{{ opts.model_name }}" {% endif %}>
</script>
{% endblock %}
{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}
</div>
</form>
<details style="margin-bottom: 30px; padding: 10px; border: 1px solid lightgray;">
<summary>
<h2 style="display: inline;">Occurrence Generator</h2>
</summary>
<div id="occurrence-generator" style="margin-top: 10px;">
{{ generator_form.media }}
<form method="post" action="../generator/">{% csrf_token %}
{{ generator_form.as_p }}
<input type="submit" value="Generator occurrences">
</form>
</div>
</details>
</div>
{% endblock %}
这里是否有明显的地方我做错了?我真的不知道表单通常来自何处以及如何获取或提供表单。