10. Django 1.8 Server Build - CentOS 7 hosted on VPS - Views 2 (home page and more templates)
In previous chapter (9. Django 1.8 Server Build - CentOS 7 hosted on VPS - Views (templates and css)), we learned about views via views.py, urls.py, templates, and css.
We have http://djangotest.sfvue.com/admin and http://djangotest.sfvue.com/cars/, however, we do not have our home page yet:
Here is the modified djangotest/urls.py:
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', 'car.views.index'), url(r'^cars/$', 'car.views.CarsAll'), ]
car/views.py:
from django.shortcuts import render_to_response from django.template import RequestContext from car.models import Car def CarsAll(request): cars = Car.objects.all().order_by('name') context = {'cars': cars} return render_to_response('carsall.html',context, context_instance=RequestContext(request)) def index(request): return render_to_response('index.html')
The render_to_response(template_name) renders a given template and returns an HttpResponse object with that rendered text.
car/templates/index.html:
{% extends "base.html" %} {% block content %} <a href="cars/">View the Cars list</a> {% endblock %}
http://djangotest.sfvue.com/ page has a link on the top-left:
If we click the link, we get http://djangotest.sfvue.com/cars/ page:
Before we go deep into templates world, let's look at how template gets rendered (The first views).
Django templates are normal Python objects whose constructor expects a string. The placeholders are replaced with the values from a context object.
The following example shows how a dictionary can be used as data structure:
$ python manage.py shell Python 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> from django.template import Context, Template >>> t = Template('My name is {{ person.first_name }}.') >>> d = {'person': {'first_name': 'bogotobogo'}} >>> t.render(Context(d)) u'My name is bogotobogo.'
We can use a Python object as data structure:
>>> class Person: pass ... >>> p = Person() >>> p.first_name = 'bogotobogo' >>> c = Context({'person': p}) >>> t.render(c) u'My name is bogotobogo.' >>>
Lists can be used as well:
>>> t = Template('First article: {{ articles.0 }}') >>> c = Context({'articles': ['bread', 'eggs', 'milk']}) >>> t.render(c) u'First article: bread' >>>
We want to list one item per line instead of just printing out all in one line:
{% extends "base.html" %} {% block content %} <div id="carslist"> {% for car in cars %} <p><a href="/cars/{{ car.slug }}">{{ car }}</a></p> {% endfor %} </div> {% endblock %}
Note that we used {{ variable }} forms for {{ car.slug }} and {{ car }}. When the template engine encounters a variable, it evaluates that variable and replaces it with the result.
But if we click the link, we get 404 error:
Let's work on displaying specific car item.
We want to make the broken link in the previous section.
from django.shortcuts import render_to_response from django.template import RequestContext from car.models import Car def CarsAll(request): cars = Car.objects.all().order_by('name') context = {'cars': cars} return render_to_response('carsall.html',context, context_instance=RequestContext(request)) def index(request): return render_to_response('index.html') def SpecificCar(request, carslug): c = Car.objects.get(slug=carslug) context = {'car': c} return render_to_response('singlecar.html')
We need to modify urls.py.
Open djangotest/urls.py and add an url for the specific car item:
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', 'car.views.index'), url(r'^cars/$', 'car.views.CarsAll'), url(r'^cars/(?P<carslug>.*)/$', 'car.views.SpecificCar'), ]
In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.
It passes a variable carslug to car.views.SpecificCar.
{% extends "base.html" %} {% block content %} <div id="singlecar"> <p>Name: {{ car }}</p> <p>Locality: {{ car.locality }}</p> <p>Make: {{ car.make }}</p> </div> {% endblock %}
Now, if we click the link we get a page for the single car item:
Let's make a minor change for the display of locality. In other words, we want "Import" instead of just "I". To see what function we can use, let's use shell:
>>> from car.models import Car >>> c = Car.objects.get(name='M6 Coupe') >>> c <Car: M6 Coupe> >>> c.slug u'BMW-M6-F12-Coupe-2015' >>> dir(c) ['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', u'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_base_manager', '_check_column_name_clashes', '_check_field_name_clashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_local_fields', '_check_long_column_names', '_check_m2m_through_same_relationship', '_check_managers', '_check_model', '_check_ordering', '_check_swappable', '_check_unique_together', '_default_manager', '_deferred', '_do_insert', '_do_update', '_get_FIELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', '_save_parents', '_save_table', '_set_pk_val', '_state', 'check', 'clean', 'clean_fields', 'date_error_message', 'delete', 'description', 'from_db', 'full_clean', 'get_deferred_fields', 'get_locality_display', 'id', 'locality', 'make', 'make_id', 'name', 'objects', 'pk', 'prepare_database_save', 'refresh_from_db', 'save', 'save_base', 'serializable_value', 'slug', 'unique_error_message', 'validate_unique'] >>> c.get_locality_display() u'Import' >>>
So, let's go back to templates/singlecar.html, and modify it:
{% extends "base.html" %} {% block content %} <div id="singlecar"> <p>Name: {{ car }}</p> <p>Locality: {{ car.get_locality_display }}</p> <p>Make: {{ car.make }}</p> </div> {% endblock %}
Note that we're not using "()" for get_locality_display in the templates.
Now, if the page is display "Import" rather than just "I":
Let's get the list of cars from a specific Makes.
Open up car/views.py, and we filter our cars from a given Makes
from django.shortcuts import render_to_response from django.template import RequestContext from car.models import Car from car.models import Make def CarsAll(request): cars = Car.objects.all().order_by('name') context = {'cars': cars} return render_to_response('carsall.html',context, context_instance=RequestContext(request)) def index(request): return render_to_response('index.html') def SpecificCar(request, carslug): c = Car.objects.get(slug=carslug) context = {'car': c} return render_to_response('singlecar.html', context, context_instance=RequestContext(request)) def SpecificMake(request, makeslug): m = Make.objects.get(slug=makeslug) cars = Car.objects.filter(make=m) context = {'cars': cars} return render_to_response('singlemake.html', context, context_instance=RequestContext(request))
Then, urls.py:
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', 'car.views.index'), url(r'^cars/$', 'car.views.CarsAll'), url(r'^cars/(?P<carslug>.*)/$', 'car.views.SpecificCar'), url(r'^makes/(?P<makeslug>.*)/$', 'car.views.SpecificMake'), ]
Then, car/templates/singlemake.html:
{% extends "base.html" %} {% block content %} <div id="carslist"> <h2>Cars from {{ cars.0.make }}</h2> {% for c in cars %} <p><a href="/cars/{{ c.slug }}/">{{ c }}</a></p> {% endfor %} </div> {% endblock %}
Also, we need to make the make a link in car/templates/singlecar.html:
{% extends "base.html" %} {% block content %} <div id="singlecar"> <p>Name: {{ car }}</p> <p>Locality: {{ car.get_locality_display }}</p> <p>Make: <a href="/makes/{{ car.make.slug }}/">{{ car.make }}</a></p> </div> {% endblock %}
If we click on "M6 Convertible 2013", we get:
Then, at the click Make BMW, we get the list of cars from that specific make:
Continued in 11. TinyMCE
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization