Using Datepicker in Django - django

I am using Django and Datepicker together with Twitter-Bootstrap and I want the form.fields to have same class and same id if they are of same widget(DateInput). In specific, i would like to change the id accordingly. It should have a different id every time.
This is the class i defined below. How do i change the id to be a different one every time.
class MyDatePicker(forms.DateInput)
def __init__(self, *args, **kwargs):
attrs = kwargs.pop("attrs",{})
attrs["class"] = "datepick"
attrs["id"] ="date_1"
kwargs["attrs"] = attrs
super(MyDatePicker, self).__init__(*args, **kwargs)
How do i go about doing it?Need some help on it...Would welcome any suggestion...

You could register a templatetag to find out the widget type:
#register.filter('klass')
def klass(obj):
return obj.__class__.__name__
Then in your template:
{% load your_filter_module %}
<form id="form" enctype="multipart/form-data" class="form-horizontal" method="POST" action="">{% csrf_token %}
<fieldset>
{{ form.non_field_errors }}
{% for field in form %}
<div class="control-group{% if field.errors %} error{% else %}{% if form_errors %} success{% endif %}{% endif %}">
<label class="control-label" for="{{ field.auto_id }}">{% trans field.label %}</label>
<div class="controls">
{% if field.field.widget|klass == "CheckboxInput" %}
<label class="checkbox">
<input type="checkbox" id="{{ field.auto_id }}" name="{{ field.name }}"{% if field.value == "on" %} checked{% endif %}>
{% trans "Some random text" %}
</label>
{% endif %}
# ... etcetera continue check for other classes ...
Note: A cleaner DRY approach would be to add the loop and class logic (horizontal/vertical etc) to a filter returning a html widget

Related

My django form is not working when i iterate through it using for loop

Basically if I tried to use this code
{% for field in form %}
<div class="input">
<label for="" class="labelinput">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
the form data wont make it pass is_valid().But it renders out the form fine. and if I use this code
<form action="" method="post"> {% csrf_token %}
{{form}}
<input type="submit" value="">
it worked perfectly fine. How do I get the first code to work because I want to add classes between the label and the input field
and here's my view
def booklist_view(request):
bkff = BookListForm()
if request.method == 'POST':
bkff = BookListForm(request.POST)
if bkff.is_valid():
bkff.save()
bkff = BookListForm()
context = {
'form': bkff,
}
return render(request, 'booklist1st/booklist.html', context)
Please try this.
views.py
def booklist_view(request):
form = BookListForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
context = {'form': form }
return render(request, 'booklist1st/booklist.html', context)
Here we render field according according to field type(hidden_fields,visible_fields).
html template:
<form method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="input">
{{field.label}}
{{field}}
</div>
{% endif %}
<input class="btn btn-primary" type="submit" name="add_book" value="Save and add book" />
</form>
You need to specify each field relate data like for=, id=, etc. To have maximum control over how your form is rendered, specify each field and control its style, for example, as we can't see your Form definition, this is an example on how it would be for a title field:
<form method="post">{% csrf_token %}
{# Include the hidden fields #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #}
{{ form.non_field_errors }}
{{ form.title.errors }}
<label for="{{ form.title.id_for_label }}">Title</label>
{{ form.title }}
{% if form.title.help_text %}
<small id="titleHelp">{{ form.title.help_text|safe }}</small>
{% endif %}
</div>
<input class="btn btn-primary" type="submit" name="add_book" value="Save and add book" />
</form>
<form method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="input">
<label for="" class="label">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<input class="btn btn-primary" type="submit" name="add_book" value="Save and add book" />
</form>
View.py
from django.views.decorators.csrf import csrf_protect
#csrf_protect
def booklist_view(request):
bkff = BookListForm()
if request.method == 'POST':
bkff = BookListForm(request.POST)
if bkff.is_valid():
bkff.save()
context = {
'form': bkff,
}
return render(request, 'booklist1st/booklist.html', context)

Django, best way to print a field key

I want to print fields of a model differently than by first_name
I want to print something like "key: value" but it prints "first_name: Georges", I would prefer that it's looks like "First name: Georges"
Currently i'm using a file named form.html that I include in every form template:
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text }}
</small>
{% endif %}
</div>
{% endfor %}
And a model that looks like this:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
What is the best way to print first_name as "First name"?:
Is it by setting verbose_name for every fields in the models.py?
Or by setting label in the forms.py for every fields in each form?
Or by not using a dynamic template and hardcode it in my form.html?
Like what Aleksei Maide said to change that you need to alter the Label, here is an example:
in your form class add a method:
def __init__(self, *args, **kwargs):
super(YourFormName, self).__init__(*args, **kwargs)
self.fields['first_name'].label = "First name"
this is how i'm displaying it in my template:
<label class="bmd-label-static">{{ field.label }}</label>
{{ field.name }}
Think by a moment that you have a Model Form with 30 fields, and as this form, you have other 30 more Model Forms, now, you have to set every time your field labels, is a very complicated task, don't you think?
i could suggest you that use the verbose name feature to each model field and build a simple template tag that can help you to get dinamicaly the verbose name of your fields i your templates
This template tag will try to get the model field's verbose name
# yourapp/templatetags/yourapp_extras.py
from django import template
register = template.Library()
#register.simple_tag
def field_name(model, field):
field_name = field
if model:
try:
field_name = model._meta.get_field(field).verbose_name.title()
except Exception as ex:
print ex
return field_name
And in your template you can display your field label as follow
# sometemplate.html
{% load widget_tweaks %}
{% load yourapp_extras %}
{% for field in form %}
<div class="form-group">
{% field_name model field.name %} <!-- here -->
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text }}
</small>
{% endif %}
</div>
{% endfor %}

