Я работаю с CreateView. При отправке моей формы со всеми правильно заполненными полями также сохраняется поле тикетов (поле ManyToMany). Однако, если я POST мою форму с некоторой ошибкой проверки (например, обязательное поле пусто), тогда все предварительно заполненные поля все еще являются полями через request.POST. Однако предварительно отмеченные мной поля больше не выбираются. Ты знаешь почему?
view.py
class DiscountCreate(AdminPermissionRequiredMixin, SuccessMessageMixin,
FormValidationMixin, BaseDiscountView, CreateView):
form_class = DiscountForm
template_name = 'discounts/admin/create.html'
success_message = _("Discount Code has been successfully created.")
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['event'] = self.request.event
return kwargs
def get_success_url(self):
return reverse('discounts:admin:detail', kwargs = {
'organizer': self.request.organizer.slug,
'event': self.request.event.slug,
'discount': self.instance.pk
})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['type_fixed'] = Discount.TYPE_FIXED
context['type_percentage'] = Discount.TYPE_PERCENTAGE
return context
def form_valid(self, form):
self.instance = form.save(commit=False)
self.instance.event = self.request.event
self.instance.status = Discount.STATUS_ACTIVE
return super().form_valid(form)
Шаблон
<div class = "card">
<div class = "card-header">
<h4 class = "card-header-title">
{% trans "Creating Discount Code" %}
</h4>
</div>
<div class = "card-body">
<form method = "post" autocomplete = "off" novalidate>
{% csrf_token %}
<div class = "form-group">
<label for = "{{ form.code.id_for_label }}">
{{ form.code.label }}
</label>
{{ form.code }}
{% if form.code.errors %}
<div class = "invalid-feedback d-block">
{{ form.code.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group">
<label for = "{{ form.type.id_for_label }}">
{{ form.type.label }}
</label>
{{ form.type }}
{% if form.type.errors %}
<div class = "invalid-feedback d-block">
{{ form.type.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group fixed{% if form.type.value != type_fixed %} d-none {% endif %}">
{{ form.value.label_tag }}
<div class = "input-group">
{{ form.value }}
<div class = "input-group-append">
<span class = "input-group-text text-dark">{{ request.event.currency }}</span>
</div>
</div>
{% if form.value.errors %}
<div class = "invalid-feedback d-block">
{{ form.value.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group percentage{% if form.type.value != type_percentage %} d-none {% endif %}">
{{ form.percentage.label_tag }}
<div class = "input-group">
{{ form.percentage }}
<div class = "input-group-append">
<span class = "input-group-text text-dark">%</span>
</div>
</div>
{% if form.percentage.errors %}
<div class = "invalid-feedback d-block">
{{ form.percentage.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group">
{{ form.available_amount.label_tag }}
{{ form.available_amount }}
{% if form.available_amount.errors %}
<div class = "invalid-feedback d-block">
{{ form.available_amount.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group">
<label for = "{{ form.tickets.id_for_label }}">
{{ form.tickets.label }}
<span class = "badge badge-light">{% trans "Optional" %}</span>
</label>
<small class = "form-text text-muted mt--2">{{ form.tickets.help_text }}</small>
{% for ticket_id, ticket_label in form.tickets.field.choices %}
<div class = "custom-control custom-checkbox">
<input
type = "checkbox"
name = "{{ form.tickets.html_name }}"
value = "{{ ticket_id }}"
class = "custom-control-input"
id = "id_{{ form.tickets.html_name }}_{{ forloop.counter }}"
{% if ticket_id in form.tickets.value %}checked{% endif %}>
<label class = "custom-control-label" for = "id_{{ form.tickets.html_name }}_{{ forloop.counter }}">{{ ticket_label }}</label>
</div>
{% endfor %}
{% if form.tickets.errors %}
<div class = "invalid-feedback d-block">
{{ form.tickets.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group">
<label for = "{{ form.valid_from.id_for_label }}">
{{ form.valid_from.label }}
<span class = "badge badge-light">{% trans "Optional" %}</span>
</label>
<small class = "form-text text-muted mt--2">{{ form.valid_from.help_text }}</small>
{{ form.valid_from }}
{% if form.valid_from.errors %}
<div class = "invalid-feedback d-block">
{{ form.valid_from.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group">
<label for = "{{ form.valid_until.id_for_label }}">
{{ form.valid_until.label }}
<span class = "badge badge-light">{% trans "Optional" %}</span>
</label>
<small class = "form-text text-muted mt--2">{{ form.valid_until.help_text }}</small>
{{ form.valid_until }}
{% if form.valid_until.errors %}
<div class = "invalid-feedback d-block">
{{ form.valid_until.errors|first }}
</div>
{% endif %}
</div>
<div class = "form-group">
<label for = "{{ form.comment.id_for_label }}">
{{ form.comment.label }}
<span class = "badge badge-light">{% trans "Optional" %}</span>
</label>
<small class = "form-text text-muted mt--2">{{ form.comment.help_text }}</small>
{{ form.comment }}
{% if form.comment.errors %}
<div class = "invalid-feedback d-block">
{{ form.comment.errors|first }}
</div>
{% endif %}
</div>
<button type = "submit" class = "btn btn-primary btn-block">{% trans "Create Discount Code" %}</button>
</form>
</div>
</div> {# / .card #}
<a class = "btn btn-block btn-link text-muted mb-4" href = "{% url 'discounts:admin:index' request.organizer.slug request.event.slug %}">
{% trans "Cancel discount code creation" %}
</a>
forms.py
class DiscountForm(forms.ModelForm):
# Remove required attribute from HTML elements
use_required_attribute = False
value = forms.DecimalField(decimal_places=2, required=False)
percentage = forms.DecimalField(max_digits=4, decimal_places=2, required=False)
class Meta:
model = Discount
fields = (
'code',
'type',
'value',
'percentage',
'available_amount',
'tickets',
'valid_from',
'valid_until',
'comment',
)
def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event')
super().__init__(*args, **kwargs)
for visible_field in self.visible_fields():
visible_field.field.widget.attrs['class'] = 'form-control'
self.fields['tickets'].queryset = self.event.tickets.all()
self.fields['code'].widget.attrs['autofocus'] = True
self.fields['valid_from'].widget.attrs['class'] = 'form-control start-date picker'
self.fields['valid_until'].widget.attrs['class'] = 'form-control end-date picker'
self.fields['valid_from'].widget.format = settings.DATETIME_INPUT_FORMATS[0]
self.fields['valid_until'].widget.format = settings.DATETIME_INPUT_FORMATS[0]
self.fields['valid_from'].widget.attrs['data-lang'] = get_lang_code()
self.fields['valid_until'].widget.attrs['data-lang'] = get_lang_code()
def clean(self):
cleaned_data = super().clean()
discount_type = cleaned_data.get('type')
if discount_type:
if discount_type == Discount.TYPE_FIXED:
value = cleaned_data.get('value')
cleaned_data['percentage'] = None
if not value:
message = _("Please enter how much discount you want to give.")
self.add_error('value', forms.ValidationError(message))
if discount_type == Discount.TYPE_PERCENTAGE:
percentage = cleaned_data.get('percentage')
cleaned_data['value'] = None
if not percentage:
message = _("Please enter how much discount you want to give.")
self.add_error('percentage', forms.ValidationError(message))
def clean_value(self):
value = self.cleaned_data['value']
if value:
value = smallest_currency_unit_converter(
value,
self.event.currency,
)
return value
def clean_percentage(self):
percentage = self.cleaned_data['percentage']
if percentage:
percentage /= 100 # convert 19 to 0.19
return percentage
def clean_valid_until(self):
valid_until = self.cleaned_data['valid_until']
if valid_until and valid_until > self.event.end_date:
valid_until = self.event.end_date
return valid_until
def clean_valid_from(self):
valid_from = self.cleaned_data['valid_from']
if valid_from and valid_from > self.event.end_date:
raise forms.ValidationError(_("Discount code should become valid \
before the event starts."), code='valid_from')
return valid_from
def clean_code(self):
code = self.cleaned_data['code']
code_check = self.event.discounts.filter(
code=code
).exclude(pk=self.instance.pk).exists()
if code_check:
raise forms.ValidationError(_("The code you chose as your discount code \
already exists for this event. Please change it."), code='code_exists')
return code






После того, как я решил проблему, окончательное решение, которое мне помогло, можно найти здесь: Шаблон Django: {% if 5 in ['4', '3', '5']%} не работает
Теперь я понял, что «request.POST »содержит опубликованные значения билетов, например, ´'tickets ': [' 2 ',' 5 '] `Похоже, моя пользовательская визуализированная форма не получает эти значения. Я до сих пор не знаю почему