There isn't anything complicated about what we'll do here. It should be very easy for you to follow along, so I'll just give you the code to write and leave the explanation, as we have done all of this many times before in the previous chapters.
Start by creating a templates
directory in the project root. Next, add it to the list of DIRS
in the TEMPLATES
configuration variable in our formmason/settings.py
file. The settings.py
file already has a TEMPLATES
variable configured, so go ahead and replace the DIRS
list in this dictionary with the value that you see here:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(BASE_DIR, 'templates'), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Next, create a base.html
template in the new templates
directory that you just created and put this code in there:
<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Form Mason</title> </head> <body> <a href="{% url 'home' %}">Home</a> {% block content %} {% endblock %} </body> </html>
Modify main/templates/custom_form.html
to match this:
{% extends "base.html" %} {% block content %} <h1>Custom Form</h1> <form action="" method="post">{% csrf_token %} {{ form.as_p }} <input type="submit" value="Submit" /> </form> {% endblock %}
Change main/views.py
to this:
from django import forms from django.views.generic import FormView from django.views.generic import ListView from main.models import FormSchema class HomePageView(ListView): model = FormSchema template_name = "home.html" class CustomFormView(FormView): template_name = "custom_form.html" def get_form(self): form_structure = FormSchema.objects.get(pk=self.kwargs["form_pk"]).schema custom_form = forms.Form(**self.get_form_kwargs()) for key, value in form_structure.items(): field_class = self.get_field_class_from_type(value) if field_class is not None: custom_form.fields[key] = field_class() else: raise TypeError("Invalid field type {}".format(value)) return custom_form def get_field_class_from_type(self, value_type): if value_type == "string": return forms.CharField elif value_type == "number": return forms.IntegerField else: return None
Create a new home template at main/templates/home.html
and give it the following code:
{% extends "base.html" %} {% block content %} <h1>Available Forms</h1> {% if object_list %} <ul> {% for form in object_list %} <li><a href="{% url 'custom-form' form_pk=form.pk %}">{{ form.title }}</a></li> {% endfor %} </ul> {% endif %} {% endblock %}
Finally, change formmason/urls.py
to match this:
from django.conf.urls import url from main.views import CustomFormView from main.views import HomePageView urlpatterns = [ url(r'^$', HomePageView.as_view(), name='home'), url(r'^form/(?P<form_pk>d+)/$', CustomFormView.as_view(), name='custom-form'), ]
Once you have done all this, open up the home page for the application again at http://127.0.0.1:8000
, and you should see a page similar to this:
Clicking on the link for the form should take you to the same form page that we had before; the only difference is that now it is served at the URL, http://127.0.0.1:8000/form/1/
.
Like I said, all this is pretty basic stuff that we have done repeatedly in the past few chapters. One thing that might be new is our use of self.kwargs['form_pk']
in the CustomFormView.get_form
method. Here's the relevant line:
form_structure = FormSchema.objects.get(pk=self.kwargs["form_pk"]).schema
For any generic view that Django provides (except for the base View
class), self.kwargs
is a dictionary of all named parameters that matched the URL pattern. If you look at our formmason/urls.py
file, we defined the URL for our custom form page like this:
url(r'^form/(?P<form_pk>d+)/$', CustomFormView.as_view(), name='custom-form')
In our view, the form_pk
parameter defined in the regex pattern for the URL is available in self.kwargs
. Likewise, any non-keyword parameters in the URL pattern are available for use in self.args
.
Now that we have a useable user interface, we will move on to storing the form responses in our database and giving our customers a page to view these responses.
18.116.19.75