I have the following form:
class UpdateForm(forms.Form):
name = forms.CharField(max_length = 15,
widget=forms.TextInput(
attrs={
"class": "form-control",
'required': True,
'placeholder': 'Device name'
}
))
turn_server = forms.ChoiceField(
choices = TURN_CHOICES,
widget=forms.Select(
attrs={
"class": "form-control form-control-sm",
}
))
fps = forms.IntegerField(
widget=forms.NumberInput(
attrs={
'id':'ex1',
'data-slider-id':'ex1Slider',
'type':"text",
'data-slider-min':"10",
'data-slider-max':"60",
'data-slider-step':"1",
}
))
bitrate = forms.IntegerField(
widget=forms.NumberInput(
attrs={
'id':'ex2',
'data-slider-id':'ex2Slider',
'type':"text",
'data-slider-min':"200",
'data-slider-max':"2000",
'data-slider-step':"1",
}
))
class Meta:
model = Device
fields = ['name','fps','bitrate','turn_server']
to be used in the HTML template:
<form action="." method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group row{% if field.errors %} invalid{% endif %}">
<label class="col-sm-3 col-form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="col-sm-6">
{{ field }}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-sm btn-light">Save</button>
</form>
and the view.py:
def control(request):
template = 'template.html'
context = {}
context['form'] = UpdateForm(initial={
'name': 'TestName',
'fps': '45',
'turn_server':'TestServer',
'bitrate':'500'
})
return render(request, template, context)
For some reason I can't figure it out, the form rendered in the template does not render with the initial values I have defined with initial. For example the fps resulted input html element is the following:
<input type="text" name="fps" value="10" id="ex1" data-slider-id="ex1Slider" data-slider-min="10" data-slider-max="60" data-slider-step="1" required="" data-value="10" style="display: none;">
Oddly, If I print in the views.py the form that is passed to the context I get the correct form data (ex value=45):
<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" value="TestName" class="form-control" required placeholder="Device name" maxlength="15" id="id_name"></td></tr>
<tr><th><label for="id_turn_server">Turn server:</label></th><td><select name="turn_server" class="form-control form-control-sm" id="id_turn_server">
<option value="1">frankfurt</option>
<option value="2">amsterdam</option>
<option value="3">new_york</option>
</select></td></tr>
<tr><th><label for="ex1">Fps:</label></th><td><input type="text" name="fps" value="45" id="ex1" data-slider-id="ex1Slider" data-slider-min="10" data-slider-max="60" data-slider-step="1" required></td></tr>
<tr><th><label for="ex2">Bitrate:</label></th><td><input type="text" name="bitrate" value="500" id="ex2" data-slider-id="ex2Slider" data-slider-min="200" data-slider-max="2000" data-slider-step="1" required></td></tr>
You can try to define the initial data from the form:
name = forms.CharField(initial='Your name')
Take a look at the documentation here
Related
I am working on a project and have ran into an issue with my forms. In particular, I want the form to use Bootstrap4 (from CDN) elements, yet when I try to use the widgets feature of ModelForm, it isn't working quite right
forms.py:
class Meta(object):
model = ScheduleItem
fields = (
'name',
'time_start',
'time_end',
'day',
)
widgets = {
'name': forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'test'
}
),
'time_start': forms.TimeInput(
attrs={
'class': "form-control"
}
)
}
def __init__(self, *args, **kwargs):
super(ScheduleItemForm, self).__init__(*args, **kwargs)
self.fields['name'].label = ""
self.fields['time_start'].label = ""
self.fields['time_end'].label = ""
self.fields['day'].label = ""
html page: (The first two are ones using the form and the latter are not using it)
<form action="" method="POST">
{% csrf_token %}
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Description</label>
{{schedule_item_form.name|as_crispy_field}}
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Start Time</label>
{{schedule_item_form.time_start|as_crispy_field}}
{% comment %} <input type="time" class="form-control" aria-label="Username" name="start_time" required> {% endcomment %}
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">End Time</label>
<input type="time" class="form-control" aria-label="Username" name="end_time" required>
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Day of the Week</label>
<select class="form-select" id="inputGroupSelect01">
<option selected>Choose...</option>
<option value="0">Monday</option>
<option value="1">Tuesday</option>
<option value="2">Wednesday</option>
<option value="3">Thursday</option>
<option value="4">Friday</option>
<option value="5">Saturday</option>
<option value="6">Sunday</option>
</select>
</div>
<button type="submit" class="btn btn-primary mb-2 mt-2">Add item to schedule</button>
</form>
Output:
HTML Output
Preferably, I would like all the inputs to look akin to the bottom two. Why does my form look so wacky? Thank you!
What I did to fix this was remove the {{|as_crispy_field}} as it was clashing with the 'form-control' tag in the widgets in my form
I have issues getting the output of my experience_level and country select fields despite my best efforts,please kindly help,below are snippets of my code for better understanding
choice.py: File to store all my selections:
salary_choices = {
'100000': '$100,000',
'200000': '$200,000',
'300000': '$300,000',
'400000': '$400,000',
'500000': '$500,000',
}
Country_choices = {
'US': 'United States',
'AF': 'Afghanistan',
'AL': 'Albania',
'DZ': 'Algeria',
}
experience_level = {
'EXP': 'Experienced(5years and above)',
'INT': 'Intermediate(2-5years)',
'JU': 'Junior(0-2years)',
'INTE': 'Intern'
}
views.py:
def jobsearch(request):
queryset_list = JobListing.objects.order_by('-list_date')
# Keywords
if 'keywords' in request.GET:
keywords = request.GET['keywords']
if keywords:
queryset_list = queryset_list.filter(description__icontains=keywords)
# city
if 'city' in request.GET:
city = request.GET["city"]
if city:
queryset_list = queryset_list.filter(city__iexact=city)
# country
if 'country' in request.GET:
q = request.GET["country"]
if q:
queryset_list = queryset_list.filter(country__iexact=q)
# experience
if 'experience' in request.GET:
experience = request.GET["experience"]
if experience:
queryset_list = queryset_list.filter(experience_level__exact=experience)
# Price
if "salary" in request.GET:
salary = request.GET["salary"]
if salary:
queryset_list = queryset_list.filter(salary__exact=salary)
context = {'salary_choices': salary_choices,
'experience_level': experience_level, 'country_choices': Country_choices,
'jobs': queryset_list,
}
return render(request, 'joblistings/jobsearch.html', context)
template:
<form action="{% url 'search' %}" class="form-horizontal">
<div class="col-md-2">
<div class="input-group"><input type="text" name="keywords" class="form-control right-bor"
id="joblist"
placeholder="Search by keyword"></div>
</div>
<div class="col-md-2">
<div class="input-group"><input type="text" name="city" class="form-control right-bor"
id="location"
placeholder="Search By City.."></div>
</div>
<div class="col-md-2 ">
<div class="input-group">
<label>
<select class="form-control" name="country">
<option selected="true" disabled="disabled">Country</option>
{% for key,value in country_choices.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</label>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<label>
<select class="form-control" name="experience">
<option disabled="disabled" selected="true" >Experience level</option>
{% for key,value in experience_level.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</label>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<label>
<select class="form-control" name="salary">
<option disabled="disabled" selected="true">Salary (Any)</option>
{% for key,value in salary_choices.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</label>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<button type="submit" class="btn btn-primary">Search Job</button>
</div>
</div>
</form>
Here is the form with the name fields supposedly to tally with the items from the get request:
from django.shortcuts import get_object_or_404, render
from .models import JobListing
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .choices import Country_choices, salary_choices, experience_level
from django.db.models import Q
# Create your views here.
def jobs(request):
joblisting = JobListing.objects.order_by('-list_date').filter(is_published=True)
"""
Getting pages from the database
"""
paginator = Paginator(joblisting, 3)
page = request.GET.get('page')
paged_joblistings = paginator.get_page(page)
context = {
'jobs': paged_joblistings
}
return render(request, 'joblistings/joblistings.html', context)
def job(request, joblisting_id):
joblist = get_object_or_404(JobListing, pk=joblisting_id)
context = {
'job': joblist
}
return render(request, 'joblistings/joblisting.html', context)
def jobsearch(request):
queryset_list = JobListing.objects.order_by('-list_date')
# Keywords
if 'keywords' in request.GET:
keywords = request.GET['keywords']
if keywords:
queryset_list = queryset_list.filter(description__icontains=keywords)
# city
if 'city' in request.GET:
city = request.GET["city"]
if city:
queryset_list = queryset_list.filter(city__iexact=city)
# country
if 'country' in request.GET:
q = request.GET["country"]
if q:
queryset_list = queryset_list.filter(country__iexact=q)
# experience
if 'experience' in request.GET:
experience = request.GET["experience"]
if experience:
queryset_list = queryset_list.filter(experience_level__exact=experience)
# Price
if "salary" in request.GET:
salary = request.GET["salary"]
if salary:
queryset_list = queryset_list.filter(salary__exact=salary)
context = {'salary_choices': salary_choices,
'experience_level': experience_level, 'country_choices': Country_choices,
'jobs': queryset_list,
}
return render(request, 'joblistings/jobsearch.html', context)
Below is my models.py file which shows my models:
from django.db import models
from datetime import datetime
from recruiters.models import Recruiter
# Create your models here.
class JobListing(models.Model):
recruiter = models.ForeignKey(Recruiter, on_delete=models.DO_NOTHING)
title = models.CharField(max_length=250)
address = models.CharField(max_length=250)
city = models.CharField(max_length=250)
state = models.CharField(max_length=200)
country = models.CharField(max_length=200, default='')
zipcode = models.CharField(max_length=20)
description = models.TextField(blank=True)
stack = models.CharField(max_length=250)
experience_level = models.CharField(
max_length=100,)
salary = models.IntegerField()
photo_main = models.ImageField(upload_to='photos/%Y/%m/%d/')
optional_photo_1 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
optional_photo_2 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
optional_photo_3 = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)
is_published = models.BooleanField(default=True)
list_date = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.title
my html code:
<form action="{% url 'search' %}" class="form-horizontal">
<div class="col-md-2">
<div class="input-group"><input type="text" name="keywords" class="form-control right-bor"
id="joblist"
placeholder="Search by keyword"></div>
</div>
<div class="col-md-2">
<div class="input-group"><input type="text" name="city" class="form-control right-bor"
id="location"
placeholder="Search By City.."></div>
</div>
<div class="col-md-2 ">
<div class="input-group">
<label>
<select class="form-control" name="country">
<option selected="true" disabled="disabled">Country</option>
{% for key,value in country_choices.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</label>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<label>
<select class="form-control" name="experience">
<option disabled="disabled" selected="true" >Experience level</option>
{% for key,value in experience_level.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</label>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<label>
<select class="form-control" name="salary">
<option disabled="disabled" selected="true">Salary (Any)</option>
{% for key,value in salary_choices.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</label>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<button type="submit" class="btn btn-primary">Search Job</button>
</div>
</div>
I wish to know how to display 'auto_now_add' fields (and as disabled fields) in django frontend forms.
I attach some of relevant code:
# models.py
class ModelA(models.Model):
name = models.CharField('Name', max_length=100)
inserted = models.DateTimeField('Inserted ', auto_now_add=True)
# forms.py
class ProcessModelAForm(forms.ModelForm):
class Meta:
model = ModelA
fields = '__all__'
widgets = {
"name": forms.TextInput({
"class": "form-control",
"disabled": True,
}),
"inserted": forms.DateTimeInput({
"class": "form-control",
"disabled": True,
}),
}
# views.py
def process_model_a(request, pk):
instance_model_a = get_object_or_404(ModelA, id=pk)
process_form = ProcessModelAForm(instance=instance_model_a)
if request.method == 'POST':
# ...
return render(request, 'myapp/process_model_a.html', {'process_form ': process_form , 'instance':instance_model_a , } )
# process_model_a.html
<form method="post" class="form-horizontal">
{% csrf_token %}
{% for field in process_form %}
<div class="form-group form-group-lg">
<label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{field.label}}</label>
<div class="col-sm-6">
{{ field }}
</div>
<div class="col-sm-4">
{{ field.errors }}
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary btn-lg center-block">Process</button>
</div>
</div>
</form>
The page "process_model_a.html" shows only "name" fields.
How can I display also "inserted" field?
Thanks.
Basically I want to change value of company id and company name if your company field is changed.
Here I have used django-autocomplete-light for your company field. Code for this form:
class PartnerAddForm(forms.ModelForm):
company_id = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'disabled': ''}), required=False)
company_name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control', 'disabled': ''}), required=False)
class Meta:
model = CompanyCompanyMap
fields = ('your_company',)
widgets = {
'your_company': autocomplete.ModelSelect2(url='url_company_autocomplete',
attrs={'class': 'form-control',
'data-placeholder': 'Type for getting available companies'})
}
Code for autocomplete view of your company field:
class CompanyAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
qs = CompanyAccess(self.request).get_non_partners()
if self.q:
qs = qs.filter(company_name__istartswith=self.q)
return qs
And code for template of this form
<form class="form-horizontal" role="form" action="." method="POST">
{% csrf_token %}
{% for f in form %}
<div class="form-group">
<label for="id_{{ f.name }}" class="col-sm-2 control-label">{{ f.label|capfirst }}</label>
<div class="col-sm-7">
{{ f }}
</div>
</div>
{% endfor %}
<div class="form-group">
<label class="col-sm-2 control-label"></label>
<div class="col-sm-7">
<button type="submit" class="btn btn-default btn-primary">
Add Company as Friend
</button>
</div>
</div>
<!-- /.table-responsive -->
</form>
Is there any way to change it using js or other mechanism?
Maybe someone could explain this to me.
With the following models:
class ContactEmail(models.Model):
# Documentation
__doc__ = _(u'Stores an e-mail address for a contact.')
# Enums
CATEGORIES = (
(0, _(u'Personal')),
(1, _(u'Professional')),
)
# Attributes
category = models.IntegerField(choices=CATEGORIES, verbose_name=_(u'category'), help_text=_(u'This values indicates wheter the address is for personal or professional use.'))
email_address = models.EmailField(max_length=255, unique=True, verbose_name=_(u'e-mail address'), help_text=_(u'A valid e-mail address.'))
contact = models.ForeignKey('Contact', related_name=u'emails', verbose_name=_(u'contact'), help_text=_(u'The contact whose the e-mail address is.'))
priority_level = models.PositiveSmallIntegerField(verbose_name=_(u'priority level'), help_text=_(u'An integer used to define a priority level for e-mail addresses of a contact.'))
# Methodes
def __unicode__(self):
return u'%(mail)s' % {u'mail': self.email_address}
# Meta-data
class Meta:
verbose_name = _(u'E-mail')
verbose_name_plural = _(u'E-mails')
unique_together = ('contact', 'priority_level')
class Contact(models.Model):
pass
And the following ModelForms:
class ContactCreateForm(forms.ModelForm):
# Documentation
__doc__ = _(u'A custom form for Contact model.')
# Methods
def __init__(self, *args, **kwargs):
super(ContactCreateForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
if name != 'image':
if field.widget.attrs.has_key('class'):
field.widget.attrs['class'] += ' form-control'
else:
field.widget.attrs.update({'class':'form-control'})
# Meta-data
class Meta:
model = Contact
exclude = ['second_names', 'suffix', 'dob', 'skype_account',]
class ContactEmailCreateForm(forms.ModelForm):
# Documentation
__doc__ = _(u'A custom form for ContactEmail model.')
# Methods
def __init__(self, *args, **kwargs):
super(ContactEmailCreateForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
if field.widget.attrs.has_key('class'):
field.widget.attrs['class'] += ' form-control'
else:
field.widget.attrs.update({'class':'form-control'})
# Meta-data
class Meta:
model = ContactEmail
I'm trying to set up a create contact form that includes a formset for Emails (intention is to use django-dynamic-formset to dynamically adds form just like the Admin does - and actuall it works). Here's the view:
class ContactCreateView(LoginRequiredMixin, CreateView):
template_name = u'frontend/contacts/create.html'
model = Contact
form_class = ContactCreateForm
def get_context_data(self, **kwargs):
context = {
'emails' : inlineformset_factory(parent_model=Contact, model=ContactEmail, form=ContactEmailCreateForm, extra=1),
}
context.update(kwargs)
return super(ContactCreateView, self).get_context_data(**context)
django-dynamic-formset requires you to set can_delete=True which is set by default in inlineformset_factory. And this parameter adds a DELETE field to each form of your formset.
Until here, nothing to complain about. Except that it adds this fields to form.visible_fields which is, IMO, kind of disturbing since this field is hidden if there is no form.instance:
# create.html
<fieldset class="emails">
<legend>{% trans "E-mail(s)" %}</legend>
{{ emails.management_form }}
{% for form in emails %}
<div class="inline-form-emails">
{{ form.media }}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<label for="{{ field.html_name }}" class="col-xs-12 col-sm-5 col-md-3 col-lg-3 control-label">
{{ field.label }} {% if field.field.required %}<span style="color: #a60000;">*</span>{% endif %}
</label>
<div class="col-xs-12 col-sm-7 col-md-9 col-lg-9">
{{ field }}
<span class="help-block">{{ field.help_text }}</span>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</fieldset>
As you can see the output:
<fieldset class="emails">
<legend>E-mail(s)</legend>
<input id="id_emails-TOTAL_FORMS" name="emails-TOTAL_FORMS" type="hidden" value="1"><input id="id_emails-INITIAL_FORMS" name="emails-INITIAL_FORMS" type="hidden" value="0"><input id="id_emails-MAX_NUM_FORMS" name="emails-MAX_NUM_FORMS" type="hidden" value="1000">
<div class="inline-form-emails dynamic-form">
<input id="id_emails-0-contact" name="emails-0-contact" type="hidden">
<input id="id_emails-0-id" name="emails-0-id" type="hidden">
<div class="form-group">
<label for="emails-0-category" class="col-xs-12 col-sm-5 col-md-3 col-lg-3 control-label">
Category <span style="color: #a60000;">*</span>
</label>
<div class="col-xs-12 col-sm-7 col-md-9 col-lg-9">
<select class="form-control" id="id_emails-0-category" name="emails-0-category">
<option value="" selected="selected">---------</option>
<option value="0">Personal</option>
<option value="1">Professional</option>
</select>
<span class="help-block">This values indicates wheter the address is for personal or professional use.</span>
</div>
</div>
<div class="form-group">
<label for="emails-0-email_address" class="col-xs-12 col-sm-5 col-md-3 col-lg-3 control-label">
E-mail address <span style="color: #a60000;">*</span>
</label>
<div class="col-xs-12 col-sm-7 col-md-9 col-lg-9">
<input class="form-control" id="id_emails-0-email_address" maxlength="255" name="emails-0-email_address" type="text">
<span class="help-block">A valid e-mail address.</span>
</div>
</div>
<div class="form-group">
<label for="emails-0-priority_level" class="col-xs-12 col-sm-5 col-md-3 col-lg-3 control-label">
Priority level <span style="color: #a60000;">*</span>
</label>
<div class="col-xs-12 col-sm-7 col-md-9 col-lg-9">
<input class="form-control" id="id_emails-0-priority_level" name="emails-0-priority_level" type="text">
<span class="help-block">An integer used to define a priority level for e-mail addresses of a contact.</span>
</div>
</div>
<div class="form-group">
<label for="emails-0-DELETE" class="col-xs-12 col-sm-5 col-md-3 col-lg-3 control-label">
Delete
</label>
<div class="col-xs-12 col-sm-7 col-md-9 col-lg-9">
<input type="hidden" name="emails-0-DELETE" id="id_emails-0-DELETE">
<span class="help-block"></span>
</div>
</div>
<a class="delete-row" href="javascript:void(0)">remove</a></div><a class="add-row" href="javascript:void(0)">add another</a>
</fieldset>
Anyone has a clue ?
As mentioned here, the problem came from the django-dynamic-form library !
Just in case someone fall into the same trap...