Creating Views in Django
A view is just a Python function that will take a request and then return a response object.
The response can be in the form of the HTML content for your web page.
Consider the example given below, which shows how a simple view can be created in Django:
from django.http import HttpResponse
def hello(request):
text = ”””<h1>welcome to my application </h1>”””
return HttpResponse(text)
The above view should give you the message “welcome to my application”.
When presenting our view, we can make use of the MVT pattern. Suppose that we have the template “myapplication/templates/hello.html”. Our view can be created as follows:
from django.shortcuts import render
def hello(request):
return render(request, “myapplication/template/hello.html”, {})
It is possible for us to pass parameters to our view. This is demonstrated below:
from django.http import HttpResponse
def hello(request, number):
text = “<h1>welcome to my application number %s!</h1>”% number
return HttpResponse(text)
When it is linked to a URL, the number which has been passed as the parameter will be displayed.
- Class Based Views :-
These views are used for sub-class View and then to implement the HTTP methods that it can support. Class based views can be implemented as shown in the following program:
from django.http import HttpResponse
from django.views.generic import View
class OurView(View):
def get(self, request, *args, **kwargs):
return HttpResponse(“Hello, there!”)
In this type of view, the HTTP methods should be mapped to the class method names. In the above example, we have a defined a handler for the GET requests with a “get” method. Just like we have implemented the function, the “request” will be taken as the first argument, and an HTTP response will be returned.
- Listing Contacts :-
Suppose we want to write a view that will give us a list of contacts that have been stored in a database. The following code can help us implement this:
from django.views.generic import ListView
from contacts.models import Contact
class ListContactView(ListView):
model = Contact
The ListView we have subclassed from is made up of numerous mixins that are expected to provide some behavior. A code such as this gives us a lot of power while using less code. We can then use “model = Contact”, which will list the contacts we have stored in the database.
- Definition of URLs :-
The configuration of URL informs Django as to how to match the path of a request to the Python code. Django will look for URL configuration that has been defined as “urlpatterns”.
We can now add a URL mapping for the contact list view. This is shown below:
from django.conf.urls import patterns, include, url
import contacts.views
urlpatterns = patterns(”,
url(r’^$’, contacts.views.ListContactView.as_view(),
name=‘contacts-list’,),
)
Although it is not a must for us to use the “url()” function, it is of great importance as after we begin to add more information to our URL pattern, it will allow us to make use of named parameters, and everything will be made much clearer. Note that we have used a regular expression as the first parameter.
- Creation of a Template :-
Note that a URL has already been defined for the list view, and we can try this out. Django usually provides us with a server that we can use during development for the purpose of testing our projects. This is shown below:
$ python manage.py runserver
Validating models…
0 errors found
Django version 1.4.3, using settings ‘addressbook.settings’
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
At this time, visiting the URL, that is, http://localhost:8000/will give you an error:
“TemplateDoesNotExist”.
This is because, from our code, the system was expecting to get a URL, but we have not yet created it. We can then go ahead and create it.
The default setting is that Django looks for templates in the applications and the directory you have specified in “settings.TEMPLATE_DIRS”. Generic views usually expect to find the templates in the directory that has been named after the application, and the model is expected to have the model name. This is especially useful in the distribution of a reusable application, as the consumer is able to create templates that override the defaults, and they have to be stored in a directory whose name is associated with that of the application.
In this case, there is no need for an additional layer, and that is why we want to specify the template that is to be used explicitly. Therefore, we use the “template_name” property. That line can be added to our code as shown below:
from django.views.generic import ListView
from contacts.models import Contact
class ListContactView(ListView):
model = Contact
template_name = ‘contact_list.html’
You can then create a subdirectory named “templates” in your “contacts” app, and then create the view “contacts_list” there. The code for this is shown below:
<h1>Contacts</h1>
<ul>
{% for contact in object_list %}
<li class=“contact”>{{ contact }}</li>
{% endfor %}
</ul>
You can open the file in your browser and be able to see the contacts that you have added to your database.
- Creation of the Contacts :-
Since we need to add some contacts to our database, doing so via the shell will make the process too slow. We should create a view that will help us do it. This can be added as shown below:
from django.views.generic import CreateView
from django.core.urlresolvers import reverse
…
class CreateContact(CreateView):
model = Contact
template_name = ‘edit_contact.html’
def get_success_url(self):
return reverse(‘contacts-list’)
In generic views that carry out form processing, the concept of “success URL” is used. This is used for redirecting the user after they have submitted the form successfully.
The code for “edit_contact.html” should be as shown below:
<h1>Add Contact</h1>
<form action=”{% url “contacts-new” %}” method=“POST”>
{% csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input id=“save_contact” type=“submit” value=“Save” />
</form>
<a href=”{% url “contacts-list” %}”>back to list</a>
Note that we have made use of the Django Form for the model. This is because we specified none and so Django created it for us. The following line of code can be added to our “url.py” file so as to configure the URL:
url(r’^new$’, contacts.views.CreateContact.as_view(),
name=‘contacts-new’,),
Once you open the URL http://localhost:8000/new on your browser, you will be allowed to create the contacts.
We can then add a link that will lead us to the “contacts_list.html” page as shown below:
<h1>Contacts</h1>
<ul>
{% for contact in object_list %}
<li class=“contact”>{{ contact }}</li>
{% endfor %}
</ul>
<a href=”{% url “contacts-new” %}”>add contact</a>
- Testing Views :-
In Django, two tools can help us in testing views: “RequestFactory” and “TestClient”. TestClient will take the URL to be retrieved, and then it will resolve it according to the URL configuration of the project. A test request will then be created, and this will then be passed through the view, and a response will be returned.
The RequestFactory makes use of a similar API. In this case, one has to specify the URL that is to be retrieved, as well as the form data or the parameters. However, this will not resolve the URL, but it will return the Request object. The result can then be passed to the view manually and the result tested.
Tests carried using RequestFactory are usually faster compared to ones carried out using TestClient. This might sound like a small issue, but it is of great significance when you are carrying out large tests.
We need to demonstrate how each kind of test can be carried out in Django. Consider the code given below:
from django.test.client import RequestFactory
from django.test.client import Client
…
from contacts.views import ListContactView
…
class ContactViewTests(TestCase):
“““Contact list view tests.”””
def test_contacts_in_the_context(self):
client = Client()
response = client.get(‘/’)
self.assertEquals(list(response.context[‘object_list’]), [])
Contact.objects.create(f_name=‘foo’, l_name=‘bar’)
response = client.get(‘/’)
self.assertEquals(response.context[‘object_list’].count(), 1)
def test_contacts_in_the_context_request_factory(self):
factory = RequestFactory()
request = factory.get(‘/’)
response = ListContactView.as_view()(request)
self.assertEquals(list(response.context_data[‘object_list’]), [])
Contact.objects.create(first_name=‘foo’, last_name=‘bar’)
response = ListContactView.as_view()(request)
self.assertEquals(response.context_data[‘object_list’].count(), 1)
- Integration Tests :-
We can use a tool named “Selester”, which is good for writing tests and driving a browser. With this tool, automation of different browsers can be done easily, and we will be in a position to interact with the full app just as the user would do. This tool can be installed as follows:
$ pip install selenium
We need to implement a number of tests for our views, for the following purposes::
1. ) To create a contact and ensure that it is listed.
2. ) To ensure the “add contact” link is visible and has been linked to the list page.
3. ) To exercise the “add contact” form, fill it in and then submit the form.
This is shown below:
from django.test import LiveServerTestCase
from selenium.webdriver.firefox.webdriver import WebDriver
…
class ContactIntegrationTests(LiveServerTestCase):
@classmethod
def setUpClass(cls):
cls.selenium = WebDriver()
super(ContactIntegrationTests, cls).setUpClass()
@classmethod
def tearDownClass(cls):
cls.selenium.quit()
super(ContactIntegrationTests, cls).tearDownClass()
def test_contact_listed(self):
# creating a test contact
Contact.objects.create(f_name=‘foo’, l_name=‘bar’)
# ensure it is listed as <first> <last> on our list
self.selenium.get(‘%s%s’ % (self.live_server_url, ‘/’))
self.assertEqual(
self.selenium.find_elements_by_css_selector(‘.contact’)[0].text,
‘foo bar’
)
def test_add_contact_linked(self):
self.selenium.get(‘%s%s’ % (self.live_server_url, ‘/’))
self.assert_(
self.selenium.find_element_by_link_text(‘add contact’)
)
def test_add_contact(self):
self.selenium.get(‘%s%s’ % (self.live_server_url, ‘/’))
self.selenium.find_element_by_link_text(‘add contact’).click()
self.selenium.find_element_by_id(‘id_f_name’).send_keys(‘test’)
self.selenium.find_element_by_id(‘id_l_name’).send_keys(‘contact’)
self.selenium.find_element_by_id(‘id_email’).send_keys(‘test@domain.com’)
self.selenium.find_element_by_id(“save_contact”).click()
self.assertEqual(
self.selenium.find_elements_by_css_selector(‘.contact’)[-1].text,
‘test contact’
)
👈Episode 4(D). Episode 6 (D)👉
Share This Post
PRINT THIS POST
No comments:
Post a Comment
If you have any doubts. Please let me know.