I created a Date Picker using Django and Bootstrap. When clicking on the calendar field on the right of the input field, however, the calendar jumps to a default of: 06/Fr/yyyy. I tried setting the todayBtn attribute to True but that produced an error. Example can be seen on the following image:
My models.py:
class TimeInterval(models.Model):
time_interval = models.DateField()
forms.py:
from .models import TimeInterval
from bootstrap_datepicker_plus import DatePickerInput
class TimeIntervalForm(forms.ModelForm):
date = forms.DateField(
widget=DatePickerInput(
options={
"format": "mm/dd/yyyy",
# "todayHighlight": True,
# "todayBtn": True,
}
)
)
class Meta:
model = TimeInterval
fields = '__all__'
views.py:
def datepicker_form_view(request):
return render(request, "datepicker_form.html", {
"time_interval_form": TimeIntervalForm(),
})
And my HTML file:
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
<form action="." method="POST">{% csrf_token %}
{% bootstrap_form time_interval_form %}
{{time_interval_form.media }}
<input type="submit" value="Submit">
</form>
I came across a similar question about the todayHighlight attribute but there the OP used JavaScript/jQuery, hence it was advised that he added that attribute using a jQuery select. I feel that in my case, expanding the HTML code with a <script> section and a jQuery selection just to have that one attribute working is an overkill - there must be a more convenient way to go about this that I'm not aware of.
Try something like this
date = forms.DateTimeField(error_messages={'invalid': 'Wrong date.'},
required=False, widget=DateInput(attrs={
'class': 'datepicker form-control input-sm ',
'data-trigger': 'focus'}))
or
date = forms.DateTimeField(required=False,
widget=DateInput(attrs={'class': 'form-control input-sm'},
format=('%Y-%m-%d')))
Related
I am making a site on Django. And I faced a problem. I would like to create an input field in the form so that it is initially empty, but so that in the process of how the user enters data into it, a frame will appear next to it, with possible selection options based on data already entered by the user.
In short, I want to make something like this field
Help me please
The Select2 library is one that does a lot of magic for you. https://django-select2.readthedocs.io/en/latest/
An example from their own docs:
forms.py
class AuthorWidget(s2forms.ModelSelect2Widget):
search_fields = [
"username__icontains",
"email__icontains",
]
class BookForm(forms.ModelForm):
class Meta:
model = models.Book
fields = "__all__"
widgets = {
"author": AuthorWidget,
}
urls.py
urlpatterns = [
path("select2/", include("django_select2.urls")),
....
]
template.html
<h1>Create a new Book</h1>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
{{ form.media.js }}
Good day,
I'm trying "create" a DatePicker for one of my Inputfields in Django but it's not working!
In my models.py:
class Customer(models.Model):
...
name = models.CharField()
date = models.DateField()
In my views.py:
def Page(request):
CustomerFormSet = modelformset_factory(Customer, fields='__all__')
formset = CustomerFormSet (queryset=Customer.objects.none())
...
context = {'formset': formset}
return render(request, 'app/base.html', context)
In my template:
{% extends 'app/base.html' %}
{% load widget_tweaks %}
<form actions="" method="POST">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.id }}
...
{% render_field form.name class="form-control" %}
...
{% render_field form.date class="form-control" %}
...
Now my first Inputfield works fine! It returns a fitting Field in Bootstraps "Form-Group"-Layout. But my InputField for Dates remains a simple TextInput with no calendar apearing to choose from.
My Question is: am I doing something wrong or is it still impossible to obtain such a function in this way?
Thanks and a nice evening to all of you.
If you ara using ModelForm try:
from django import forms
class DateInput(forms.DateInput):
input_type = 'date'
class DataTreinoForm(forms.ModelForm):
class Meta:
model = models.YOURMODEL
fields = _all_
widgets = {
'dateField': DateInput
}
The default format is mm/dd/yyyy. I don't know how to change it in this way.
I just solved this too. Add type="date" to the render_field.
{% render_field form.date type="date" class="form-control" %}
You can add any input tag attributes here which is convenient because
Modify form appearance on the template instead of forms.py, which is conceptually consistent
When you save templates, it doesnt reload the app, so faster testing with html
I am using django 3.0 and I am trying to display a datepicker widget in my ModelForm, but I can't figure out how (all I can get is text field). I have tried looking for some solutions, but couldn't find any. This is how my Model and my ModelForm look like:
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
}
And this is my html:
<form class="container" action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Although #willem-van-onsem's answer is great, there are a few alternatives that do not require additional dependencies.
A few options, in order of increasing effort:
Use a SelectDateWidget instead of the default DateInput (no JavaScript required):
class MyForm(forms.Form):
date = forms.DateField(widget=forms.SelectDateWidget())
Use the browser's built-in date picker, by implementing a customized widget that uses the HTML <input type="date"> element (no JavaScript required):
class MyDateInput(forms.widgets.DateInput):
input_type = 'date'
class MyForm(forms.Form):
date = forms.DateField(widget=MyDateInput())
or, alternatively:
class MyForm(forms.Form):
date = forms.DateField(widget=forms.DateInput(attrs=dict(type='date')))
Use the date picker from django.contrib.admin, as described here in detail. In short, there are a few things you would need:
from django.contrib.admin.widgets import AdminDateWidget
...
class MyForm(forms.Form):
date = forms.DateField(widget=AdminDateWidget())
then, to make this work, add the following dependencies to your template <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' #}
Now there's one catch: the admin:jsi18n url only works for users with admin access, so you may need to replace this and define an alternative path in your urls.py, e.g.:
from django.views import i18n
...
urlpatterns = [
...,
path('jsi18n/', i18n.JavaScriptCatalog.as_view(), name='jsi18n'),
]
Finally, here's what the widgets look like (on firefox):
Personally I like the second option best. It also allows us to specify initial, minimum and maximum values (in django you can do this e.g. using the attrs argument). Here's a quick snippet to show the HTML element in action:
<input type="date" value="2021-09-09" min="2021-09-09">
Django 4.0. Leaving this here incase it helps someone else.
This will set the minimum date and default value to today's date and should be used in forms.py. In my case I use crispy forms in my .html to render the field.
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']
This is the expected behavior. A DateInput widget [Django-doc] is just a <input type="text"> element with an optional format parameter.
You can make use of a package, like for example django-bootstrap-datepicker-plus [pypi]
, and then define a form with the DatePickerInput:
from bootstrap_datepicker_plus import DatePickerInput
class MembershipForm(ModelForm):
class Meta:
model = Membership
fields = ['owner', 'start_date', 'type']
widgets = {
'start_date': DatePickerInput
}
In the template you will need to render the media of the form and load the bootstrap css and javascript:
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{{ form.media }}
<form class="container" action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
As other have said, this is expected since its just a special text field.
An alternative I prefer is using django-widget-tweaks as this pushes front-end customizations back to your template instead of editing forms.py on the backend. Saving/testing is also faster since the app doesn't have to reload with each save.
Install to your environment:
pip install django-widget-tweaks
Add to installed apps:
INSTALLED_APPS = [
...
"widget_tweaks",
]
Add to your template:
{% extends 'app/base.html' %}
{% load widget_tweaks %}
Use render_field with input tag attributes to customize your field. Eg below using bootstrap 5. Notice how we can specify attributes such as type and class within the template tag:
<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>
I am looking to create a dropdown in a template where the values of the dropdown come from a field (reference) within my Orders model in models.py. I understand creating a dropdown where the values are set statically, but since I am looking to populate with values stored in the DB, I'm unsure of where to start.
I've created the model and attempted playing around with views.py, forms.py and templates. I am able to get each of the order numbers to display but not in a dropdown and I am struggling with how to write my template.
models.py
from django.db import models
class Orders(models.Model):
reference = models.CharField(max_length=50, blank=False)
ultimate_consignee = models.CharField(max_length=500)
ship_to = models.CharField(max_length=500)
def _str_(self):
return self.reference
forms.py
from django import forms
from .models import *
def references():
list_of_references = []
querySet = Orders.objects.all()
for orders in querySet:
list_of_references.append(orders.reference)
return list_of_references
class DropDownMenuReferences(forms.Form):
reference = forms.ChoiceField(choices=[(x) for x in references()])
views.py
def reference_view(request):
if request.method == "POST":
form = references(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
form = references()
return render(request, 'proforma_select.html', {'form': form})
proforma_select.html
{% extends 'base.html' %}
{% block body %}
<div class="container">
<form method="POST">
<br>
{% for field in form %}
<div class="form-group row">
<label for="id_{{ field.name }}" class="col-2 col-form-label"> {{ field.label }}</label>
<div class="col-10">
{{ field }}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary" name="button">Add Order</button>
</form>
</div>
{% endblock %}
All I get when I render the template is each of the reference #s listed out but NOT within a dropdown. This leads me to believe my problem is mainly with the template, but I'm unsure as I am new to using Django.
Are you using Materialize CSS? If yes, then Django forms renders dropdowns differently from how Materialize expects them. So you will want to override the form widget. You can do something like so:
forms.py:
class DropDownMenuReferences(forms.Form):
reference = forms.ChoiceField(choices=[(x) for x in references()],
widget=forms.Select(choices=[(x) for x in references()], attrs={'class':
'browser-default'}))
This overrides the parameters passed into html. You can also pass any name tags in the attrs too.
The issue:
https://github.com/Dogfalo/materialize/issues/4904
I have the following radio button html using django widget tweaks (i do not have to use this library and open to using whatever method works):
{% for choice in seeking_form2.disaster_recovery %}
<div class="radio radio-primary radio-inline">
{{ choice.tag|attr:"required" }}
<label for='{{ seeking_form2.disaster_recovery.auto_id }}_{{ forloop.counter0 }}'>{{ choice.choice_label }}</label>
</div>
{% endfor %}
Which should create radios that look like this:
<input id="id_disaster_recovery" name="disaster_recovery" type="radio" value="2" required>
My model looks like:
BOOL_CHOICES = ((True, 'Yes'), (False, 'No'))
disaster_recovery = models.BooleanField(choices=BOOL_CHOICES, default=False, )
My form looks like:
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'disaster_recovery': forms.RadioSelect(),
}
I get the error:
'SafeText' object has no attribute 'as_widget'
If i understand your problem correctly, you should be overriding this in the form, rather than at the template, or the models.
class MyModelForm(..):
disaster_recovery = forms.ChoiceField(choices=BOOL_CHOICES, widget=forms.RadioSelect(), required=True) #Default is dropdown
Now, you could simplify your HTML to render the radiobuttons.
Some more context on this can be found here
To add the HTML required attribute, to your existing form, you can do:
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'disaster_recovery': forms.RadioSelect(attrs={"required": "required"}),
}
Here is the relevant documentation on the custom attributes