如何在 django 的 ModelForm 中使用 DatePicker?
How to use a DatePicker in a ModelForm in django?
我正在使用 django 3.0,我正试图在我的 ModelForm 中显示一个日期选择器小部件,但我不知道如何(我只能得到文本字段)。我曾尝试寻找一些解决方案,但找不到任何解决方案。这就是我的模型和 ModelForm 的样子:
class Membership(models.Model):
start_date = models.DateField(default=datetime.today, null=True)
owner = models.ForeignKey(Client, on_delete=models.CASCADE, null=True)
type = models.ForeignKey(MembershipType, on_delete=models.CASCADE, null=True)
class MembershipForm(ModelForm):
class Meta:
model = Membership
fields = ['owner', 'start_date', 'type']
widgets = {
'start_date': forms.DateInput
}
这是我的 html:
<form class="container" action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
这是预期的行为。 DateInput
widget [Django-doc] 只是一个带有可选 format
参数的 <input type="text">
元素。
你可以使用一个包,例如 django-bootstrap-datepicker-plus
[pypi]
, 然后用 DatePickerInput
:
定义一个表单
from bootstrap_datepicker_plus import <b>DatePickerInput</b>
class MembershipForm(ModelForm):
class Meta:
model = Membership
fields = ['owner', 'start_date', 'type']
widgets = {
'start_date': <b>DatePickerInput</b>
}
在模板中,您需要呈现表单的媒体并加载 bootstrap css 和 javascript:
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{{ <b>form.media</b> }}
<form class="container" action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
虽然 很棒,但有一些替代方案不需要额外的依赖项。
几个选项,按照努力程度的顺序排列:
使用SelectDateWidget instead of the default DateInput(不需要 JavaScript):
class MyForm(forms.Form):
date = forms.DateField(widget=forms.SelectDateWidget())
使用浏览器的内置日期选择器,通过实现使用 HTML <input type="date"> 元素的自定义小部件(no JavaScript 必填):
class MyDateInput(forms.widgets.DateInput):
input_type = 'date'
class MyForm(forms.Form):
date = forms.DateField(widget=MyDateInput())
或者,或者:
class MyForm(forms.Form):
date = forms.DateField(widget=forms.DateInput(attrs=dict(type='date')))
使用 django.contrib.admin
中的日期选择器,详见 here。简而言之,您需要一些东西:
from django.contrib.admin.widgets import AdminDateWidget
...
class MyForm(forms.Form):
date = forms.DateField(widget=AdminDateWidget())
然后,要使其正常工作,请将以下依赖项添加到您的模板 <head>
:
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}" />
<script src="{% static 'admin/js/core.js' %}"></script>
<script src="{% url 'admin:jsi18n' %}"></script> {# see note below #}
{{ form.media }} {# this adds 'calendar.js' and 'DateTimeShortcuts.js' #}
现在有一个问题:admin:jsi18n
url 仅适用于具有管理员访问权限的用户,因此您可能需要替换它并在 urls.py
中定义替代路径,例如:
from django.views import i18n
...
urlpatterns = [
...,
path('jsi18n/', i18n.JavaScriptCatalog.as_view(), name='jsi18n'),
]
最后,小部件的外观如下(在 Firefox 上):
我个人最喜欢第二种选择。它还允许我们指定初始值、最小值和最大值(在 django 中你可以这样做,例如使用 attrs
参数)。下面是显示 HTML 元素的快速片段:
<input type="date" value="2021-09-09" min="2021-09-09">
正如其他人所说,这是预料之中的,因为它只是一个特殊的文本字段。
我更喜欢的替代方法是使用 django-widget-tweaks
,因为这会将 front-end 自定义推送回您的模板,而不是在后端编辑 forms.py。 Saving/testing 也更快,因为应用程序不必在每次保存时重新加载。
安装到您的环境:
pip install django-widget-tweaks
添加到已安装的应用程序:
INSTALLED_APPS = [
...
"widget_tweaks",
]
添加到您的模板:
{% extends 'app/base.html' %}
{% load widget_tweaks %}
使用 render_field
和输入标签属性来自定义您的字段。例如下面使用 bootstrap 5. 注意我们如何在模板标签中指定 type
和 class
等属性:
<div class="col-2">
<label for="{{ form.date.id_for_label }}" class="col-form-label">{{ form.year.label }}</label>
</div>
<div class="col-4">
{% render_field form.year type="date" class="form-control" placeholder="mm/dd/yyyy" %}
<div>
Django 4.0。把它留在这里以防它帮助别人。
这会将最小日期和默认值设置为今天的日期,应该在 forms.py 中使用。就我而言,我在我的 .html 中使用脆皮形式来呈现该字段。
from datetime import date
today = date.today()
class DateForm(forms.ModelForm):
target_Date = forms.DateField(widget=forms.TextInput(attrs={'min': today, 'value': today, 'type': 'date'}), required=True)
class Meta:
model = DateForm
fields = ['target_Date']
我正在使用 django 3.0,我正试图在我的 ModelForm 中显示一个日期选择器小部件,但我不知道如何(我只能得到文本字段)。我曾尝试寻找一些解决方案,但找不到任何解决方案。这就是我的模型和 ModelForm 的样子:
class Membership(models.Model):
start_date = models.DateField(default=datetime.today, null=True)
owner = models.ForeignKey(Client, on_delete=models.CASCADE, null=True)
type = models.ForeignKey(MembershipType, on_delete=models.CASCADE, null=True)
class MembershipForm(ModelForm):
class Meta:
model = Membership
fields = ['owner', 'start_date', 'type']
widgets = {
'start_date': forms.DateInput
}
这是我的 html:
<form class="container" action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
这是预期的行为。 DateInput
widget [Django-doc] 只是一个带有可选 format
参数的 <input type="text">
元素。
你可以使用一个包,例如 django-bootstrap-datepicker-plus
[pypi]
, 然后用 DatePickerInput
:
from bootstrap_datepicker_plus import <b>DatePickerInput</b>
class MembershipForm(ModelForm):
class Meta:
model = Membership
fields = ['owner', 'start_date', 'type']
widgets = {
'start_date': <b>DatePickerInput</b>
}
在模板中,您需要呈现表单的媒体并加载 bootstrap css 和 javascript:
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{{ <b>form.media</b> }}
<form class="container" action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
虽然
几个选项,按照努力程度的顺序排列:
使用SelectDateWidget instead of the default DateInput(不需要 JavaScript):
class MyForm(forms.Form): date = forms.DateField(widget=forms.SelectDateWidget())
使用浏览器的内置日期选择器,通过实现使用 HTML <input type="date"> 元素的自定义小部件(no JavaScript 必填):
class MyDateInput(forms.widgets.DateInput): input_type = 'date' class MyForm(forms.Form): date = forms.DateField(widget=MyDateInput())
或者,或者:
class MyForm(forms.Form): date = forms.DateField(widget=forms.DateInput(attrs=dict(type='date')))
使用
django.contrib.admin
中的日期选择器,详见 here。简而言之,您需要一些东西:from django.contrib.admin.widgets import AdminDateWidget ... class MyForm(forms.Form): date = forms.DateField(widget=AdminDateWidget())
然后,要使其正常工作,请将以下依赖项添加到您的模板
<head>
:<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}" /> <script src="{% static 'admin/js/core.js' %}"></script> <script src="{% url 'admin:jsi18n' %}"></script> {# see note below #} {{ form.media }} {# this adds 'calendar.js' and 'DateTimeShortcuts.js' #}
现在有一个问题:
admin:jsi18n
url 仅适用于具有管理员访问权限的用户,因此您可能需要替换它并在urls.py
中定义替代路径,例如:from django.views import i18n ... urlpatterns = [ ..., path('jsi18n/', i18n.JavaScriptCatalog.as_view(), name='jsi18n'), ]
最后,小部件的外观如下(在 Firefox 上):
我个人最喜欢第二种选择。它还允许我们指定初始值、最小值和最大值(在 django 中你可以这样做,例如使用 attrs
参数)。下面是显示 HTML 元素的快速片段:
<input type="date" value="2021-09-09" min="2021-09-09">
正如其他人所说,这是预料之中的,因为它只是一个特殊的文本字段。
我更喜欢的替代方法是使用 django-widget-tweaks
,因为这会将 front-end 自定义推送回您的模板,而不是在后端编辑 forms.py。 Saving/testing 也更快,因为应用程序不必在每次保存时重新加载。
安装到您的环境:
pip install django-widget-tweaks
添加到已安装的应用程序:
INSTALLED_APPS = [
...
"widget_tweaks",
]
添加到您的模板:
{% extends 'app/base.html' %}
{% load widget_tweaks %}
使用 render_field
和输入标签属性来自定义您的字段。例如下面使用 bootstrap 5. 注意我们如何在模板标签中指定 type
和 class
等属性:
<div class="col-2">
<label for="{{ form.date.id_for_label }}" class="col-form-label">{{ form.year.label }}</label>
</div>
<div class="col-4">
{% render_field form.year type="date" class="form-control" placeholder="mm/dd/yyyy" %}
<div>
Django 4.0。把它留在这里以防它帮助别人。 这会将最小日期和默认值设置为今天的日期,应该在 forms.py 中使用。就我而言,我在我的 .html 中使用脆皮形式来呈现该字段。
from datetime import date
today = date.today()
class DateForm(forms.ModelForm):
target_Date = forms.DateField(widget=forms.TextInput(attrs={'min': today, 'value': today, 'type': 'date'}), required=True)
class Meta:
model = DateForm
fields = ['target_Date']