django custom date_field widget by datepicker - django

So, I want to use a JS library called datepicker as a template for my date fields in forms.
My custom widget`s code just renders a template:
class MyDateWidget(SelectDateWidget):
def render(self, name, value, attrs=None):
template = loader.get_template('date_widget.html')
return template.render(Context({}))
and date_widget.html contains following
<div class="input-append date" id="dp-input1" data-date-format="dd-mm-yyyy">
<input class="span12" size="16" type="text" value="12-02-2012" readonly="">
<span class="add-on"><i class="icon-calendar" onclick="$('#dp-input1').datepicker();"></i></span>
</div>
this html is kind of ok, I can see the nice popup datepicker menu in my page, but for some reason request.POST (this form posts, yes) doesn`t contain the picked date. Other fields are presented into the POST data.
Apparently my widget misses some important "backend" logic.

Though this question is pretty old, I think you must add the name attribute to the input tag:
class MyDateWidget(SelectDateWidget):
def render(self, name, value, attrs=None):
template = loader.get_template('date_widget.html')
return template.render(Context({'name': name}))
And:
<div class="input-append date" id="dp-input1" data-date-format="dd-mm-yyyy">
<input class="span12" size="16" type="text" name="{{ name }}" value="12-02-2012" readonly="">
<span class="add-on"><i class="icon-calendar" onclick="$('#dp-input1').datepicker();"></i></span>
</div>

Related

How to pass text argument to custom widget in django form?

