简体   繁体   English

带有自定义字段模板的Django Crispy Forms不会添加要请求的字段的值

[英]Django Crispy Forms with custom field template is not adding the value of the field to request

I am using Django 1.10 and django-crispy-forms 1.6.1 in my project. 我在我的项目中使用Django 1.10和django-crispy-forms 1.6.1。 I added a custom datetimepicker dropdown template that seems to be functioning correctly. 我添加了一个似乎正常运行的自定义datetimepicker下拉模板。 The problem I am now encountering, is that every time I attempt to submit a form, I am flashed with the error on the field that it is required. 我现在遇到的问题是,每当我尝试提交表单时,我都会在字段上显示错误,并且需要它。 It seems that after submitting the form, the field is cleared out, and the error class is added to the field. 似乎在提交表单后,字段被清除,错误类被添加到字段中。

After submit, form shows errors 提交后,表单显示错误

When I checked the console, I receive no errors, but when I check Chrome DevTools, I looked at the request payload sent server-side and I see that the field is not added at all to the request. 当我检查控制台时,我没有收到任何错误,但是当我检查Chrome DevTools时,我查看了服务器端发送的请求有效负载,我发现该字段根本没有添加到请求中。 Here is a picture of the request payload from the dev tools. 这是来自开发工具的请求有效负载的图片。

DevTools request payload without "time_stamp" DevTools请求有效负载而没有“time_stamp”

I am able to get the datetimepicker to dropdown when the input receives focus, and that seems to work just fine. 当输入获得焦点时,我能够将datetimepicker下拉到下拉,这似乎工作得很好。 Here is the relevant code for my forms/views, and the custom template.html: 以下是我的表单/视图和自定义template.html的相关代码:

models.py models.py

class Call(models.Model):
    history = AuditlogHistoryField()
    analyst = models.ForeignKey(settings.AUTH_USER_MODEL, models.SET_NULL, blank=True, null=True, limit_choices_to={'is_staff': True}, related_name='call_analyst')
    contact = models.CharField(max_length=50)
    time_stamp = models.DateTimeField(default=datetime.now)
    description = models.CharField(max_length=512)
    ticket = models.PositiveIntegerField(blank=True, null=True)
    CALL_TYPE = (
        ('M', 'Made'),
        ('R', 'Received'),
    )
    call_type = models.CharField(max_length=1, choices=CALL_TYPE)
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    @python_2_unicode_compatible
    def __str__(self):
        return "Call instance {}".format(self.pk)

forms.py forms.py

class CallForm(forms.ModelForm):
    description = forms.CharField(widget=forms.Textarea)

    class Meta:
        model = Call
        fields = ['analyst', 'contact', 'time_stamp', 'description', 'ticket', 'call_type']

    def __init__(self, *args, **kwargs):
        super(CallForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.form_tag = True
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-sm-3'
        self.helper.field_class = 'col-sm-9'
        self.helper.layout = Layout(
            Field('analyst'),
            Field('contact'),
            Field('time_stamp', template="datetimepicker.html"),
            Field('description'),
            Field('ticket'),
            Field('call_type'),
        )

    def is_valid(self):
        return super(CallForm, self).is_valid()

    def full_clean(self):
        return super(CallForm, self).full_clean()

    def clean_analyst(self):
        analyst = self.cleaned_data.get("analyst", None)
        return analyst

    def clean_contact(self):
        contact = self.cleaned_data.get("contact", None)
        return contact

    def clean_time_stamp(self):
        time_stamp = self.cleaned_data.get("time_stamp", None)
        return time_stamp

    def clean_description(self):
        description = self.cleaned_data.get("description", None)
        return description

    def clean_ticket(self):
        ticket = self.cleaned_data.get("ticket", None)
        return ticket

    def clean_call_type(self):
        call_type = self.cleaned_data.get("call_type", None)
        return call_type

    def clean(self):
        return super(CallForm, self).clean()

    def validate_unique(self):
        return super(CallForm, self).validate_unique()

    def save(self, commit=True):
        return super(CallForm, self).save(commit)

views.py views.py

class CallCreateView(AjaxCreateView):
    model = Call
    form_class = CallForm
    # fields = ['analyst', 'contact', 'call_timestamp', 'description', 'ticket', 'call_type']
    template_name = "reports/../_templates/create_update_template.html"
    success_url = reverse_lazy("call_list")

    def __init__(self, **kwargs):
        super(CallCreateView, self).__init__(**kwargs)

    def dispatch(self, request, *args, **kwargs):
        return super(CallCreateView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return super(CallCreateView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return super(CallCreateView, self).post(request, *args, **kwargs)

    def get_form_class(self):
        return super(CallCreateView, self).get_form_class()

    def get_form(self, form_class=None):
        return super(CallCreateView, self).get_form(form_class)

    def get_form_kwargs(self, **kwargs):
        return super(CallCreateView, self).get_form_kwargs()

    def get_initial(self):
        return super(CallCreateView, self).get_initial()

    def form_invalid(self, form):
        return super(CallCreateView, self).form_invalid(form)

    def form_valid(self, form):
        obj = form.save(commit=False)
        obj.save()
        return super(CallCreateView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        ret = super(CallCreateView, self).get_context_data(**kwargs)
        return ret

    def render_to_response(self, context, **response_kwargs):
        return super(CallCreateView, self).render_to_response(context, **response_kwargs)

    def get_template_names(self):
        return super(CallCreateView, self).get_template_names()

    def get_success_url(self):
        return reverse("call_detail", args=(self.object.pk,))

datetimepicker.html datetimepicker.html

{% load crispy_forms_field %}

<div{% if div.css_id %} id="{{ div.css_id }}"{% endif %}
                        class="form-group{% if form_show_errors and field.errors %} has-error{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}{% if div.css_class %} {{ div.css_class }}{% endif %}">
    {% if field.label and form_show_labels %}
        <label for="{{ field.id_for_label }}"
               class="control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
            {{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
        </label>
    {% endif %}

    <div class="controls date datetimepicker col-sm-9" id="{{ field.id_for_label }}"
         data-link-field="{{ field.id_for_label }}" {{ flat_attrs|safe }}>
        <input class="form-control" id="{{ field.id_for_label }}" type="text">
    </div>
    <input type="hidden" id="{{ field.id_for_label }}" value=""/><br/>
    {% include 'bootstrap3/layout/help_text_and_errors.html' %}
</div>

{% block datetimepicker %}
    <script type="text/javascript">
        $(function () {
            $('#{{ field.id_for_label }}').datetimepicker({
                sideBySide: true,
                allowInputToggle: true,
                showTodayButton: true,
                showClear: true,
                showClose: true,
                toolbarPlacement: "top",
                format: "dddd, MMMM Do YYYY, h:mm A"
            })
        })
    </script>
{% endblock %}

I think there must be a problem either with my template, or how django-crispy-forms handles fields that use a custom template, because when I remove the template from the form helper, a regular input box is used and the datetime string is submitted just fine to django. 我认为我的模板或者django-crispy-forms如何处理使用自定义模板的字段一定存在问题,因为当我从表单助手中删除模板时,会使用常规输入框并提交日期时间字符串django很好。 Thank you all for your help. 谢谢大家的帮助。 Sorry that I had to link the images, I don't have a high enough rep to embed them. 对不起,我必须链接图像,我没有足够高的代表嵌入他们。

I think the reason why the time_stamp is not being sent to the server because the datepicker input tag doesn't have a name attribute: 我认为time_stamp没有被发送到服务器的原因是因为datepicker input标签没有name属性:

<input class="form-control" id="{{ field.id_for_label }}" type="text">

Have a look at the notes in w3schools : 看看w3schools中的笔记

Note: Only form elements with a name attribute will have their values passed when submitting a form. 注意:只有具有name属性的表单元素才会在提交表单时传递其值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM