Django choicefield Выберите правильный выбор
Я пытаюсь отправить свою модель формы с ajax загруженной информацией из других моих моделей. Для поля ChoiceField моей формы модели я получил эту ошибку;
Select a valid choice. 69 is not one of the available choices.
Запрос.POST выглядит нормально. Я получил все мои поля правильно. Поскольку мое поле remind_object уже является CharField, я должен быть в состоянии сохранить ['69'] туда, но я не могу понять, почему я получил эту ошибку
*** request.POST: <QueryDict: {'csrfmiddlewaretoken': ['dTtWIUKCOytmYVsbGf7StxMmd4ywPd0gzvvraAgrqiLuiUfLv3xo2TD1lv9Xpcxs'], 'topic': ['dsfdsfs'], 'remind_date': ['2022-02-22 13:45:59'], 'reminder_object_type': ['Client'], 'remind_object': ['69'], 'detail': ['<p>fdgfdgfd</p>\r\n'], 'submit_reminder_create_form': ['']}>
models.py
class Reminder(models.Model):
user_owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reminder_user') # user.reminder_user
topic = models.CharField(max_length=100, blank=True, null=True)
remind_date = models.DateTimeField(blank=True, null=True)
reminder_object_type = models.CharField(max_length=100, blank=True, null=True)
# Client
# Contact
# Action
remind_object = models.CharField(max_length=999, blank=True, null=True)
detail = RichTextField(max_length=999999,blank=True, null=True)
reminder_status = models.CharField(max_length=100, default="Active", blank=True, null=True)
slug = models.SlugField(max_length=200, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.topic)
def save(self, *args, **kwargs):
self.slug = slugify(str(self.topic) + "-" + str(self.user_owner) + "-" + str(get_random_code()))
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse('reminder-detailview', kwargs={'slug': self.slug})
forms.py
class ReminderModelForm(forms.ModelForm):
class Meta:
model = models.Reminder
fields = ('reminder_object_type', 'topic', 'remind_date', 'remind_object', 'detail')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['reminder_object_type'] = forms.ChoiceField(required=True, label="", widget=forms.RadioSelect(attrs={'class': 'form-check form-control'}), choices=(
("Client", "Client"),
("Contact", "Contact"),
("Action", "Action")
))
self.fields['topic'] = forms.CharField(required=True, max_length=100, label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder': 'Topic'}))
self.fields['remind_date'] = forms.DateTimeField(required=True, label="", validators=[validate_greater_than_now], widget=DateTimeWidget(
attrs={'class':'form-control'},
usel10n = True,
bootstrap_version=4
) )
self.fields['remind_object'] = forms.ChoiceField(required=False, label="", widget=forms.Select(attrs={'class': 'form-control'}))
self.fields['detail'] = forms.CharField(required=False, max_length=999999, widget=CKEditorWidget(attrs={'class' : 'form-control'}))
views.py
class ReminderListView(generic.ListView):
model = models.Reminder
template_name = 'crm/reminder_list.html'
ordering = ['-created']
def post(self, request, *args, **kwargs):
if 'submit_reminder_create_form' in self.request.POST:
print("*** request.POST: ", request.POST)
reminder_form = forms.ReminderModelForm(self.request.POST, self.request.FILES)
if reminder_form.is_valid():
print("*** request.POST: ", request.POST)
instance = reminder_form.save(commit=False)
instance.user_owner = self.request.user
instance.save()
reminder_form = forms.ReminderModelForm()
messages.success(self.request, f'{instance.topic} created successfully')
return redirect('reminder-detailview', slug=instance.slug)
else:
messages.warning(self.request, 'The form is not valid, please check the form fields properly!')
context = {
'reminder_create_form':forms.ReminderModelForm(self.request.POST, self.request.FILES),
'all_reminders': models.Reminder.objects.all().order_by('-created')
}
return render(request, 'crm/reminder_list.html', context, status=404)
def get_context_data(self, **kwargs):
context = super(ReminderListView, self).get_context_data(**kwargs)
context['all_reminders'] = models.Reminder.objects.all().order_by('-created')
context['sidebar_in'] = 'Reminder'
context['time_is'] = timezone.now()
context['reminder_create_form'] = forms.ReminderModelForm
context['active_reminders'] = models.Reminder.objects.filter(reminder_status = 'Active').filter(remind_date__lte = timezone.now() ).order_by('-created')
return context
html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
{{ reminder_create_form.media }}
<form id="reminder-create-form" method="POST" enctype="multipart/form-data" class="needs-validation"> {% csrf_token %}
{{reminder_create_form|crispy}}
</form>
<!-- jquery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!-- my custom -->
<script>
// bu js kısmı; sadece html formuna verilerin istediğimiz gibi bağlı-dropdown şeklinde yüklenmesini sağlıyor, ama forma kaydetmede forms.py da overwrite ettiğimiz init çalışacak
$(document.getElementById("reminder-create-form").elements["reminder_object_type"]).change(function () {
var selectedValue = $(this).val();
$.ajax({
url: "{% url 'ajax_reminder_type_view' %}",
data: { 'gonderilen_kelime': selectedValue, },
success: function (data) {
$(document.getElementById("reminder-create-form").elements["remind_object"]).html(data);
}
});
});
</script>
ajax_loading.html
{% for i in aranacak_objeler %}
<option value="{{ i.pk }}">
{% if i.name %}
{{ i.name }} {% if i.client_owner %} - Client: {{i.client_owner}} {% endif %}
{% else %}
{{ i.topic }} - Client: {{i.client_owner}} - Created: {{i.created|date:"F d, Y"}}
{% endif %}
</option>
{% endfor %}
Ошибка возникает в процессе валидации формы через метод to_python или validate класса django.form.Field. Вы передаете в поле недопустимое значение. Недопустимыми значениями могут быть те, которых нет в списке выбора или кортеже, но если вы уверены, что значение находится в списке выбора, просто проверьте поле и его виджет.
Значения, используемые для валидации поля, строго зависят от форматов ввода, заданных виджетом. Если вы используете для виджета поля виджет forms.RadioSelect, он передает полю строковое значение, тогда как виджет forms.CheckboxSelectMultiple передает перечисленные значения типа ['apple', 'orange', ...]. Дело в том, что каждое поле имеет свой собственный допустимый тип данных. Например, MultipleChoiceField принимает только списки или кортежи, в то время как ChoiceField принимает только строку. Может возникнуть коллизия между типом значения, указанным в виджете поля, который используется для валидации, и типом значения, который ожидает поле. Возможно, вы хотите сохранить строковое значение для CharField при передаче значения одноэлементного списка (или наоборот)?
Здесь вы можете узнать, какой тип данных допустим для конкретных полей. https://github.com/django/django/blob/737542390af27616d93f86cd418e2d7f3e874b27/django/forms/fields.py