Render django-filter(filterset) bar with Crispy Forms - django

I created a filter bar (with filterset from the django-filter module), but I'm unable to render it with crispy forms.
Are crispy-forms compatible with django-filter? I tried it, and Crispy Forms works well with all my other forms and modelforms, but it seems like django-filter rejects to render in crispy-bootstrap.
HTML:
{% extends 'base/base1.html' %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="row">
<div class="col">
<div class="card card-body">
<form method="get">
****{{ myFilter.form}}****
*/tried also {{ myFilter.form|crispy}}
{{ myFilter.form.variablefieldhere|as_crispy_field}}**
<button class="btn btn-primary" type="submit">
Search</button>
</form>
</div>
</div>
</div>
Filter.py:
import django_filters
from .models import log
class logFilter(django_filters.FilterSet):
class Meta:
model = log
fields = {
'varfliedhere': ['icontains'],
'varfliedhere': ['icontains'],
'varfliedhere': ['icontains'],
'Boolean varfliedhere': ['exact'],
}
Should I try to set the FormHelper in forms? But in that case, how do I render it in Crispy Forms?
In the other forms, I rendered them 1 by 1 as:
{{ myFilter.form.variablefieldhere|as_crispy_field}}
which works, but I can't understand how to solve this problem.

As Your requirement is not clear to me. But i assume you want that all field in single row and you are using bootstrap templates for crispyform.
<form method="GET">
<div class="form-row">
<div class="form-group col-md-2 mb-0 ">
{{myFilter.form.variablefieldhere1|as_crispy_field}}
</div>
<div class="form-group col-md-2 mb-0 ">
{{myFilter.form.variablefieldhere2|as_crispy_field}}
</div>
<div class="form-group col-md-2 mb-0 ">
{{myFilter.form.variablefieldhere3|as_crispy_field}}
</div>
<div class="form-group col-md-2 mb-0 ">
{{myFilter.form.variablefieldhere4|as_crispy_field}}
</div>
<div class=" col-md-2 mb-0 ">
<button class="btn btn-primary btn-sm" type="submit">search</button>
</div>
</div>
</form>

Related

How is it possible to get data from one form that has multiple textareas in Django

I'd like to get data from one form that has multiple textareas inside , In my views: 'compare_ingredients' I've tried requesting data from my form id 'compareform' also the textarea id 'ingredients', but when I enter something into one texture and click on submit it comes back as 'None' when I print. Here is my html and views:
html :
<div class="container-fluid">
<h4>Please enter in your ingredients:</h4>
<h6>(Seperate each item by comma)</h6>
<br>
<button class="add_item">Add Item</button>
<br>
<div class="row row-cols-1 row-cols-md-2 mx-auto">
<form action="{% url 'compare_ingredients' %}" method="POST" name="compareform" id="compare">
{% csrf_token %}
<br>
<button type="submit" class="btn btn-info sub_btn">Submit</button>
<button type="submit" class="btn btn-secondary back_button">
Back
</button>
<br>
<br>
<div class="row form_row">
<div class="col mb-4">
<h5>Item 1</h5>
<div class="card form_card">
<div class="card-body compare_cardbody">
<textarea name="ingredients1" id="ingredients" cols="30" rows="10" form="compareform"></textarea>
</div>
</div>
</div>
<div class="col mb-4">
<h5>Item 2</h5>
<div class="card form_card">
<div class="card-body compare_cardbody">
<textarea name="ingredients2" id="ingredients" cols="30" rows="10" form="compareform"></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
views.py:
def compare_ingredients(request):
if request.method == "POST":
ingredients = request.POST.get('compareform')
print(ingredients)
return render(request, 'result/compare.html')
ok, I figured it out , the problem was in the html textarea I had the name of the form as 'compareform' when it should have been 'compare' :
<textarea name="ingredients2" id="ingredients" cols="30" rows="10" form="compare"></textarea>
then in my views I did:
ingredients1 = request.POST.get('ingredients1')

Django - How to apply onlivechange on CharField / IntegerField

I want to hide the field form.name_of_parent_if_minor if the age (CharField) < 18 else show. I am not getting where to write jQuery or JS code or add separate js file. For this do I need to the html definition and add tag for age (CharField) or we can perform action on this as well.
I am new to the Django so if you find any mistakes in my code then any help would be appreciated for guidance.
forms.py
class StudentDetailsForm(forms.ModelForm):
class Meta:
model = StudentDetails
views.py
class StudentCreateView(LoginRequiredMixin, CreateView):
template_name = 'student/student_details_form.html'
model = StudentDetails
form_class = StudentDetailsForm
success_url = "/"
html
{% extends 'student/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div id="idParentAccordian" class="content-section">
<form method="POST">
{% csrf_token %}
<div class="card mt-3">
<div class="card-header">
<a class="collapsed card-link" style="display: block;" data-toggle="collapse"
href="#idPersonalInformation">Personal Information</a>
</div>
<div id="idPersonalInformation" class="collapse show" data-parent="#idParentAccordian">
<div class="card-body">
<div class="row">
<div class="col-6">
{{ form.joining_date|as_crispy_field }}
</div>
<div class="col-6">
{{ form.class|as_crispy_field }}
</div>
</div>
{{ form.student_name|as_crispy_field }}
{{ form.father_name|as_crispy_field }}
{{ form.mother_name|as_crispy_field }}
{{ form.gender|as_crispy_field }}
<div class="row">
<div class="col-6">
{{ form.date_of_birth|as_crispy_field }}
</div>
<div class="col-6">
{{ form.age|as_crispy_field }}
</div>
</div>
<div>
{{ form.name_of_parent_if_minor|as_crispy_field }}
</div>
</div>
</div>
</div>
<div class="form-group mt-3">
<button class="btn btn-outline-info" type="submit">Save</button>
<a class="btn btn-outline-secondary" href="javascript:history.go(-1)">Cancel</a>
</div>
</form>
</div>
{% endblock content %}
the easiest way but not the cleanest is to add JS script in your html
the recommanded way is to add static folder to your app and load static files in your html template using {% load static %}

How do you implement a Form in a ListView

I'm new to Django, I basically have a homepage which has a search bar that is being implement using a Django Form. Additionally, in the homepage I have bootstrap card whichis being used to display data from my model.
I'm using the def_get to render the form (since it's being used to query the DB). The form is very basic, it's just a CharField. However, when I use the def_get to render the Form in my class based view it now doesn't retrieve any of the data that goes into the bootstrap card which is causing the card to not display.
I've tried to render both the form and data in the card by using ModelFormMixin but it seems like this hasn't solved my issue yet, not sure whether this is the way to achieve this?
Forms.py
from django import forms
class SearchBarForm(forms.Form):
q = forms.CharField(label="", max_length=150, required=True)
Views.py
from django.views.generic import TemplateView
from django.views.generic.list import ListView
from property.models import Property
from pages.forms import SearchBarForm
from django.shortcuts import render
class HomePageView(ListView):
model = Property
template_name = 'home.html'
def get(self, request):
form = SearchBarForm()
return render(request, self.template_name, {'form': form})
Home.html
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<div class="container">
<!-- search bar -->
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-8 custom-search-bar">
<form action="{% url 'property_for_rent' %}" method="get" id="search-form">
{{ form.as_p }}
</form>
</div>
<div class="col-xs-6-md-4 custom-search-bar-button">
<button type="submit" form="search-form" class="btn btn-light" value="For sale">For rent</button>
<button form="rent" type="submit" class="btn btn-light" value="For sale">For Sale</button>
</div>
</div>
<!-- search bar -->
<!-- property card -->
<div class="row">
{% for property in object_list|slice:"3" %}
<div class="col-lg-4 d-flex align-items-stretch custom-cards">
<div class="card" style="width: auto;">
<div class="card-img">
{% if property.image %}
<img class="card-img-top" src="{{property.image.url}}" alt="Card image cap"> {% endif %}
</div>
<div class="card-body">
<h5 class="card-title"> {{ property.location }} </h5>
<p class="card-text">{{ property.description }} </p>
<button type="button" class="btn btn-primary waves-effect waves-light" data-toggle="modal" data-target="#modal-{{ property.id }}">View</button>
</div>
<div class="card-footer">
<small class="text-muted">Last updated</small>
</div>
</div>
<!-- property card -->
<!-- Full Height Modal Right -->
<div class="modal fade right" id="modal-{{ property.id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<!-- Add class .modal-full-height and then add class .modal-right (or other classes from list above) to set a position to the modal -->
<div class="modal-dialog modal-full-height modal-right" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title w-100" id="myModalLabel">{{ property.location }}</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>{{ property.description }}</p>
<ul class="list-group z-depth-0">
<li class="list-group-item justify-content-between">
Bedrooms
<span class="badge badge-primary badge-pill">14</span>
</li>
<li class="list-group-item justify-content-between">
Price
<span class="badge badge-primary badge-pill">2</span>
</li>
<li class="list-group-item justify-content-between">
Location
<span class="badge badge-primary badge-pill">1</span>
</li>
<li class="list-group-item justify-content-between">
Property Type
<span class="badge badge-primary badge-pill">14</span>
</li>
</ul>
</div>
<div class="modal-footer justify-content-center">
<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>
<!-- Full Height Modal Right -->
</div>
{% endfor %}
</div>
</div>
{% endblock %}
What I want to achieve is to both display the search bar and the cards which are using data from my models.
Any hints on how to achieve this is much appreciated as i'm just a beginner :) Thanks!
You can just pass your form in the get_context_data method [Django-doc]:
class HomePageView(ListView):
model = Property
template_name = 'home.html'
def get_context_data(self, *args, *kwargs):
context = super().get_context_data(*args, **kwargs)
context['form'] = SearchBarForm()
return context
or you can make this more declarative, by making use of the FormMixin mxin [Django-doc]:
from django.views.generic.edit import FormMixin
class HomePageView(FormMixin, ListView):
model = Property
template_name = 'home.html'
form_class = SearchBarForm

Sort by ascending and descending using django-filter

I have the following code for few filterings:
from .models import ProductLaptop
import django_filters
class ProductLaptopFilter(django_filters.FilterSet):
laptops_name = django_filters.CharFilter(lookup_expr='icontains')
laptops_price = django_filters.NumberFilter()
laptops_price__gt = django_filters.NumberFilter(field_name='laptops_price', lookup_expr='gt')
laptops_price__lt = django_filters.NumberFilter(field_name='laptops_price', lookup_expr='lt')
class Meta:
model = ProductLaptop
fields = ['laptops_name', 'laptops_price', 'brand_name']
The html codes for this:
{% load widget_tweaks %}
{% block content %}
<form method="get">
<div class="well">
<h4 style="margin-top: 0">Filter</h4>
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_name.label_tag }}
{% render_field filter.form.laptops_name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price.label_tag }}
{% render_field filter.form.laptops_price class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.brand_name.label_tag }}
{% render_field filter.form.brand_name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price__gt.label_tag }}
{% render_field filter.form.laptops_price__gt class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.laptops_price__lt.label_tag }}
{% render_field filter.form.laptops_price__lt class="form-control" %}
</div>
</div>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
Which gives me a view like below:
Here I want to add an option where people can sort the items in ascending and descending order.
Can anyone give me some suggestions how can I implement this?
For that, you can use OrderingFilter from django-filter. Create this filter in your FilterSet class and provide all fields that should be enabled for ordering.

