Экземпляры тегов через django-taggit не отображаются так, как ожидается, в форме сообщения об обновлении
{{ form.tags | as_crispy_field }}
при получении экземпляра вопроса отображается не так, как ожидалось. Тот же синтаксис crispy forms работает и отображается идеально при создании начального поста
Нажатие кнопки Submit приводит к ошибке Server 500. Результаты тестирования задокументированы в строке:
<!-- templates/update_question.html -->
{% extends "base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block extra_head %}
<!-- django-quill-editor Media -->
{% include 'django_quill/media.html' %}
{% endblock %}
{% block content %}
<main class="flex-shrink-0 main-bg">
<div class="container-question my-5">
[...]
<form id="standards-form" method="post" action="{% url 'question_update' slug=question.slug %}">
{% csrf_token %}
[...]
<h2 class="text-center">Subject line</h2>
{{ form.subject | as_crispy_field }} <!-- rendering as expected-->
<br>
<h2 class="text-center">Details</h2>
{{ form.content | as_crispy_field }} <!-- rendering as expected-->
<br>
<h2 class="text-center">Tags</h2>
<div class="tag-input">
<div class="input">
<div>
<i class="fa fa-tags"></i>
{{ form.tags | as_crispy_field }} <!--not rendering as expected: reading as [<Tag: tag1>, <Tag: tag2>, <Tag: tag3>]. Expecting tag1 tag2 tag3 to be retrieved from django-taggit's TaggableManager-->
</div>
</div>
<div class="tag-list mb-4"></div>
</div>
<button type="submit" class="btn btn-primary " id="question-submit">Submit</button>
</form>
</div>
</main>
{% endblock %}
Шаги отладки
форма обрабатывается в этом классе Я пробовал печатать журналы и перемещать функцию init в начало.
# main_forum/forms/question_form.py
# This file contains the form for the Question model. The QuestionForm class will be used to create and update questions in the forum.
from django import forms
from django.contrib.auth.models import User
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from ..models import Question, Answer
from django_quill.forms import QuillFormField
from taggit.forms import TagField
from django.contrib.auth.forms import PasswordChangeForm
class QuestionForm(forms.ModelForm):
[...]
tags = forms.CharField(required=False)
class Meta:
model = Question # Specifies the model in models.py associated with this form
fields = ['subject', 'content', 'tags']
def __init__(self, *args, **kwargs):
"""
This is for checking if the form is bound to an existing instance, i.e. if the form is being used to update an existing question.
"""
super(QuestionForm, self).__init__(*args, **kwargs)
[...]
if self.instance.pk:
self.fields['tags'].initial = ' '.join(tag.name for tag in self.instance.tags.all()) # Pre-populate the tags field with the existing tags
print('tags initial:', self.fields['tags'].initial) # PASS. prints as tags initial: tag1 tag2 tag3
[...]
def clean_tags(self):
tags = self.cleaned_data.get('tags', '')
return tags
def save(self, *args, **kwargs):
instance = super(QuestionForm, self).save(commit=False)
instance.save()
# Handling tags here
tags = self.cleaned_data.get('tags', '')
tag_names = tags.split()
print('tag_names after tag.split', tag_names) # expecting ['tag1', 'tag2', 'tag3'] in order to be saved correctly etc. PASS
instance.tags.clear()
for tag_name in tag_names:
instance.tags.add(tag_name.strip()) # Ensure tag is stripped of extra whitespace
print('instance.tags.all:', instance.tags.all()) # PASS <QuerySet [<Tag: tag1>, <Tag: tag2>, <Tag: tag3>]> etc.
if self.instance.pk:
# If this is an update, save the instance again
instance.save() # Save the instance again to save the many-to-many relationships
print('instance saved:', instance) # testing: leads to server 500 error
return instance
Похоже, что лучшее решение, которое я могу найти, это замена {{ form.tags | as_crispy_field }}
на пользовательский ввод, который использует {{ question.tags.all|join:' ' }}
:
<input type="text" name="tags" id="id_tags id_tags_update" value="{{ question.tags.all|join:' ' }}" /> <!-- this correctly renders the tags as tag1 tag2 tag3 etc.-->