本文介绍了Django DateTimeInput类型“ datetime-local”未保存到数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Django应用程序来记录交易。所有交易文档都在一个页面上完成,并带有一个内联表单集,该表单集显示了交易的所有条目和出口。直到datetimeinput字段都正常工作。如果我删除类型,则该表格效果很好,但对用户非常不友好。



没有类型的工作条目



具有'type'的非工作项:'datetime-local'
)。



要使用Flatpickr,您需要在相关的HTML文件顶部添加:

 < link rel = stylesheet href = https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css > 
< script src = https://cdn.jsdelivr.net/npm/flatpickr< / script>


< script>
//此代码会在文档加载
window.addEventListener( DOMContentLoaded,function(){
flatpickr(。datetimefield, {
enableTime:true,
enableSeconds:true,
dateFormat: Ymd H:i:S,
});
});
< / script>

并更改:

 小部件= {
'date':form.DateTimeInput(attrs = {'type':'datetime-local','class':'form-control'}),
}

 小部件= {
'date':form.DateTimeInput(format ='%Y-%m-%d%H:%M:%S',attrs = {'class ':'datetimefield'}),
}

这将导致Django生成的字段具有也配置为flatpickr的格式(基于上面字段中的文本,并且一个django接受)。



还有许多其他日期您可以使用的选择器小部件,并且因为您已经在使用jquery,所以不必依赖jquery对您来说是一个大问题。


I'm working on a django app to document trades. All the trade documentation is done on one page with an inline formset that shows all the entries and exits for a trade. All work well up to the datetimeinput field. If I remove the 'type' the form works great but is very non-user friendly.

Working entries with no 'type'

Non-working entries with 'type': 'datetime-local'

So I guess you could say there are several issues datetime-local creates, or maybe it's not datetime-local to blame. I've been stuck on it all day and I'm really not sure where the issue comes from:

  1. Entry.date value is not populated into field anymore
  2. When a new date and time is selected in datetimepicker it doesn't save
  3. datetime-local removes the seconds, we need the seconds

models.py

from django.db.models.functions import datetime

class Entry(models.Model):
    ENTRY = 'entry'
    EXIT = 'exit'

    ENTRY_TYPE_CHOICES = [
        (ENTRY, 'Entry'),
        (EXIT, 'Exit'),
    ]

    class Meta:
        verbose_name = "Entry"
        verbose_name_plural = "Entries"

    trade = models.ForeignKey(Trade, on_delete=models.CASCADE)
    date = models.DateTimeField(null=True, blank=True, default=datetime.datetime.now)
    amount = models.FloatField(null=True)
    price = models.FloatField(null=True, blank=True)
    fee = models.FloatField(null=True, blank=True)
    entry_type = models.CharField(max_length=5, choices=ENTRY_TYPE_CHOICES, default=ENTRY)

forms.py

class EntriesForm(ModelForm):
    class Meta:
        model = Entry
        exclude = ()
        widgets = {
            'date': forms.DateTimeInput(attrs={'type':'datetime-local', 'class':'form-control'}),
        }

EntriesFormSet = inlineformset_factory(Trade, Entry, form=EntriesForm, extra=1)

views.py

class TradeUpdateView(UpdateView):
    model = Trade
    form_class = CreateForm
    success_url = reverse_lazy('trade-list')

    def get_context_data(self, **kwargs):
        data = super(TradeUpdateView, self).get_context_data(**kwargs)
        if self.request.POST:
            data['entries'] = EntriesFormSet(self.request.POST, instance=self.object)
        else:
            data['entries'] = EntriesFormSet(instance=self.object)
        return data

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.created_by = self.request.user
        context = self.get_context_data()
        entries = context['entries']
        with transaction.atomic():
            self.object = form.save()

            if entries.is_valid():
                entries.instance = self.object
                entries.save()
        return super(TradeUpdateView, self).form_valid(form)

trade_form.html

{% extends 'dashboard/base.html' %}
{% load static %}

{% block content %}

<script type="text/javascript" src="{% static 'vendor/jquery/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>

<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-3">
    <h2>New Trade</h2>
</div>

<div class="row">
    <div class="col">
        <form action="" method="post">{% csrf_token %}
            {{ form.as_p }}

            <table class="table">
                {{ entries.management_form }}

                {% for form in entries.forms %}
                {% if forloop.first %}
                <thead>
                <tr>
                    {% for field in form.visible_fields %}
                    <th>{{ field.label|capfirst }}</th>
                    {% endfor %}
                </tr>
                </thead>
                {% endif %}
                <tr class="{% cycle row1 row2 %} formset_row">
                    {% for field in form.visible_fields %}
                    <td>
                        {# Include the hidden fields in the form #}
                        {% if forloop.first %}
                        {% for hidden in form.hidden_fields %}
                        {{ hidden }}
                        {% endfor %}
                        {% endif %}
                        {{ field.errors.as_ul }}
                        {{ field }}
                    </td>
                    {% endfor %}
                </tr>
                {% endfor %}
            </table>
            <input type="submit" value="Save"/> <a href="{% url 'trade-list' %}">back to the list</a>
        </form>
    </div>


</div>


<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'js/formset/jquery.formset.js' %}"></script>
<script type="text/javascript">
    $('.formset_row').formset({
        addText: 'add entry',
        deleteText: 'remove',
        prefix: 'entry_set'
    });

</script>


{% endblock content %}
解决方案

The format that is submitted by a field with type=datetime-local appears not to be one that is accepted by Django, which in my local tests caused the form not to save. It is potentially possible to add datetime formats for fields to those that django accepts using DATETIME_INPUT_FORMATS in the settings file (see https://docs.djangoproject.com/en/3.0/ref/settings/#std:setting-DATETIME_INPUT_FORMATS). However, if you are using localisation (i.e. USE_L10N = True in your settings) then DATETIME_INPUT_FORMATS appears not be used (based on my tests - I haven't reviewed the underlying code). In the (admittedly limited) time I spent, I could not get DATETIME_INPUT_FORMATS to have any effect at all.

Given the very limited support for datetime-local and difficulties getting django to accept the result in any case, I would suggest you consider using a datetime widget that gives you more control and greater cross-browser compatibility. One that appears (as of Feb 2020) to be maintained and have very limited dependencies is Flatpickr (https://flatpickr.js.org/).

In your case, to use Flatpickr you would need to include in top of the relevant HTML files:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>


<script>
    // This code activates flatpickr on fields with the 'datetimefield' class when the document has loaded
    window.addEventListener("DOMContentLoaded", function () {
        flatpickr(".datetimefield", {
            enableTime: true,
            enableSeconds: true,
            dateFormat: "Y-m-d H:i:S",
        });
    });
</script>

and change:

        widgets = {
            'date': forms.DateTimeInput(attrs={'type':'datetime-local', 'class':'form-control'}),
        }

to

        widgets = {
            'date': forms.DateTimeInput(format='%Y-%m-%d %H:%M:%S', attrs={'class':'datetimefield'}),
        }

This will cause the django-generated field to have the format that is also configured for flatpickr (which is based on the text in your fields above, and one django accepts).

There are a number of other date picker widgets you could use, and as you're already using jquery, having a jquery dependency would not necessary be a big problem for you.

这篇关于Django DateTimeInput类型“ datetime-local”未保存到数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 03:13
查看更多