Я программирую сайт, который отображает события.Каждое возникновение события является его собственным объектом.Поскольку многие из событий повторяются и утомительно вводить все заново и просто изменять дату, я добавил генератор событий, чтобы пользователь мог задать имя, местоположение и время, а затем выбрать несколько дат длякакие вхождения могут быть сгенерированы с помощью этих свойств.
Я интегрировал форму для генератора вхождений в представление изменений на странице администратора события.Мне даже удалось заставить это работать, даже при том, что я столкнулся с большим количеством ошибок типа вредных и сбоев, связанных с типом.(Мне бы очень хотелось, чтобы у 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 %}
Есть ли что-то очевидное, что я здесь ошибся?Я действительно понятия не имею, откуда обычно берется форма и как я могу ее получить или предоставить.