Django formset not rendering with django-widget-tweaks

I am getting the error 'LoginForm' object has no attribute 'as_widget' whenever I use formset. I really do not know what is the problem as the forms renders properly with normal Django forms. I am trying to see what characteristics in the formset is giving this problem with django-widget-tweaks, but up until now it is hard to figure out. I am getting the error at {% render_field field class="form-control" placeholder=field.label %} in the HTML code.
forms.py:
class LoginForm(ModelForm):
user_login = forms.HiddenInput()
prefix = 'prefix_login'
class Meta:
model = Usermie
fields = ['email', 'password']
widgets = {'password': forms.PasswordInput(),
'email': forms.EmailInput()}
views.py
def manage_articles(request):
article_formset = formset_factory(LoginForm)
book_formset = formset_factory(SignUpForm)
if request.method == 'POST':
if 'login' in request.POST:
login = article_formset(request.POST, request.FILES, prefix='login')
if login.is_valid():
email = request.POST.get('prefix_login-email', '')
password = request.POST.get('prefix_login-password', '')
# Return a user_obj object if the username and password are valid
# otherwise it will return null, the null variable is called None in python
user_obj = auth.authenticate(email=email, password=password)
# return HttpResponse("inside form if condition")
if user_obj is not None:
if user_obj.is_active:
login_usermie(request, user_obj)
return HttpResponseRedirect('/home/')
else:
# pass
return HttpResponse("Your account is inactive.")
elif 'signup' in request.POST:
signup = book_formset(request.POST, request.FILES)
if signup.is_valid():
pass
else:
login = article_formset
signup = book_formset
return render(request, 'usermie/formtest.html', {
'login': login,
'signup': signup,
})
HTML:
<div class="navbar navbar-default nav-links navbar-static-top page-nav">
<div class="container">
<a class="mini-navbar navbar-brand" href="/">
<img src="http://i.imgur.com/GAQSCtB.png" width="25"
alt="Driven Car Sales Logo"
class="img-rounded logo-nav mini-navbar" />
</a>
<ul class="nav navbar-nav nav-form-out pull-right">
<li>
<form class="navbar-form navbar-form-out login" action="" method="POST">
{% csrf_token %}
{% load widget_tweaks %}
{% for field in login %}
{% if login.errors %}
<div class="form-group">
<label class="sr-only" for="{{ field.auto_id }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
{% if field == login.password %}
{% for hidden in field.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
<div class="help-block with-errors">{{ field.errors }}</div>
</div>
{% else %}
<div class="form-group">
<label class="sr-only" for="{{ field.auto_id }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
{% if field == login.password %}
{% for hidden in field.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
</div>
{% endif %}
{% endfor %}
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
<button type="submit" name="action" value="login" class="btn btn-default">Sign in</button>
</form>
</li>
</ul>
</div>
<form class="signup" method="POST" action="">
{% csrf_token %}
{{ signup.as_p }}
<button name='action' value='signup' type="submit">Sign up</button>
</form>
login variable in template is a formset. So when you do following:
{% for field in login %}
{% render_field field class="form-control" placeholder=field.label %}
{% endfor %}
you have form as field value and not a field.
Try do this:
{% for form in login %}
{% for field in form %}
{% render_field field class="form-control" placeholder=field.label %}
{% endfor %}
{% endfor %}

django form wizard, does not go to second step

I am trying to perform the following using Django :
Wizard containing two formds
First form is a simple form containing some Ajax to compute automatically some fields
Second form is a user registration
The problem is the following :
The first form is displayed correctly and the Ajax within the page is working fine
The second form is never displayed after pushing on the button "submit"
The code is as follows :
urls.py
from forms import InsertPropertyForm1, InsertPropertyForm2
from views import InsertPropertyWizard
urlpatterns = patterns('',
url(r'^addProperty/$', InsertPropertyWizard.as_view([InsertPropertyForm1, InsertPropertyForm2]), name='addProperty'),
)
views.py
FORMS = [("property", InsertPropertyForm1),
("test", InsertPropertyForm2)
]
TEMPLATES = {'0': 'realEstate/addProperty.html',
'1' : 'realEstate/test.html',
}
class InsertPropertyWizard(SessionWizardView):
def get_template_names(self):
print ("next step !!!!! " + str(self.steps.current))
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
print "Wizard done"
#do_something_with_the_form_data(form_list)
return HttpResponseRedirect('http://TO_FILL_IN')
realEstate/addProperty.html
{% extends 'realEstate/base.html' %}
{% load socialaccount %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<h1> Insert an ad </h1>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form class="form-horizontal" role="form" action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
</table>
{{ form.non_field_errors }}
<fieldset>
<legend>Localisation</legend>
<div class="form-group">
{{ form.country.errors }}
<label class="col-lg-1" for="id_country">{{form.country.label}}</label>
<div class="col-lg-1">
{{ form.country }}
</div>
</div>
</fieldset>
</fieldset>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "first step" %}
</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}
</button>
{% endif %}
<input type="submit" value="{% trans "submit" %}"/>
</form>
{% endblock %}
Just thought it could help someone.
Problem was that one of the field was not defined in the form and I forgot to include it in the template.
The behaviour of the wizard was correct. It got stuc on the first page but did not display the error on the screen as the field was not displayed.
Got me crazy but it was my fault.
Cheers

Trying to access ModelForm field modelChoice choices in Django template

I'm generating ModelForms and want some granular control over how they are output in my template. Specifically, I need to add some markup to the end of each radio button in each of my select lists.
Code:
# order-form.html
{% load catname %}
<form id = "order-form">
{% for form in forms %}
<div id="gun-{{ forloop.counter }}">
{% for field in form.fields %}
<div id="{{ field }}-item" class="item">
<h3>{{ field|catname }}</h3>
{% for choice in form.field.choices %} {# <-- Help me out here #}
{{ choice.id }}
{{ choice.title }}
{% endfor %}
</div>
{% endfor %}
{% endfor %}
<button type="submit" id="standard-gun-form-submit">Continue to next step</button>
</form>
# views.py
def get_form(request):
if request.method == 'POST':
if request.POST['gun_type'] == 'standard':
forms = [StandardGunForm(prefix=p) for p in range(0,2)]
return render_to_response('main/order-form.html', {'forms' : forms,}, RequestContext(request))
# forms.py
class StandardGunForm(ModelForm):
def __init__(self, *args, **kwargs):
super(StandardGunForm, self).__init__(*args, **kwargs)
for field in self.fields:
if isinstance(self.fields[field], ModelChoiceField):
self.fields[field].empty_label = None
class Meta:
model = BaseGun
widgets = {
'FrameTuning' : RadioSelect(),
'FrameConnection' : RadioSelect(),
}
exclude = ('price')
Endgame: markup that looks like this
<form id="foo">
<div class="category">
<div class="item">
<input type="radio" name="srsbzns" value="1">Option 1</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
<div class="item">
<input type="radio" name="srsbzns" value="2">Option 2</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
<div class="item">
<input type="radio" name="srsbzns" value="3">Option 3</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
</div>
</form>
From the shell, this returns what I want
>>> forms = [StandardGunForm(prefix=p) for p in range(0,2)]\
>>> forms[0].fields['frame_tuning'].choices.queryset
I'm surprised this is proving so challenging!
Bonus: I have DEBUG = True and Django Debug toolbar enabled. Is it possible to dump the variables to the browser, so I can see what this stuff looks like as I drill down?
Thanks!
I had to do something similar and started down this path as well. I wanted to create table rows from a ModelChoiceField where each column had a different field of the model instance (and then I'd allow filtering the table rows via JavaScript).
I couldn't find it in the Django docs, but a quick perusal of the Django source showed the way. You can get to the queryset to access the model instances like so:
<form action="{% url 'some_view' %}" method="post">
{% csrf_token %}
{% if form.non_field_errors %}
{{ form.non_field_errors }}
{% endif %}
{% for field in form %}
{{ field.label }}
{% if field.field.choices %}
{% for model_instance in field.field.choices.queryset %}
{{ model_instance.id }}
{% endfor %}
{% else %}
{{ field }}
{% endif %}
{% if field.errors %}
{{ field.errors|striptags }}
{% endif %}
{% endfor %}
<button type="submit">Submit</button>
</form>
However, at this point we've disassembled the shiny widget (in my case a CheckboxSelectMultiple) and must re-assemble the HTML form input using template code. I found no direct way to simultaneously iterate over the ModelChoiceField to access the model instance fields and get the HTML form tags for the choices.
Maybe there's a way, but I abandoned my attempt and built my own HTML form, handling all the POST data in a view. It ended up much easier that way. ModelForms are really nice and convenient, but using them for something they weren't built for can end up being more difficult.
I figured I'd post this in case anyone is trying to do it for some other reason. Hope it helps.
Very late, but I'm reading now and this is what it worked for me
{% for field in form %}
{% for x, y in field.field.choices %}
{{x}}
{{y}}
{% endfor %}
{% endfor %}
Where "x" is the id or code, and "y" is the readable value or title.
You can access the underlying model instance for each choice:
{% for choice, label in form.field_name.field.choices %}
{{ choice.value }}
{{ choice.instance }}
{{ choice.instance.instance_attribute }}
{{ label }}
{% endfor %}
{% for choice in form.field.choices %} {# <-- Help me out here #}
{{ choice.id }}
{{ choice.title }}
{% endfor %}
Look what you're doing here, you're literally trying to access a field called "field" every time in this loop, which presumably does not exist.
You need to take the field object you're iterating through, and access the choices attribute on that.
{% for field in form.fields %}
{% for choice in field.choices %}