setting initial values for more then one form - django

I have looked at some examples but none of them have worked for me.
What i have is List of Locations and the user has the choice to add them to a group. First step is he gives the group a name. And then he can choose from the locations which are already in the database, to add them to the group name.
To put it simple i want to loop 3 form elements for each location, and attach initial values for each location, so it can be stored inside a group.
This is what i want to see:
<form>
<input type="text" label="group_name">
First Location
<input type="hidden" value="street_name">
<input type="hidden" value="location_name">
<input type="checkbutton">
Second location
<input type="hidden" value="street_name2">
<input type="hidden" value="location_name2">
<input type="checkbutton">
and so on
<input type="submit" value="Create this Group">
</form>
I have tried it like this:
Froms.py is currently missing the check input for True and False.
FORMS.py:
class GroupAddForm(forms.ModelForm):
groupname = forms.CharField(label='',widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
page_name = forms.CharField(label='' ,widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
page_street = forms.CharField(label='' ,widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
class Meta:
model = GroupManagement
fields = ['groupname', 'page_name', 'page_street']
VIEW:
def page_groups(request):
email =request.user.email
locationdata = LocationData.objects.filter(email=email).values_list(
'id',
'name',
'street',
'postal_code',
'tel',
'website',
'description',
'fb_page_id'
)
form = []
for items in locationdata:
name = items[1]
form = GroupAddForm(request.POST or None, initial={"page_name": name})
print(form)
context = {
'locationdata': locationdata,
'form': form,
}
return render(request, 'page_groups.html', context)
OR in the Template:
<form method="POST" action=""> {% csrf_token %}
{% for items in locationdata %}
{{items.1}}
{{form.fields.page_name.value|default:items.1}}
{{form}}
{% endfor %}
</form>
Inside the View only the last element is attached to the form.
The initial Value inside the Template doesn't work at all.

Fixed it myself.
for items in locationdata:
name = items[1]
form = GroupAddForm(request.POST or None, initial={"page_name": name})
forms.append(form)
<form method="POST" action=""> {% csrf_token %}
{% for items in forms %}
{{items}}
{% endfor %}
</form>

Related

How to disable fields validation if we want to go to the previous step?

I am using the django's form wizard in the authentication system.
I have 2 form wizards steps. In the second, I have two buttons: the Prev Step button and the Submit button. When the Prev Step button is used to go backwards, I get the django's warning to fill out the field.
How do I disable validations for the Prev Step button and keep the validations for the Submit button?
I already disabled the javascript validations for the Prev Step button.
My html:
<!-- Forms -->
{{ wizard.management_form }}
{% for field in wizard.form %}
<div class="wrap-input100 rs1-wrap-input100 validate-input m-b-20">
{{ field }}
<span class="focus-input100"></span>
</div>
{% endfor %}
<!-- Buttons -->
{% if wizard.steps.next %}
<div class="container-login100-form-btn">
<button type="submit" value="{{ wizard.steps.next }}" class="login100-form-btn">Next step</button>
</div>
{% else %}
<div class="container-login100-form-btn">
<div class="split-left">
<button type="submit" value="{{ wizard.steps.prev }}" class="login100-form-btn" formnovalidate>Prev step</button>
</div>
<div class="split-right">
<button type="submit" class="login100-form-btn">Sign up</button>
</div>
</div>
{% endif %}
views:
class signup(SessionWizardView):
template_name='accounts/signup.html'
form_list = [UserCreationForm_1, UserCreationForm_2]
def done(self, form_list, **kwargs):
form_step = [form for form in form_list]
# step 1: ModelForm
user = form_step[0].save()
auth_login( self.request, user )
# step 2: Form
user = form_step[1].save()
return redirect( 'home' )
forms:
class UserCreationForm_1(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput(attrs={'class':'input100', 'placeholder': 'Password'}))
password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class':'input100', 'placeholder': 'Repeat Password'}))
class Meta:
model = MyUser
fields = ('shown_name', 'email')
widgets = {
'email': forms.EmailInput(attrs={'class':'input100', 'placeholder': 'Email'}),
'shown_name': forms.TextInput(attrs={'class':'input100', 'placeholder': 'User name'}),
}
class UserCreationForm_2(forms.Form):
name = forms.CharField( max_length=40, widget=forms.TextInput(attrs={'class':'input100', 'placeholder': 'Name'}) )
date_of_birth = forms.DateField( widget=forms.DateInput(attrs={'class':'input100', 'placeholder': 'Date of Birth'}) )
phone = PhoneNumberField( widget=forms.TextInput(attrs={'class':'input100', 'placeholder': 'Phone'}) )
In the second form wizard step, when I use the Prev button, this happens:
https://imgur.com/54VvvZx
When I use the Submit button, this happens:
https://imgur.com/JLCYMmr
The problem had nothing to do with Django. It was a javascript problem. I only had to remove the class validate-input from the forms' div.

ValidationError when submitting a form with custom date format

When submitting a django form i am getting a ValidationError.
In my form this is my input: 01/01/2017
But django tell me that the format must be 'AAAA-MM-GG'.
With this Exception Location: /usr/local/lib/python3.5/dist-packages/django/db/models/fields/init.py in to_python, line 1271
This is the code on my project:
# models.py
class Archivio(models.Model):
sys_codice = models.AutoField(primary_key=True)
some_other_field ...
class QuoteIscrizione(models.Model):
sys_chiave = models.AutoField(primary_key=True)
sys_cod = models.ForeignKey(Archivio, on_delete=models.CASCADE)
data_quota = models.DateField(blank=True, null=True)
# forms.py
class ArchivioSearchForm(forms.Form):
data_quota = forms.DateField(widget=forms.DateInput(format='%d/%m/%Y'), input_formats=('%d/%m/%Y',), required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self:
field.field.widget.attrs['class'] = 'form-control '
if type(field.field.widget) is DateInput:
field.field.widget.attrs['class'] += 'datepicker'
def clean(self):
data_quota = self.cleaned_data['data_quota']
return self.cleaned_data
# views.py
def ArchivioSearchView(request):
model = Archivio
form = ArchivioSearchForm()
if request.GET.get('data_quota'):
selection = Archivio.objects.filter(Q(quoteiscrizione__data_quota__gte=request.GET.get('data_quota'))
return render(request, 'search_template.html', {'selection':selection, 'form':form})
# search_template.html
<form action="" method="get" class="form-horizontal">
<div class="form-group form-group-md">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{% for field in form %}
<div class="form-group row">
<label class="col-md-3 col-form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="col-md-6">
{{ field.as_widget() }}
</div>
</div>
{% endfor %}
<input type="submit" value="Confermo" />
</div>
</form>
{% for select in selection %}
<h4><li>{{ select.nominativo }}</li></h4>
{% endfor %}
And I also have this on my settings.py
LANGUAGE_CODE = 'it-IT'
TIME_ZONE = 'Europe/Rome'
USE_I18N = True
USE_L10N = True
USE_TZ = True
I have tried to use on my settings.py of course after turning USE_L10N = False
DATE_INPUT_FORMATS = ['%d/%m/%Y']
I have tried also to use on my forms.py on init function on for loop:
if type(field.field.widget) is DateInput:
field.field.widget.input_formats = ['d%/%m/%Y']
I have tried not only with Lists but also with strings like this '%d/%m/%Y'.
I also see that this error occur even if my input is 2017/01/01!
I cannot figure out what I am doing wrong. Django continues expecting dates in format 'YYYY-MM-DD' even if I override every possible method or parameter of DateField's widget.
Thank to all of you that will take some of your time trying to help me!
You need to set formats on DateInput widget when you declare your variable on the form, plus input_formats, like:
data_quota = forms.DateField(widget=forms.DateInput(format ='%d/%m/%Y'), input_formats=('%d/%m/%Y',), required=False)

Autocomplete-light registry issues

I am trying to install autocomplete-light into one of my forms. I keep getting this error:
Institution not registered, you have registered: ['InstitutionAutocomplete']
I have not declare or registered InstitutionAutocopmlete anywhere in my code so I don't know how I could have triggered this error.
I have the following form:
class AddUserAccountsForm(forms.ModelForm):
"""
Form for adding new user financial accounts.
"""
required_css_class = 'required'
name = forms.ModelChoiceField(required=True, queryset=Institution.objects.all(), widget=autocomplete_light.ChoiceWidget('Institution'))
user_accounts_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'User Name'}), label="")
user_accounts_password = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Password'}), label="")
class Meta:
model = Institution
fields = ('name','user_accounts_name', 'user_accounts_password',)
This is in my autocomplete_light_registry.py:
import autocomplete_light
from models import Institution
autocomplete_light.register(Institution,
search_fields = ['name'],
attrs={
'placeholder':'Find your institution',
'data-autocomplete-minimum-characters':1,
},
widget_attrs={
'data-widget-maximum-values':4,
'class':'modern-style',
},
)
Here is my html. The error is triggered when the code runs {{ form.as_p}}.
{% load staticfiles %}
<script type="text/javascript" src="{% static 'jquery.js' %}">
</script>
{% include 'autocomplete_light/static.html' %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
urls.py is:
url(r'^profile/add_user_accounts/', UserAccountsUpdate.as_view(), name='add_user_accounts'),
In your form you have to use 'InstitutionAutocomplete' instead of 'Institution'
name = forms.ModelChoiceField(required=True,
queryset=Institution.objects.all(),
widget=autocomplete_light.ChoiceWidget('InstitutionAutocomplete'))

Appended Form Element only returns one set of data

i tried to return multiple Form Elements with the same name, however i only get the last element not all of them. In my View it works and shows all elements, once i hit submit only the last Element returns (in this case 3 times). Why is that?
forms.py:
class GroupAddForm(forms.ModelForm):
email = forms.EmailField(label='' ,widget=forms.HiddenInput(attrs={'class': 'form-control'}))
page_name = forms.CharField(label='' ,widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
page_street = forms.CharField(label='' ,widget=forms.HiddenInput(attrs={'rows': '4', 'class': 'form-control'}))
add_button = forms.BooleanField(label='', required=False, widget=forms.CheckboxInput(attrs={'rows': '4', 'class': 'form-control'}))
class Meta:
model = GroupManagement
fields = ['email', 'page_name', 'page_street', 'add_button']
View.py
for items in locationdata:
show_name.append(items[1])
show_street.append(items[2])
name = items[1]
street = items[2]
form = GroupAddForm(request.POST or None, initial={"page_name": name, "page_street": street, "email": email})
forms.append(form)
for item in forms:
if item.is_valid():
email = item.cleaned_data.get("email")
page_name = item.cleaned_data.get("page_name")
page_street = item.cleaned_data.get("page_street")
add_button = item.cleaned_data.get("add_button")
if add_button == true:
//// do stuff
context = {
'names': names,
'street': street,
'group_name_form': group_name_form,
'locationdata': locationdata,
'forms': forms,
}
Template:
<div class="modal-body">
<div class="col-md-12">
<form method="POST" action=""> {% csrf_token %}
{{group_name_form.as_p}}
<div class="col-md-6 pull-left">
{% for items in names %}
<p style="text-align:left;"> {{items.0}} {{items.1}} </p>
{% endfor %}
</div>
<div class="col-md-6">
{% for items in forms %}
{{items.as_p}}
{% endfor %}
</div>
</div>
<input type="submit" class="btn btn-success" value="Gruppe erstellen"></form>
</div>
The correct way to have multiple instances of the same form class is to use formsets.

How do I display the value of a Django form field in a template?

I have a form with an email property.
When using {{ form.email }} in case of some validation error, Django still renders the previous value in the input tag's value attribute:
<input type="text" id="id_email" maxlength="75" class="required"
value="some#email.com" name="email">
I want to render the input tag myself (to add some JavaScript code and an error class in case of an error). For example this is my template instead of {{ form.email }}:
<input type="text" autocomplete="on" id="id_email" name="email"
class="email {% if form.email.errors %} error {% endif %}">
However, this does not display the erroneous value (some#email.com in this example) to the user.
How do I get the field's value in the template?
This was a feature request that got fixed in Django 1.3.
Here's the bug: https://code.djangoproject.com/ticket/10427
Basically, if you're running something after 1.3, in Django templates you can do:
{{ form.field.value|default_if_none:"" }}
Or in Jinja2:
{{ form.field.value()|default("") }}
Note that field.value() is a method, but in Django templates ()'s are omitted, while in Jinja2 method calls are explicit.
If you want to know what version of Django you're running, it will tell you when you do the runserver command.
If you are on something prior to 1.3, you can probably use the fix posted in the above bug: https://code.djangoproject.com/ticket/10427#comment:24
You can do this from the template with something like this:
{% if form.instance.some_field %}
{{form.instance.some_field}}
{% else %}
{{form.data.some_field}}
{% endif %}
This will display the instance value (if the form is created with an instance, you can use initial instead if you like), or else display the POST data such as when a validation error occurs.
I have a simple solution for you!
{{ form.data.email }}
I tried this and it worked. This requires your view to populate the form class with the POST data.
Very simple example:
def your_view(request):
if request.method == 'POST':
form = YourForm(request.POST)
if form.is_valid():
# some code here
else:
form = YourForm()
return render_to_response('template.html', {'form':form})
Hope that helps you. If you have any questions please let me know.
This seems to work.
{{ form.fields.email.initial }}
{{ form.field_name.value }} works for me
The solution proposed by Jens is correct.
However, it turns out that if you initialize your ModelForm with an instance (example below) django will not populate the data:
def your_view(request):
if request.method == 'POST':
form = UserDetailsForm(request.POST)
if form.is_valid():
# some code here
else:
form = UserDetailsForm(instance=request.user)
So, I made my own ModelForm base class that populates the initial data:
from django import forms
class BaseModelForm(forms.ModelForm):
"""
Subclass of `forms.ModelForm` that makes sure the initial values
are present in the form data, so you don't have to send all old values
for the form to actually validate.
"""
def merge_from_initial(self):
filt = lambda v: v not in self.data.keys()
for field in filter(filt, getattr(self.Meta, 'fields', ())):
self.data[field] = self.initial.get(field, None)
Then, the simple view example looks like this:
def your_view(request): if request.method == 'POST':
form = UserDetailsForm(request.POST)
if form.is_valid():
# some code here
else:
form = UserDetailsForm(instance=request.user)
form.merge_from_initial()
I tried a few of the mentioned possibilities, and this is how I solved my problem:
#forms.py
class EditProfileForm(forms.ModelForm):
first_name = forms.CharField(label='First Name',
widget=forms.TextInput(
attrs={'class': 'form-control'}),
required=False)
last_name = forms.CharField(label='Last Name',
widget=forms.TextInput(
attrs={'class': 'form-control'}),
required=False)
# username = forms.CharField(widget=forms.TextInput(
# attrs={'class': 'form-control'}),
# required=True)
address = forms.CharField(max_length=255, widget=forms.TextInput(
attrs={'class': 'form-control'}),
required=False)
phoneNumber = forms.CharField(max_length=11,
widget=forms.TextInput(
attrs={'class': 'form-control'}),
required=False)
photo = forms.ImageField(label='Change Profile Image', required=False)
class Meta:
model = User
fields = ['photo', 'first_name', 'last_name', 'phoneNumber', 'address']
# 'username',
#views.py
def edit_user_profile(request, username):
user = request.user
username = User.objects.get(username=username)
user_extended_photo = UserExtended.objects.get(user=user.id)
form = EditProfileForm(request.POST or None, request.FILES, instance=user)
user_extended = UserExtended.objects.get(user=user)
if request.method == 'POST':
if form.is_valid():
# photo = UserExtended(photo=request.FILES['photo'] or None, )
user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user_extended.address = request.POST['address']
user_extended.phoneNumber = request.POST['phoneNumber']
user_extended.photo = form.cleaned_data["photo"]
# username = request.POST['username']
user_extended.save()
user.save()
context = {
'form': form,
'username': username,
'user_extended_photo': user_extended_photo,
}
return render(request, 'accounts/profile_updated.html', context)
else:
photo = user_extended.photo
first_name = user.first_name
last_name = user.last_name
address = user_extended.address
phoneNumber = user_extended.phoneNumber
form = EditProfileForm(
initial={'first_name': first_name, 'last_name': last_name,
'address': address, 'phoneNumber': phoneNumber,
'photo': photo})
context = {
'form': form,
'username': username,
'user_extended_photo': user_extended_photo,
}
return render_to_response('accounts/edit_profile.html', context,
context_instance=RequestContext(request))
#edit_profile.html
<form action="/accounts/{{ user.username }}/edit_profile/" method="post" enctype='multipart/form-data'>
{% csrf_token %}
<div class="col-md-6">
<div class="form-group">
{{ form.as_p }}
</div>
</div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button type="submit" value="Update Profile" class="btn btn-info btn-fill pull-right">Update Profile</button>
<div class="clearfix"></div>
</form>
I am trying to explain this in a way so that beginners may find it easier to understand. Pay close attention to the else:
photo = user_extended.photo
first_name = user.first_name
last_name = user.last_name
address = user_extended.address
phoneNumber = user_extended.phoneNumber
form = EditProfileForm(
initial={'first_name': first_name, 'last_name': last_name,
'address': address, 'phoneNumber': phoneNumber,
'photo': photo})
It is what gets the value attrib, e.g.:
<p><label for="id_first_name">First Name:</label> <input class="form-control" id="id_first_name" name="first_name" type="text" value="Emmanuel" /></p>
<p><label for="id_last_name">Last Name:</label> <input class="form-control" id="id_last_name" name="last_name" type="text" value="Castor" /></p>
If you've populated the form with an instance and not with POST data (as the suggested answer requires), you can access the data using {{ form.instance.my_field_name }}.
I wanted to display the value of a formset field. I concluded this solution, which should work for normal forms too:
{% if form.email.data %} {{ form.email.data }}
{% else %} {{ form.initial.email }}
{% endif %}
The above solutions didn't worked very well for me, and I doubt they would work in case of prefixed forms (such as wizards and formsets).
The solutions using {{ form.data.email }} can't work, because it is a dictionary lookup, and with prefixed forms your field name would look something like '1-email' (wizard and prefixed form) or 'form-1-email' (formset), and the minus sign (-) are not allowed in dotted template lookup expressions.
{{form.field_name.value}} is Django 1.3+ only.
For check box with its items:
{% for item in people.q %}
<div class="form-check form-switch ">
<label class="form-check-label" for="{{ item.id_for_label }}">{{ item.data.label }}</label>
<input class="form-check-input" type="checkbox" id="{{ item.id_for_label }}" value="{{ item.data.value }}">
</div>
{% endfor %}
q is field name.
On Django 1.2, {{ form.data.field }} and {{ form.field.data }} are all OK, but not {{ form.field.value }}.
As others said, {{ form.field.value }} is Django 1.3+ only, but there's no specification in https://docs.djangoproject.com/en/1.3/topics/forms/. It can be found in https://docs.djangoproject.com/en/1.4/topics/forms/.
{{form.fields.email}}