django class page view not rendering template code

I wanted to use class based views and went through the django documentation and I get noerror messages but wind up with an empty template. I had it working with the non-classed based views. How do I reformat the code so that it renders the template? The template consists of a title, some headings, a navigational menu, flags for selecting instructions in different languages,
followed by a form which shows a flag, policy name char field, and a check box control. I think the initial = {'key': 'value'} in the view forms incorrect but I don't know what to replace it with. Thanks in advance.
forms.py
from django import forms
from policytracker.models import Flag, Label_Links
class PolicyStartForm( forms.Form ):
flags = Flag.objects.all()
policy = Label_Links.objects.all().filter(iso_language='en')[0]
frm_policy1_name=[]
for flag in flags:
frm_policy1_name.append(forms.CharField(max_length=40))
policy_dict = { 'new_policy_link' :policy.nav_section_new_policy_link,
'new_policy_label' :policy.nav_section_new_policy_label,
'graphs_link':policy.nav_section_graphs_link,
'graphs_label' :policy.nav_section_graphs_label,
'account_link' :policy.nav_section_account_link,
'account_label' :policy.nav_section_account_label,
'policy_list_link':policy.nav_section_list_policies_link,
'policy_list_label':policy.nav_section_list_policies_label,
'login_link' :policy.nav_section_login_link,
'login_label' :policy.nav_section_login_label,
'new_policy1_heading' :policy.new_policy1_heading,
'new_policy1_title_label':policy.new_policy1_title_label,
'policy_needs_translation_label':policy.new_policy1_needs_trans_label,
'policy1_submit_label': policy.new_policy1_submit_button_label,
'policy1_tip_msg' :policy.new_policy1_tip_msg,
't_logged_in' :True,
'frm_policy_name' :frm_policy1_name,
't_flags' :flags }
</code>
<code>
views.py
# coding=utf-8
from django.shortcuts import render
from django.http import HttpResponseRedirect
from policytracker.forms import LoginForm, PolicyStartForm
from policytracker.models import Flag, Label_Links
from django.views import View
class PolicyStartView(View):
template_name = 'policystart.html'
initial = {'key': 'value'}
form_class = PolicyStartForm
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
</code>
<code>
policystart.html
{% extends "policy-base.html" %}
{% block navsection %}
<div class="container top">
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h1 class="text-center">{{ new_policy1_heading }}</h1>
</div>
</div>
{% if t_policy_details %}
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4">
<h4 class="text-nowrap text-left" id="week_start">2017-02-11</h4></div>
<div class="col-md-4 col-xs-4">
<h4 class="text-center" id="week_number">Week 1</h4></div>
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-4">
<h4 class="text-nowrap text-right" id="week_end">2016-09-18</h4></div>
</div>
{% endif %}
<div class="row">
<div class="col-md-12">
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header"><a class="navbar-brand hidden navbar-link" href="#"> Policies</a>
<button class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navcol-1"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button>
</div>
<div class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav navbar-right">
<li class="hidden" role="presentation">{{ new_policy_label }}</li>
<li {% if not t_logged_in %} class="hidden" {% endif %} role="presentation">{{ graphs_label }}</li>
<li {% if not t_logged_in %} class="hidden" {% endif %} role="presentation">{{ account_label }}</li>
<li role="presentation">{{ policy_list_label }}</li>
{% if not t_logged_in %} <li role="presentation">{{ login_label }}</li> {% endif %}
</ul>
</div>
</div>
</nav>
</div>
</div>
{% include "pol-new1-lang.html" %}
</div>
<div class="container middle-container">
<div class="row">
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-3">
<p> </p>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-8">
<h4>{{ new_policy1_title_label }}</h4>
</div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1">
<h4 class="text-center">{{ policy_needs_translation_label }}</h4>
</div>
</div>
<form method="POST">
{% csrf_token %}
{% load static %}
{% for f in t_flags %}
<div class="row flag">
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-2"><img src="{% static f.flag_image_filename %}"></div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-9">
<input class="form-control" type="text" name="policytitle">
</div>
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-1">
<input class="form-control" type="checkbox" name="needstranslation">
</div>
</div>
{% endfor %}
<div class="row enter">
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-3">
<p> </p>
</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-8">
<button class="btn btn-default" type="submit">{{ policy1_submit_label }}</button>
</div>
</div>
</form>
<div class="row enter">
<div class="col-lg-1 col-md-1 col-sm-1 col-xs-3">
<p> </p>
</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-8">
<p>{{ policy1_tip_msg }}</p>
</div>
</div>
</div>
{% endblock %}
</code>
You're using a load of variables in your template, but you aren't actually sending any of them to the context; the only thing your view passes is form. If you want to use things like new_policy1_heading, policy_needs_translation_label and t_flags you need to define them in your view and send them to the template from there.
Actually, it looks like you've completely misunderstood the jobs of forms and views. All the code you've currently put inside your form actually belongs in the view, and you should use policy_dict as the template context. It doesn't look like you need a form class at all.
Even there, though, you're doing much more work than you need to. There's no need to send all the specific fields of the policy object individually; just send policy and then in the template you can do {{ policy.policy_needs_translation_label }} etc.