Django - how to modify crispy forms? - django

First, I want to generate a page that looks like this:
There are three things that makes it difficult.
1. Label + Input field set should line up horizontally
2. Some of the fields have checkbox
3. Date Field has a special Bootstrap plugin.
Here are the html source code for each types:
generic type:
<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" style="margin-bottom: 5px">
<label class="input-upper-title">Drill String Name</label>
<input type="text" id="" class="form-control input-field-height-vertical" name="" required="">
</div>
has checkbox:
<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" style="margin-bottom: 5px">
<label class="input-upper-title">String Length (ft)</label>
<div class="has-checkbox">
<input type="checkbox"><input disabled="disabled" type="text" id="" class="form-control input-field-height-vertical input-calculated" name="" data-parsley-trigger="" required="">
</div>
</div>
has date plugin:
<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" style="margin-bottom: 5px">
<label class="input-upper-title">Date Run</label>
<div class="form-group">
<div class="input-group date" id="datetimepicker7" data-target-input="nearest">
<input type="text" class="form-control datetimepicker-input input-field-height-vertical" data-target="#datetimepicker7"/>
<div class="input-group-append" data-target="#datetimepicker7" data-toggle="datetimepicker">
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
</div>
</div>
</div>
</div>
And here is my forms.py:
class BHA_overall_Form(forms.ModelForm):
prefix = 'bha_overall'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
class Meta():
model = BHA_overall
fields = '__all__'
How should I modify my forms.py, using crispy_forms to get the same effect as my html source code does?

Related

How to force this field to submit data?

I have a form that looks like
I am trying to add a product. The description of which will be entered through this form. But my textarea dont send data to product
html:
<div class="col-12">
<div class="mb-2">
<label class="form-label">Текст новости</label>
<div id="blog-editor-wrapper">
<div id="blog-editor-container">
<div class="editor">
<textarea name="text" class="form-control" id="text" rows="3" required>TEXT</textarea>
</div>
</div>
</div>
</div>
</div>
vievs:
def create(request):
if (request.method == 'POST'):
obj, created = Posts.objects.get_or_create(title=request.POST.get("title"))
obj.text=request.POST.get("text")
obj.preview=request.POST.get("preview")
obj.date=request.POST.get("date")
obj.image=request.POST.get("image")
obj.save()
models:
text = models.TextField('Текст статьи')
Мy other fields (not custom) look like this
<label class="form-label" for="blog-edit-title">Заголовок</label>
<input type="text" id="blog-edit-title" class="form-control" value="" name="title" />

crispy form field type attribute ignored

