2👍
In my opinion each view should do have one purpose. Doesn’t mean you cannot have multiple form elements in a single page. You can do it by
Make a normal view that would only process the data. You would set the url of the view, and then make an ajax call to that view. This can be easily achievable if you are willing to use JavaScript for that as well.(simple xhr methods, blur,change events)
Ex:-
class FormElementProcess(View):
def post(self,request,*args,**kwargs):
#Do your processing and return httpresponse
You can further customise the above class and also use formviews for processing and returning of form data, if a form class is also used.
This would be the way out of this I guess. Suppose I have dozens of forms in my Homepage. Forms like -> search,login,register etc. I wouldn’t be handling everything through my IndexView. That would over complicate everything when the application would get larger in scale.
2) If page refreshes, then I would suggest you use a FormMixin.
There’s a good implementation I found for making FormListView
from django.http import Http404
from django.utils.translation import ugettext as _
from django.views.generic.edit import FormMixin
from django.views.generic.list import ListView
class FormListView(FormMixin, ListView):
def get(self, request, *args, **kwargs):
# From ProcessFormMixin
form_class = self.get_form_class()
self.form = self.get_form(form_class)
# From BaseListView
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty and len(self.object_list) == 0:
raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
context = self.get_context_data(object_list=self.object_list, form=self.form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
class MyListView(FormListView):
form_class = MySearchForm
model = MyModel
# ...
You would modify the post method further to do your processing. You could directly use the form class, include parameters from request for processing.
1👍
An example of using function-based view to achieve what you want is as follows:
contacts/models.py:
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Contact(models.Model):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.email
contacts/forms.py:
from django import forms
class UserForm(forms.Form):
search = forms.CharField(label='Search', max_length=100)
contacts/views.py:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render, redirect
from .models import Contact
from .forms import UserForm
def my_contacts(request):
form = UserForm()
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
# Do something with form data here
print(form.cleaned_data['search'])
redirect('my_contacts')
contacts_list = Contact.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(contacts_list, 10)
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
return render(request, 'contacts/contacts.html', {'contacts': contacts, 'form': form})
contacts/urls.py:
from django.conf.urls import patterns, url
urlpatterns = patterns(
'contacts.views',
url(r'^$', 'my_contacts', name='my_contacts'),
)
templates/contacts/contacts.html:
{% extends 'base.html' %}
{% block 'container' %}
<div class="row">
<div class="col-sm-12">
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered">
<thead>
<tr>
<th>Email</th>
<th>First name</th>
<th>Last name</th>
</tr>
</thead>
<tbody>
{% for contact in contacts %}
<tr>
<td>{{ contact.email }}</td>
<td>{{ contact.first_name }}</td>
<td>{{ contact.last_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if contacts.has_other_pages %}
<ul class="pagination">
{% if contacts.has_previous %}
<li><a href="?page={{ contacts.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in contacts.paginator.page_range %}
{% if contacts.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if contacts.has_next %}
<li><a href="?page={{ contacts.next_page_number }}">»</a></li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
</div>
</div>
{% endblock %}
templates/base.html:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>{% block 'title'%}{% endblock %}</title>
<!-- Bootstrap Core CSS -->
<link href={% static 'css/bootstrap.min.css' %} rel="stylesheet">
</head>
<body>
<!-- Page Content -->
<div class="container" style="padding-top: 50px;">
{% block 'container' %}{% endblock %}
</div>
<!-- /.container -->
<script src="{% static 'js/jquery.js' %}"></script>
<!-- Bootstrap Core JavaScript -->
<script src="{% static 'js/bootstrap.min.js' %}"></script>
</body>
</html>
- [Django]-How does one include the server hostname in a django error email?
- [Django]-Import data into Django model with existing data?
- [Django]-How to get currently logged user id in form model in Django 1.7?