I'd like to display a dynamic text value in a custom widget.
It will more or less be a bootstrap input group with some dynamic text in a input-group-append element.
I'm having difficulty understanding how I can pass this through to the template, as when I define the field in the Form class, I can't seem to reference arguments from the Form constructor.
I'm inexperienced with both python and django so its very likely I'm missing some foundational python knowledge that's causing my confusion.
If I do this, the widget renders partially ok (There is an automatic label "Site prefix" rendered that I don't want but that seems like a different problem)
class SiteNameForm(forms.Form):
site_prefix = forms.CharField(widget=SiteNameInputWidget(prefix_for='T E S T'), label=None)
And create the form like so
form = SiteNameForm()
However, I need to pass in a dynamic value, so I tried
class SiteNameForm(forms.Form):
def __init__(self, prefix_for=None, *args, **kwargs):
self.prefix_for = prefix_for
self.site_prefix = forms.CharField(widget=SiteNameInputWidget(prefix_for=self.prefix_for))
super().__init__(self, args, kwargs)
While creating the form
form = SiteNameForm(prefix_for='TEST')
But when I do that, nothing is rendered at all, not even the automatic label that I didn't want.
The template specified as template_name
<div class="row">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">https://</span>
</div>
<input type="text" id="site_prefix" name="site_prefix" class="form-control" aria-label="prefix">
<div class="input-group-append">
<span class="input-group-text">.<span class="domain-suffix-type">{{ prefix_for }}</span>.foo.bar</span>
</div>
</div>
Is there a way to accomplish what I'm trying to do?

Django-crispy-forms: set css for individual field and inputs

Is there a way to specify the css for an individual field and input in django crispy forms? I am using bootstrap4 and would like to use a horizontal form for a few fields in my form.
I know you can use a self.helper to set label.class and field.class but I presume that applies to all field. I only want to change the label and field class on a few of my fields.
EDIT:
I need to add css to the label that is different from the input
I'm trying to get a horizontal field inside a form like the amount field below
<div id="div_id_amount" class="row">
<label for="id_amount" class="col-form-label col-2 requiredField">
Amount<span class="asteriskField">*</span>
</label>
<div class="">
<input type="number" name="amount" step="0.01" class="numberinput form-control col-md" required="" id="id_amount">
</div>
</div>
One solution is given here:
You add the class attributes for the input field via the widget, as also explained in the django docs
You explicitly add the <label> tags with the correct class in your HTML.
Or, for the label, you can also create the following template filter:
#register.filter(is_safe=True)
def label_with_classes(field, css):
return field.label_tag(attrs={'class': css})
which you can use like this in your template after you've loaded it with {% load my_filters %}: {{ form.name|label_with_classes:"col-sm-6 col-lg-3" }}
I don't know of an easy way with crispy-forms.
You can add this in your Layout:
Field('password', id="password-field", css_class="passwordfields", title="Explanation")
You can find more details here

Django: how to retrieve a form search parameters in a django generic listView

how to retrieve a form search parameters in a django generic listView. My url is:
url(r'postsearch$', views.PostsList.as_view(), name='postsearch'),
My generic listview is:
class PostsList(generic.ListView):
model = Post
template_name = 'posts/post_list.html'
def get_queryset(self):
localisation = #how to get location
discipline = #how to get discipline
return Post.objects.filter(.......)
and my form is:
<form class="form-inline text-center" action="{% url 'posts:postsearch' %}" id="form-searchLessons" method="get">
<div class="form-group">
<input type="text" class="form-control" id="typeCours" list="matieres" placeholder="Matieres: e.g. Math, Physique,.." name="discipline">
<datalist id="matieres">
<option value="value1">
<option value="value2">
</datalist>
</div>
<div class="form-group">
<input type="text" class="form-control" id="Localisation" placeholder="Lieu: Bousaada, Douaouda,.."
name="localisation" onFocus="geolocate()">
</div>
<button type="submit" class="btn btn-default" id="btn-getLessons">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span> Trouver !
</button>
</form>
I want to get the Posts by applying a filter according to the lacalisation and matieres introduced in the search fields (in the form)
You can add the search terms to your url regular expression.
url(r'postsearch/(?P<localisation>\w+)/(?P<descipline>\w+)/$', views.PostsList.as_view(), name='postsearch'),
(Note, mind the trailing slash)
In your get_queryset method you can use those given url parameters
def get_queryset(self):
localisation = self.kwargs['localisation'] or None
discipline = self.kwargs['discipline'] or None
filters = {}
if localisation:
filters.update(localisation: localisation)
if discipline:
filters.update(discipline: discipline)
return Post.objects.filter(**filters)
Eventually you should relocate getting the parameters outside your get_queryset, but that is up to you.
I'm not sure about the security risks doing it this way. Anyone having more information about the security risks during this operation, please share.
I build a library that can help you to solve this problem, you just have to put in the searchable_fields the attributes you want to filter and it will take care of the rest.
https://github.com/SchroterQuentin/django-search-listview

django ModelMultipleChoiceField display in template

class AddRoleForm(forms.Form):
roles=forms.ModelMultipleChoiceField(queryset=Role.objects.all(),widget=forms.CheckboxSelectMultiple())
in the template :
{{ form.roles }}
the result is like this:
<ul>
<li><label for="id_roles_0"><input type="checkbox" value="1" name="roles" id="id_roles_0"> User object</label></li>
<li><label for="id_roles_1"><input type="checkbox" value="2" name="roles" id="id_roles_1"> User object</label></li>
</ul>
I want to show the role's name in each line and get the role's id in the chebox
like:
<ul>
<li><label for="id_roles_0"><input type="checkbox" value="100" name="roles" id="id_roles_0">boss</label></li>
<li><label for="id_roles_1"><input type="checkbox" value="101" name="roles" id="id_roles_1">employee</label></li>
</ul>
What should i do?
check your model 'Role'
you need add
def __unicode__(self):
return self.name
I think you this post can possibly help you.
Have a look at: Django - Render CheckboxSelectMultiple() widget individually in template (manually)
To change value parameter you have to do those steps:
Write your own CheckboxInput and overload render function. You have to change
final_attrs['value'] = force_text(value)
to something like that:
final_attrs['value'] = force_text(str(int(value) + 99))
Other parts can be copied without changes.
Write your own CheckboxSelectMultiplue and overload render function. You have to change
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
to your implementation of CheckboxInput.
Use your new widget instead of built-in.
NOTE: Parts of code may differs, because they can depends of Django version
About issue with User object: I'm not sure, but try to check your __unicode__ function.

Existing forms:In Django

I have an pre-built HTML form and I need to reuse it with Django form class (django.forms), So how do I incorporate my HTML form with Django form class. for example
HTML:
<li id="foli11" class="">
<label class="desc" id="title11" for="Field11">
Username
<span id="req_0" class="req">*</span>
</label>
<div class="col">
<input id="Field11" name="Field11" type="text" class="field text medium" value="" maxlength="255" tabindex="11" />
</div>
</li>
How do I map this HTML in to Django form class, I know that it can be done by modifying Django form fields according to this HTML. But I guess it's a time consuming approach,so I would like to know that is there any easy and time saving solutions for this issue.
Thanks.
Extend the django forms.Form class and write to it your own form.as_my_ul similar to form.as_p:
Here is the implementation of as_p: http://code.djangoproject.com/browser/django/trunk/django/forms/forms.py#L227
def as_p(self):
"Returns this form rendered as HTML <p>s."
return self._html_output(
normal_row = u'<p%(html_class_attr)s>%(label)s %(field)s%(help_text)s</p>',
error_row = u'%s',
row_ender = '</p>',
help_text_html = u' %s',
errors_on_separate_row = True)