I am trying to use crispy forms in my django app and I can not seem to get the type attribute to set on a field.
#forms.py
class ReminderForm(ModelForm):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.helper=FormHelper()
self.helper.layout = Layout(
Fieldset('Reminder',
Row(
Div(Field('message'),css_class="col"),
),
Row(
Div(Field('messagetype'),css_class="col-md-6"),
Div(Field('account'),css_class="col-md-6"),
),
Row(
Div(Field('reminddate',type="date"),css_class="col-md-6"),
Div(Field('duedate', type="date"),css_class="col-md-6"),
),
)
)
class Meta:
model=Reminder
exclude=['sentdate','confirmdate','completedate']
my modal form
{% load cms_tags crispy_forms_tags %}
<div class="modal fade" id="{{formid}}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{title}}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form >
{% crispy form %}
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
rendered html for the inputs below show reminddate and duedate style with type="text"
<div class="modal-body">
<form>
<fieldset> <legend>Reminder</legend> <div class="form-row "> <div class="col"> <div id="div_id_message" class="form-group"> <label for="id_message" class="">
Message
</label> <div class=""> <textarea name="message" cols="40" rows="10" class="textarea form-control" id="id_message"></textarea> </div> </div> </div>
</div>
<div class="form-row "> <div class="col-md-6"> <div id="div_id_messagetype" class="form-group"> <label for="id_messagetype" class="">
Messagetype
</label> <div class=""> <select name="messagetype" class="select form-control" id="id_messagetype"> <option value="">---------</option> <option value="email">Email</option> <option value="sms">Text Message</option> <option value="internal">Internal Website</option>
</select> </div> </div> </div>
<div class="col-md-6"> <div id="div_id_account" class="form-group"> <label for="id_account" class="">
Account
</label> <div class=""> <select name="account" class="select form-control" id="id_account"> <option value="" selected="">---------</option> <option value="4">jim.pm</option> <option value="2">joe.sp</option> <option value="3">sally.om</option> <option value="1">sparrow</option>
</select> </div> </div> </div>
</div>
<div class="form-row "> <div class="col-md-6"> <div id="div_id_reminddate" class="form-group"> <label for="id_reminddate" class=" requiredField">
Reminddate<span class="asteriskField">*</span> </label> <div class=""> <input type="text" name="reminddate" class="datetimeinput form-control" required="" id="id_reminddate"> </div> </div> </div>
<div class="col-md-6"> <div id="div_id_duedate" class="form-group"> <label for="id_duedate" class=" requiredField">
Duedate<span class="asteriskField">*</span> </label> <div class=""> <input type="text" name="duedate" class="datetimeinput form-control" required="" id="id_duedate"> </div> </div> </div>
</div> </fieldset> </form>
</div>
rendred form
How do I correctly set the type attribute? Other attributes(custom attributes) work fine.
#Martin Beran pointed me in the right direction. Since I am trying to stay with the {% crispy form %} method... I found that using the widgets override in the Meta class provided what I needed!
class Meta:
model=Reminder
exclude=['sentdate','confirmdate','completedate']
widgets = {
'reminddate': forms.DateInput(attrs={'type':'date'}),
'duedate': forms.DateInput(attrs={'type':'date'})
}
Form with bootstrap date control
Oh, you want type=date, that's a tricky one... you should make your own widget then, but if you are lazy, like me, you make a workaround with a template filter:
from django import forms
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.filter
def set_input_type(field, field_type=None):
if field_type:
pass
elif isinstance(field.field.widget, forms.DateInput):
field_type = 'date'
elif isinstance(field.field.widget, forms.TimeInput):
field_type = 'time'
elif isinstance(field.field.widget, forms.SplitDateTimeWidget):
for subfield in field.field.widget.widgets:
if isinstance(subfield, forms.DateInput):
subfield.input_type = 'date'
elif isinstance(subfield, forms.TimeInput):
subfield.input_type = 'time'
elif isinstance(field.field.widget, forms.DateTimeInput):
# field_type = 'datetime-local' # can't work with passing/returning ISO format
# field_type = 'datetime' # is deprecated, doesn't work in many browsers
# use widget=forms.SplitDateTimeWidget() instead
pass
if field_type:
field.field.widget.input_type = field_type
return field
so you can change the type in template like
{{ form.dt|set_input_type:'date' }}
but ofc if you use just {% crispy form %}, you have to go the first (preferable) way and make your own widget :)
also another way is to use JS, like $('#id_reminddate').attr('type', 'date');
btw they probably use type=text, because type=date is ugly in desktop browsers, so you use some JS library like jqueryui for callendars

how to creater a signup register form with my own reqired field form in django?

