django choicefield Select 一个有效的选择

django choicefield Select a valid choice

我正在尝试提交我的模型,其中包含 ajax 我其他模型的加载信息。对于我的模型形式的 ChoiceField,我得到了这个错误;

Select a valid choice. 69 is not one of the available choices.

request.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或django.form.Fieldclass的验证方法进行表单验证的过程中。您正在做的是将无效值传递给您的字段。无效值可以是不在选择列表或元组中的值,但如果您确定该值在‖选择列表中,只需检查字段及其小部件。

用于字段验证的值严格取决于小部件指定的输入格式。如果您对字段的小部件使用 forms.RadioSelect,则小部件会将字符串值传递给字段,而 forms.CheckboxSelectMultiple 小部件会传递列出的值,例如 ['apple'、'orange'、.. .]。问题是每个字段都有自己可接受的验证数据类型。例如,MultipleChoiceField 只接受列表或元组,而 ChoiceField 只接受字符串。也许字段小部件中指定的值类型(用于验证的值类型)与字段期望的值类型之间可能存在冲突。也许您想在传递给 single-element 列表值(或相反)时为 CharField 保存一个字符串值?

您可以在此处检查特定字段可接受的数据类型。 https://github.com/django/django/blob/737542390af27616d93f86cd418e2d7f3e874b27/django/forms/fields.py