I am now studying Django form. Right now I am focusing on crispy form. For now crispy and then after I master the form I will move on to Django Admin form and Django admin model form.
Django 1.10
Python 3.6.0
I am following these tutorials:
https://blog.bixly.com/awesome-forms-django-crispy-forms
http://django-crispy-forms.readthedocs.io/en/latest/layouts.html#
https://godjango.com/29-crispy-forms/
Here are my source code:
views.py:
from django.views.generic import FormView
from apps.colors.forms import PersonDetailForm
class ColorStudyView(FormView):
template_name = 'colors/study.html'
form_class = PersonDetailForm
success_url = '/'
forms.py:
from crispy_forms.bootstrap import Tab, TabHolder
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout
from django import forms
class NoFormTagCrispyFormMixin(object):
#property
def helper(self):
if not hasattr(self, '_helper'):
self._helper = FormHelper()
self._helper.form_tag = False
return self._helper
class PersonDetailForm(forms.Form):
name = forms.CharField(max_length=100)
age = forms.IntegerField(required=False)
address1 = forms.CharField(max_length=50, required=False)
address2 = forms.CharField(max_length=50, required=False)
city = forms.CharField(max_length=50, required=False)
state = forms.CharField(max_length=50, required=False)
mobile = forms.CharField(max_length=32, required=False)
home = forms.CharField(max_length=32, required=False)
office = forms.CharField(max_length=32, required=False)
twitter = forms.CharField(max_length=100, required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout(
TabHolder(
Tab('Information',
'name',
'age'
),
Tab('Address',
'address1',
'address2',
'city',
'state'
),
Tab('Contact',
'mobile',
'home',
'office',
'twitter',
)
)
)
self.helper.layout.append(Submit('submit', 'Submit'))
study.html:
{% load crispy_forms_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<meta charset="UTF-8">
<title>Study</title>
<form action="" method="POST">
{% crispy form %}
</form>
</head>
<body>
</body>
</html>
Problem:
Tab does not change.
Am I miss something?
Sorry for very basic level question, but this is my first day with Django frontend
Here is my picture. Tab Address and Contact are not work.
Update:
Zollie solves my problem. Here is my study.html
{% load staticfiles %}
{% load crispy_forms_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<meta charset="UTF-8">
<title>Study</title>
<form action="" method="POST">
{% crispy form %}
</form>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.9.1.js">
</script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.js">
</script>
<script type="text/javascript" src="{% static 'bootstrap-tab.js' %}"> </script>
</body>
</html>
And here is my filesystem configuration
/Users/el/Code/siam-sbrand/static
(siam-sbrand) Sarits-MacBook-Air-2:static el$ ls
admin django_extensions img
bootstrap-tab.js file.txt js
dist font rest_framework
I had the same problem when first I wanted to use the Tabs in crispy forms. The documentation is quite weak unfortunately for this package.
The answer on why TabHolder and Tabs are not working is, because you have to include jquery and javascript in your html template head. Also, you have to download bootstrap-tab.js and put it in your 'static' folder in the bootstrap subfolder ie., and you also have to include the path to it in your html .
So, it is not enough if you just include Bootstrap or bootstrap.css in the html head.
Here is an example how it should look like:
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js">
</script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.js">
</script>
<script type="text/javascript" src="{% static 'bootstrap/js/bootstrap-tab.js' %}"> </script>
Check these things:
In settings.py you should have CRISPY_TEMPLATE_PACK = 'bootstrap3'
In your static files you should have a bootstrap-tab.js
Although the question is old and solved, I find it might be worthwhile to add some more observations: I came across the problem and found another cause.
First, I checked and confirmed that I had included the .js files as mentioned in the accepted answer. But the tab still did not work.
I found some bootstrap tab examples, such as https://mdbootstrap.com/docs/jquery/components/tabs/. And I concluded that, to make tab work, one should make sure there is a one-to-one relationship between the href attr of the 'tab header' and the id attr of the 'tab body'. Like this:
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home"
aria-selected="true">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile"
aria-selected="false">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact"
aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">A Tab</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">B tab</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">C tab</div>
</div>
Note: pay attention to the href attrs of 'a' elements and the id attrs of 'div' elements.
I did some experimentation and concluded that: once related .js and other files are imported and href and id attrs are properly set, the tab would work.
Now the problem became "how to make crispy set them properly".
I checked following files:
1. /root/.pyenv/versions/3.7.3/lib/python3.7/site-packages/crispy_forms/bootstrap.py
class Tab(Container):
"""
Tab object. It wraps fields in a div whose default class is "tab-pane" and
takes a name as first argument. Example::
Tab('tab_name', 'form_field_1', 'form_field_2', 'form_field_3')
"""
css_class = 'tab-pane'
link_template = '%s/layout/tab-link.html'
def render_link(self, template_pack=TEMPLATE_PACK, **kwargs):
"""
Render the link for the tab-pane. It must be called after render so css_class is updated
with active if needed.
"""
link_template = self.link_template % template_pack
return render_to_string(link_template, {'link': self})
/root/.pyenv/versions/3.7.3/lib/python3.7/site-packages/crispy_forms/templates/bootstrap3/layout/tab-link.html
<li class="tab-pane{% if 'active' in link.css_class %} active{% endif %}">{{ link.name|capfirst }}{% if tab.errors %}!{% endif %}</li>
I noticed the css_id attr. And I guessed that if one set 'css_id' properly, maybe crispy would do the rest. I tried. And it worked like a charm.
Maybe crispy documentation needs some improvement.
If you- like me- search for answer why this solution doesn't work for you, check if you are using bootstrap 4. To my knowledge tabs from crispy don't work on 5 at least for now.
Related
I have a large django model with about 800 objects and I want to create a view in which the user can select a certain number of those objects to pass to another view for further processing. The fact that there are so many objects of the model makes listing all the objects very unpractical, as the user would have to scroll through 800 objects.
In order to address this problem, I want to place an as-you-type search-bar in the top of the view so that the user can type the name of the objects and select them by clicking them. When the objects are selected, they should appear under the search-bar as tags that the user can remove by clicking an "x" next to each one.
When the user has made all the required selections, then they should be able to click a button and jump to the next view where those selected objects are accessible.
The model I am using can be simplified to:
class Song():
song_name = models.CharField(max_length=256)
song_author = models.CharField(max_length=256, blank=True)
song_content = models.TextField()
def __str__(self):
return self.song_name
class Meta:
ordering = ['song_order']
song_order = models.PositiveIntegerField(editable=False, db_index=True)
So far I have been able to make a view to search through the model.
mytemplate.html
<!DOCTYPE html>
{% load static %}
<html style="height: 100%;" lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="preload" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="https://unpkg.com/bootstrap-material-design#4.1.1/dist/css/bootstrap-material-design.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
</head>
<body>
{% block body_block %}
<div class="container" style="padding-bottom:40px;margin-top: 35px;">
<div class="form-group">
<label for="searchInput" class="bmd-label-floating">Search</label>
<input type="text" class="form-control" id="searchInput" oninput="filter()">
</div>
<ul class="list-group bmd-list-group-sm">
{% for song in songs %}
<div
class="list-group-item"
data-title="{{song.song_name}}"
data-author="{{song.song_author}}"
data-lyrics="{{song.song_content}}">
<h4>
{{song.song_name}}
{% if song.song_author %}
({{ song.song_author }})
{% endif %}
</h4>
</div>
{% endfor %}
</ul>
</div>
<script>
$('#searchInput').focus();
function short(s) {
let punctuationRegEx = /[.,\/#!$%\^&\*;:{}=\-_`~()]/g;
return s.replace(punctuationRegEx, '')
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "");
}
function filter() {
let f = short($('#searchInput').val());
$('.list-group-item').each(function (index) {
if (short($(this).data('title') + "").includes(f) ||
short($(this).data('author') + "").includes(f)
) {
$(this).show();
} else {
$(this).hide();
}
});
}
</script>
{% endblock %}
</body>
</html>
views.py
class SongListView(ListView):
context_object_name = 'songs'
model = Song
template_name = "songapp/mytemplate.html"
Any ideas on how to do the selection?
I have created a part inventory program with the as you type search.
It's a complete example of ajax call for search and database.
You can modify it to show the results under the search with the X.
https://github.com/edcodes/Django-Parts-Inventory
For almost 5h I can't make detail view.
My app name -movies
My views:
"
def actor_view(request):
actor_list = Actor.objects.all()
context = {'actor_list': actor_list}
return render(request,'movies/actor.html',context)
def actor_detail_view(request,id):
actorrr=get_object_or_404(Actor,id=id)
context={
'actorrr':actorrr,
}
return render(request,"movies/actor_detail_view.html",context)
My model
class Actor(models.Model):
name = models.CharField(max_length=50)
date_of_birth = models.DateField()
age=models.IntegerField( null=True)
net_worth = models.TextField(max_length=140, null=True)
picture=models.URLField(default = '')
children =models.TextField(max_length=140, null=True)
marital_status=models.TextField(max_length=140, null=True)
My actor html:
{% load static %}
{% block mainbody %}
{% for actor in actor_list %}
<!DOCTYPE html>
<html>
<head>
<title>List of actors we have</title>
<link rel="stylesheet" href="{% static 'css/style_actor.css' %}">
</head>
<body>
<div class="card" >
<div class="card-image">
<img src="{{ actor.picture }}" alt="No poster in datebase" width="289" height="345">
</div>
<div class="card-text">
<h2>
{{ actor.name }}
</h2>
<p>{{movie.pilot}}</p>
</div>
<div class="card-imdb-score">
<p
>Age: {{ actor.age }}
</p>
</div>
</div>
</body>
</html>
{% endfor %}
{% endblock %}
My actor_detail html
<h6>TEST</h6>
movies url:
path('actor_detail_view/<int:id>',views.actor_detail_view,name='actor_detail_view'),
and the main url:
path('<int:id>/',views.actor_detail_view,name="actor_detail_view")
So I have no idea how to make urls and what to place in actor.html in href url.I've made many tutorials and still couldn't do it.
First of all, I recommends to you set the name of variable actorrr correctly.
If you're using Pycharm IDEA, the idea helps you to avoid problems with names of variables or spaces, following PEP08.
Some tips:
verify your urls.py file, to see if exists "/movies/actor_detail/{{actor.id }}
Probably, you have to add django template structure to appear the data of actor detail HTML, without for looping, because it's just one data.
your link to the actor detail page must be like this :
<a href={% url 'actor_detail_view' actor.id %}
also it's better to use django generic views to get detailed models.
I recommend you use CBVs, in this case, DetailView, I had same project and I put code here to use:
class DetailedActor(DetailView):
template_name = 'your_template'
model = models.YourModel
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
return context
then in your template, you have an instance of your model whit a specific actor! just don't forget to pass the id when you render to the URL assigned to this view
so Im building and simple mooc plataform using Django 2.1 and Im having a problem.
Here you can find my entire project but ill describe all situation above, and here u can find a entire printscreen of django error.
So i have this project called TamerMooc, this project has 2 apps. A core app and a courses app.
This is the /courses/views.py file:
from django.shortcuts import render, get_object_or_404
from .models import Course
def index(request):
courses = Course.objects.all()
template_name = 'courses/index.html'
context = {
'courses':courses
}
return render(request, template_name, context)
def details(request, slug):
course = get_object_or_404(Course, slug=slug)
template_name = 'courses/details.html'
context = {
'course': course
}
return render(request, template_name, context)
And this is the /courses/urls.py file:
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('',views.index ,name='index'),
path('<slug:slug>', views.details , name='details'),
]
And at least the /core/templates/base.html file quoted in the error file.
<!doctype html>
{% load static %}
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Simple MOOC - Uma simples plataforma de ensino a distância" />
<title>Tâmer MOOC</title>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.3.0/pure-min.css">
<link rel="stylesheet" href="{% static 'css/styles.css' %}" />
</head>
<body>
<div class="header">
<div class="pure-menu pure-menu-open pure-menu-fixed pure-menu-horizontal">
<a class="pure-menu-heading" href="{% url 'home' %}">TÂMER MOOC</a>
<ul>
<li class="pure-menu-selected">Início</li>
<li>Cursos</li>
<li><a href="{% url 'contact' %}"}>Contato</a></li>
</ul>
</div>
</div>
<div class = "content">
{% block content %}{% endblock %}
<div class="footer">
Tâmer MOOC - Uma simples plataforma de ensino a distância
</div>
</div>
<script src="http://yui.yahooapis.com/3.12.0/build/yui/yui-min.js"></script>
</body>
</html>
I really read a lot of questions here on stackoverflow about similar errors but cant find a solution.
I think the problem is here.
<a href=" {{ course.get_absolute_url }} "> <!--- {% url 'courses:details' course.slug %}--->
^^^^^ ^^^^
In django template, comments does not work in this way. If you want to comment out something do it like this:
{% comment %}
{% url 'courses:details' course.slug %}
{% endcomment %}
Or
{# url 'courses:details' course.slug #}
Relevant documentation can be found here.
I'm not familiar with javascript but I've been commenting out this js plugin, made for django projects, and using .modal("show") as a signifier for when the code actually had executed - and I cannot see why this doesn't show the modal (meaning it never got past the load statement).
modal_forms.js
(function ($) {
// Open modal & load the form at formURL to the modalContent element
var newForm = function (modalID, modalContent, modalForm, formURL, errorClass, submitBtn) {
##IT WOULD SHOW MODAL IF SCRIPT HERE##
$(modalContent).load(formURL, function () {
$(modalID).modal("show");
##DESIGNED TO SHOW HERE BUT DOESNT##
$(modalForm).attr("action", formURL);
// Add click listener to the submitBtn
ajaxSubmit(modalID, modalContent, modalForm, formURL, errorClass, submitBtn);
});
};
// Add click listener to the submitBtn
var ajaxSubmit = function (modalID, modalContent, modalForm, formURL, errorClass, submitBtn) {
...};
// Check if form.is_valid()
var isFormValid = function (modalID, modalContent, modalForm, formURL, errorClass) {
...};
$.fn.modalForm = function (options) {
// Default settings
var defaults = {
modalID: "#modal",
modalContent: ".modal-content",
modalForm: ".modal-content form",
formURL: null,
errorClass: ".invalid",
submitBtn: ".submit-btn"
};
// Extend default settings with provided options
var settings = $.extend(defaults, options);
return this.each(function () {
// Add click listener to the element with attached modalForm
$(this).click(function (event) {
// Instantiate new modalForm in modal
newForm(settings.modalID,
settings.modalContent,
settings.modalForm,
settings.formURL,
settings.errorClass,
settings.submitBtn);
});
});
};
}(jQuery));
This is referenced in my base template that would be extended by other templates that make up the body content and not just the navigation bar. The sections highlighted show the button that will trigger the modalForm function, an empty modal form and at the bottom the js script that links the trigger and the modalForm function.
base.html
<!DOCTYPE html>
<html lang="en">
<head>
{% load staticfiles %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"/> <!--bootstrap css-->
<link rel="stylesheet" type="text/css" href="{% static 'WebProjects/style.css' %}"/> <!--style file-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <!--icons-->
{% block head %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#"></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="{% url 'webprojects:index' %}">ProjectOverview<span class="sr-only">(current)</span></a>
<li class="nav-item active">
<!-- Creating a new project, Pop up trigger -->
<button class="create-project btn btn-primary" type="button" name="button" id="modalTrigger"> <!--class="nav-link ml-sm-1" href="#"-->
<i class="fa fa-plus-circle"></i> AddProject <span class="sr-only">(current)</span>
</button>
</ul>
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content" id="modalContent"></div>
</div>
</div>
...
</div>
</nav>
{% block body %}{% endblock %}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script> <!-- Refrencing js assets and bootstrap -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js"></script>
<!-- jQuery plugins found unsuitable, Reverse engineered and modified version found bellow -->
<script src="{% static 'WebProjects/js/modal_forms.js' %}"></script>
<script>
$(document).ready(function() {
$("#modalTrigger").modalForm({
formURL: "{% url 'webprojects:create_projects' %}"
});
});
</script>
</body>
</html>
The complexity of this is that instead of just a static form in the modal, it is meant to load the form that would only be generated at the view that the URL is linked with - without leaving the page.
urls.py
from django.urls import path
from . import views
app_name = 'webprojects'
urlpatterns = [
# /projects/
path('', views.IndexView.as_view(), name='index'),
# /projects/-/create
path('create', views.ProjectsCreateView.as_view(), name='create_projects')
]
views.py
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.views import generic
from django.views.generic.edit import CreateView # UpdateView, DeleteView
from .mixins import PassRequestMixin
from .models import Projects
from .forms import ProjectsForm
class IndexView(generic.ListView):
template_name = 'WebProjects/index.html'
queryset = Projects.objects.all() # pylint: disable=E1101
class DetailView(generic.DetailView):
model = Projects
template_name = 'WebProjects/detail.html'
class ProjectsCreateView(PassRequestMixin, SuccessMessageMixin, CreateView):
form_class = ProjectsForm
template_name = 'WebProjects/create_projects.html'
success_message = "Success"
success_url = reverse_lazy('index')
forms.py
from django import forms
from .models import Projects
from .mixins import PopRequestMixin, CreateUpdateAjaxMixin
class ProjectsForm(PopRequestMixin, CreateUpdateAjaxMixin, forms.ModelForm):
class Meta:
model = Projects
fields = ['project', 'description']
Another part of django-bootstrap-modal-forms is the mixins used in these two files.
mixins.py
from django.contrib import messages
from django.contrib.auth import (REDIRECT_FIELD_NAME, get_user_model, login as auth_login)
from django.http import HttpResponseRedirect
class PassRequestMixin(object):
"""
Mixin which puts the request into the form's kwargs.
Note: Using this mixin requires you to pop the `request` kwarg
out of the dict in the super of your form's `__init__`.
"""
def get_form_kwargs(self):
kwargs = super(PassRequestMixin, self).get_form_kwargs()
# Update the existing form kwargs dict with the request's user.
kwargs.update({"request": self.request})
return kwargs
class PopRequestMixin(object):
"""
Mixin which pops request out of the kwargs and attaches it to the form's
instance.
Note: This mixin must precede forms.ModelForm/forms.Form. The form is not
expecting these kwargs to be passed in, so they must be popped off before
anything else is done.
"""
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(PopRequestMixin, self).__init__(*args, **kwargs)
class CreateUpdateAjaxMixin(object):
"""
Mixin which passes or saves object based on request type.
"""
def save(self, commit=True):
if not self.request.is_ajax():
instance = super(CreateUpdateAjaxMixin, self).save(commit=commit)
else:
instance = super(CreateUpdateAjaxMixin, self).save(commit=False)
return instance
I've focussed on experimenting with the html and js rather than the python back-end but only because I have confidence that it is not the cause of the problem - unless the way I have the back end is simply not suited for how the load function is intended to be used.
I do hope I'm simply making a small mistake, any creative suggestions appreciated xoxo
I have a django (2.0) application with a page that contains two separate forms that are not meant to interact with each other at all. However, I am getting some weird behavior. Pictured here, when I click on one of the labels on the bottom form, it triggers the checkbox for the corresponding (based on row, not name) element in the upper form (clicking "members" on the group form selected "Email" on the person form). This only goes one way--clicking anywhere on the top form never effects the bottom form. Checking the actual boxes of the bottom form do trigger the expected boxes that their labels correspond to.
The html for this page is:
<head>
{% load static %}
<title>LDAP - Search</title>
<link rel="shortcut icon" href="{% static 'djangoWrapper/favicon.ico' %}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{% static 'ldap/style.css' %}">
</head>
<body>
<h1>Search</h1>
<div class="search-form">
<h2>Search for Person</h2>
<form action="{% url 'ldap:person_results' %}" method='post'>
{% csrf_token %}
<table>
{{ personForm }}
</table>
<input type="submit" value="Search">
</form>
</div>
<div class="search-form">
<h2>Search for Group</h2>
<form action="{% url 'ldap:group_results' %}" method='post'>
{% csrf_token %}
<table>
{{ groupForm }}
</table>
<input type="submit" value="Search" />
</form>
</div>
<div class="url">
or go back to login
</div>
</body>
And the forms are
class PersonSearchForm(forms.Form):
uniqname = forms.CharField(label="uniqname", max_length=10)
options = personFieldsDict.items()
attributes = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple, choices = options, label='',
required=False)
class GroupSearchForm(forms.Form):
groupName = forms.CharField(label='Group Name')
options = groupFieldsDict.items()
attributes = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple, choices = options, label='',
required=False)
And the view that renders this page is simply:
def search(request):
personForm = PersonSearchForm()
groupForm = GroupSearchForm()
context = {'personForm': personForm, 'groupForm': groupForm}
return render(request, 'ldap/search.html', context)
I am guessing that this has something to do with the fact that both forms use a MultipleChoiceField widget, but I can't see how they are interacting with each other if their attributes are different and they are in different div's. Any idea on why there is this interaction? Thanks.
You should use the prefix argument to one or both forms to prevent the fields from interferin with each other.
personForm = PersonSearchForm(prefix="person")
groupForm = GroupSearchForm(prefix="group")
Don't forget to also use the prefixes when instantiating the form on post.