Im new to django i want create signup form with my own feild ,i dont want to signup form in default that is in user table i want to created own custom sign up forn any can hepl plz
Im new to django i want create signup form with my own feild ,i dont want to signup form in default that is in user table i want to created own custom sign up forn any can hepl plz
here is my example how my form feild look like
[enter link description here][1]
<form id="contact-form" method="post" action="/addyourschool/" role="form">
<input type="hidden" name="csrfmiddlewaretoken" value="vhcAZ5w1HpK2mUXMhdqHR1to9Yv2LeOB85E2kR7Z1ZsPo5fjtWZ5P7o23kj8lDsk">
<div class="messages"></div>
<div class="controls">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="form_name">School Name</label>
<input type="text" name="schoolname" id="product" class="form-control ui-autocomplete-input" placeholder="Type few letter & select from down *" required="required" data-error="Lastname is required." autocomplete="off">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="form_cfschp">Can't find your School *</label>
<input id="form_cfschp" type="text" name="form_cfschpool" class="form-control" placeholder="Can't find your School *" required="required" data-error="Can't find your School">
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="Pessonname">Contact person Name *</label>
<input id="Pessonname" type="text" name="Pessonname" class="form-control" placeholder="Contact person Name *" required="required" data-error="Contact person Name ">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="DesignationatSchool">Designation at School(job title at this section) *</label>
<select id="DesignationatSchool" name="DesignationatSchool" class="form-control" required="required" data-error="Designation at School">
<option value=""></option>
<option value="Request principal">Principal</option>
<option value="Request quotation">Founder</option>
<option value="Request order status">Management</option>
<option value="Request copy of an invoice">Teachers</option>
<option value="Other">Others</option>
</select>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="pwd">Password *</label>
<input id="pwd" type="password" name="password" class="form-control" placeholder="Enter your Password *" required="required" data-error="password">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="pwd">Confirm Password *</label>
<input id="pwd" type="password" name="password" class="form-control" placeholder="Confirm Password *" required="required" data-error="Lastname is required.">
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="email">Email *</label>
<input id="email" type="email" name="email" class="form-control" placeholder="Please enter your email *" required="required" data-error="Valid email is required.">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="tel">Mobile No. *</label>
<input id="tel" type="tel" name="phone" class="form-control" placeholder="Please enter your Mobile No *" required="required" data-error="Valid email is required.">
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="text-center"> <input type="submit" class="btn btn-success btn-send" value="Register"></div>
<div class="text-center">Aready Register / have an account ? Login here</div>
</div>
</div>
</form>
from django import forms
class RegisterForm(forms.Form):
username = forms.CharField(max_length=50)
email = forms.EmailField(max_length=50)
subject = forms.CharField(max_length=50)
message = forms.CharField(widget=forms.Textarea)
You have to first create the forms.py file in your app as e.g(contact_us)
from django.shortcuts import render
from django.core.mail import send_mail
from .forms import RegisterForm
from django.http import HttpResponse
Create your views here.
def contact_us(request):
#request for POST
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
sender_name = form.cleaned_data['username']
sender_email = form.cleaned_data['email']
message = "{0} has sent you a new message:\n\n{1}".format(sender_name, form.cleaned_data['message'])
send_mail('New Enquiry', message, sender_email, ['example#gmail.com'])
return HttpResponse('Thanks for Contacting US')
else:
form = RegisterForm()
return render(request, 'Contactus/contact.html', {'form': form})
After created the forms you have to insert the forms class name in views.py to display the custom form on browser.
#Create Your Template
<form id="contactform" method="POST">
{% csrf_token %}
<div class="column one-second">
{{ form.username }}
</div>
<div class="column one-second">
{{form.email }}
</div>
<div class="column one">
{{ form.subject }}
</div>
<div class="column one">
{{ form.message }}
</div>
<div class="column one">
<input type="submit" value="submit">
</div>
</form>
After this you have to call the form in template. To display your own custom form.
As i did above.

Django formset with crispy - submit buttons not submitting

I'm using a FormSet with crispy, and have but a submit button on each row, however hitting submit does not update records currently.
I've searched and found some similar answers which suggest the submit isn't inside the form, but mine are. Also that a form action is missing, but none of my other crispy forms have actions and they work without issue.
Are there any other reasons seen from the code below that would cause the records to not save?
forms.py
class ChangeGroupForm(FormHelper):
def __init__(self, *args, **kwargs):
super(ChangeGroupForm, self).__init__(*args, **kwargs)
self.form_method = 'post'
self.css_class = 'form-inline'
self.form_id = 'changegroup_form'
self.form_show_labels = False
self.layout = Layout(
Div(
Div(
Div(
Field('group', placeholder='Group', css_class="form-control mb-2 mr-sm-2"),
css_class='col-lg-3'
),
Div(
Field('gps', placeholder='gps coords', css_class="form-control mb-2 mr-sm-2"),
css_class='col-lg-8'
),
Div(
HTML("""<input type="submit" name="submit" value="Save" class="btn btn-primary mt-1"/>"""),
css_class='col-lg-1'
),
css_class='row'
),
)
)
self.render_required_fields = True
views.py
#login_required
def db_change_groups(request):
change_form = modelformset_factory(ChangeGroup, fields=('group','gps'))
change_form_helper = ChangeGroupForm()
return render(request, 'home/db_change_groups.html', {
"change_form": change_form,
"change_form_helper": change_form_helper,
})
template.html
{% crispy change_form change_form_helper %}
rendered html
<form id="changegroup_form" method="post"> <input type="hidden" name="csrfmiddlewaretoken"
value="7v0000CPl3G70M6HLfF2FAiwefdfsdgdfwewdf7Gp4nay1hFqZ1Y34SBUA000mHBZQ54">
<div> <input type="hidden" name="form-TOTAL_FORMS" value="10" id="id_form-TOTAL_FORMS"> <input type="hidden"
name="form-INITIAL_FORMS" value="9" id="id_form-INITIAL_FORMS"> <input type="hidden"
name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS"> <input type="hidden"
name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS"> </div>
<div>
<div class="row">
<div class="col-lg-3">
<div id="div_id_form-0-group" class="form-group">
<div class="controls "> <input type="text" name="form-0-group" value="A" maxlength="50"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="Group"
id="id_form-0-group"> </div>
</div>
</div>
<div class="col-lg-8">
<div id="div_id_form-0-gps" class="form-group">
<div class="controls "> <input type="text" name="form-0-gps" maxlength="255"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="gps coords"
id="id_form-0-gps"> </div>
</div>
</div>
<div class="col-lg-1"> <input type="submit" name="submit" value="Save" class="btn btn-primary mt-1" />
</div>
</div>
</div> <input type="hidden" name="form-0-id" value="1" id="id_form-0-id">
<div>
<div class="row">
<div class="col-lg-3">
<div id="div_id_form-1-group" class="form-group">
<div class="controls "> <input type="text" name="form-1-group" value="B" maxlength="50"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="Group"
id="id_form-1-group"> </div>
</div>
</div>
<div class="col-lg-8">
<div id="div_id_form-1-gps" class="form-group">
<div class="controls "> <input type="text" name="form-1-gps" maxlength="255"
class="form-control mb-2 mr-sm-2 textinput textInput form-control" placeholder="gps coords"
id="id_form-1-gps"> </div>
</div>
</div>
<div class="col-lg-1"> <input type="submit" name="submit" value="Save" class="btn btn-primary mt-1" />
</div>
</div>
</div>
</div> <input type="hidden" name="form-9-id" id="id_form-9-id">
</form>
You need to attach somthing like this to your view
def db_change_groups(request):
....
if request.method == "POST":
form = ChangeGroupForm(request.POST)
if form.is_valid():
# Access cleaned data with
group = form.cleaned_data['group']
# Then you can save this to a model.
# return success template or something
else:
# Check for errors.
If you created the form with ModelForm instead of FormHelper you could use form.save() which you automatically save it to the model.

field alignments in django crispy forms and bootstrap 3?

I am using django-crispy-forms and Bootstrap 3 in my template rendering.
Here is how my form looks like:
As you can notice, the fields are not aligned correctly. I want them to be inline. please provide suggestions on how to fix this:
My crispy form code is below:
class SortFieldsForm(forms.Form):
latest_year=forms.BooleanField(label="latest year")
newest_entry=forms.BooleanField(label="newest post")
price_order=forms.ChoiceField(
widget=forms.RadioSelect,
label="price order",
choices=(('lowest_price','lowest '),('highest_price','highest'),),
initial="lowest_price",
)
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_class = 'form-inline'
self.helper.field_template='bootstrap3/layout/inline_field.html'
self.helper.form_method = 'post'
self.helper.form_action = '.'
super(SortFieldsForm, self).__init__(*args, **kwargs)
self.helper.layout = Layout(
InlineRadios('price_order'),
'newest_entry',
'latest_year',
Submit('submit', 'Submit', css_class='button white'),
)
And the generated HTML code:
<form action="." id="id-exampleForm" class="form-inline" method="post" >
<div id="div_id_price_order" class="form-group">
<label for="id_price_order" class="control-label requiredField">
price order
<span class="asteriskField">*</span>
</label>
<div class="controls ">
<label class="radio-inline">
<input type="radio" checked="checked" name="price_order" id="id_price_order_1" value="lowest_price" >lowest</label>
<label class="radio-inline">
<input type="radio" name="price_order" id="id_price_order_2" value="highest_price" >highest</label>
</div>
</div>
<div id="div_id_newest_entry" class="checkbox">
<label for="id_newest_entry" class=" requiredField">
<input class="checkboxinput checkbox" id="id_newest_entry" name="newest_entry" type="checkbox" />
newest post
</label>
</div>
<div id="div_id_latest_year" class="checkbox">
<label for="id_latest_year" class=" requiredField">
<input class="checkboxinput checkbox" id="id_latest_year" name="latest_year" type="checkbox" />
latest year
</label>
</div>
<input type="submit" name="submit" value="Submit" class="btn btn-primary button white" id="submit-id-submit"/>
</form>
This has nothing to do with crispy-forms itself, but rather that you have a label on the radio inputs that is pushing the actual inputs down. You need to add a margin-top style to div_id_newest_entry, submit-id-submit, and div_id_latest_year. For example (your use case may vary a bit), in your CSS file:
#div_id_newest_entry,
#div_id_latest_year,
#submit-id-submit {
margin-top: 25px;
}