<h1>Game website<aclass="headerlink"href="#game-website"title="Permalink to this headline">¶</a></h1>
<p>When Evennia starts it will also start a <aclass="reference internal"href="Webserver.html"><spanclass="doc std std-doc">Webserver</span></a> as part of the
<aclass="reference internal"href="Portal-And-Server.html"><spanclass="doc std std-doc">Server</span></a> process. This uses <aclass="reference external"href="https://docs.djangoproject.com">Django</a>
to present a simple but functional default game website. With the default setup,
open your browser to <aclass="reference external"href="http://localhost:4001">localhost:4001</a> or <aclass="reference external"href="http://127.0.0.1:4001">127.0.0.1:4001</a>
to see it.</p>
<p>The website allows existing players to log in using an account-name and
password they previously used to register with the game. If a user logs in with
the <aclass="reference internal"href="Webclient.html"><spanclass="doc std std-doc">Webclient</span></a> they will also log into the website and vice-versa.
So if you are logged into the website, opening the webclient will automatically
log you into the game as that account.</p>
<p>The default website shows a “Welcome!” page with a few links to useful
resources. It also shows some statistics about how many players are currently
connected.</p>
<p>In the top menu you can find</p>
<ulclass="simple">
<li><p><em>Home</em> - Get back to front page.</p></li>
<li><p><em>Documentation</em> - A link to the latest stable Evennia documentation.</p></li>
<li><p><em>Characters</em> - This is a demo of connecting in-game characters to the website.
It will display a list of all entities of the
_typeclasses.characters.Character` typeclass and allow you to view their
description with an optional image. The list is only available to logged-in
users.</p></li>
<li><p><em>Channels</em> - This is a demo of connecting in-game chats to the website. It will
show a list of all channels available to you and allow you to view the latest
discussions. Most channels require logging in, but the <codeclass="docutils literal notranslate"><spanclass="pre">Public</span></code> channel can
also be viewed by non-loggedin users.</p></li>
<li><p><em>Help</em> - This ties the in-game <aclass="reference internal"href="Help-System.html"><spanclass="doc std std-doc">Help system</span></a> to the website. All
database-based help entries that are publicly available or accessible to your
account can be read. This is a good way to present a body of help for people
to read outside of the game.</p></li>
<li><p><em>Play Online</em> - This opens the <aclass="reference internal"href="Webclient.html"><spanclass="doc std std-doc">Webclient</span></a> in the browser.</p></li>
<li><p><em>Admin</em> The [Web admin](Web admin) will only show if you are logged in.</p></li>
<li><p><em>Log in/out</em> - Allows you to authenticate using the same credentials you use
in the game.</p></li>
<li><p><em>Register</em> - Allows you to register a new account. This is the same as
creating a new account upon first logging into the game).</p></li>
</ul>
<sectionid="modifying-the-default-website">
<h2>Modifying the default Website<aclass="headerlink"href="#modifying-the-default-website"title="Permalink to this headline">¶</a></h2>
<p>You can modify and override all aspects of the web site from your game dir.
You’ll mostly be doing so in your settings file
(<codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/conf/settings.py</span></code> and in the gamedir’s <codeclass="docutils literal notranslate"><spanclass="pre">web/folder</span></code>
(<codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code> if your game folder is <codeclass="docutils literal notranslate"><spanclass="pre">mygame/</span></code>).</p>
<blockquote>
<div><p>When testing your modifications, it’s a good idea to add <codeclass="docutils literal notranslate"><spanclass="pre">DEBUG</span><spanclass="pre">=</span><spanclass="pre">True</span></code> to
your settings file. This will give you nice informative tracebacks directly
in your browser instead of generic 404 or 500 error pages. Just remember that
DEBUG mode leaks memory (for retaining debug info) and is <em>not</em> safe to use
for a production game!</p>
</div></blockquote>
<p>As explained on the <aclass="reference internal"href="Webserver.html"><spanclass="doc std std-doc">Webserver</span></a> page, the process for getting a web
page is</p>
<olclass="simple">
<li><p>Web browser sends HTTP request to server with an URL</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">urls.py</span></code> uses regex to match that URL to a <em>view</em> (a Python function or callable class).</p></li>
<li><p>The correct Python view is loaded and executes.</p></li>
<li><p>The view pulls in a <em>template</em>, a HTML document with placeholder markers in it,
and fills those in as needed (it may also use a <em>form</em> to customize user-input in the same way).
A HTML page may also in turn point to static resources (usually CSS, sometimes images etc).</p></li>
<li><p>The rendered HTML page is returned to the browser as a HTTP response. If
the HTML page requires static resources are requested, the browser will
fetch those separately before displaying it to the user.</p></li>
</ol>
<p>If you look at the <aclass="reference external"href="https://github.com/evennia/evennia/blob/develop/evennia/web">evennia/web/</a> directory you’ll find the following
structure (leaving out stuff not relevant to the website):</p>
<p><spanclass="versionmodified changed">Changed in version 1.0: </span>Game folders created with older versions of Evennia will lack most of this
convenient <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code> layout. If you use a game dir from an older version,
you should copy over the missing <codeclass="docutils literal notranslate"><spanclass="pre">evennia/game_template/web/</span></code> folders from
there, as well as the main <aclass="reference external"href="http://urls.py">urls.py</a> file.</p>
</div>
<p>As you can see, the <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code> folder is a copy of the <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/</span></code> folder
structure except the <codeclass="docutils literal notranslate"><spanclass="pre">mygame</span></code> folders are mostly empty.</p>
<p>For static- and template-files, Evennia will <em>first</em>
look in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/static</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">mygame/templates</span></code> before going to the default
locations in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/</span></code>. So override these resources, you just need to put
a file with the same name in the right spot under <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code> (and then
reload the server). Easiest is often to copy the original over and modify it.</p>
<p>Overridden views (Python modules) also need an additional tweak to the
<codeclass="docutils literal notranslate"><spanclass="pre">website/urls.py</span></code> file - you must make sure to repoint the url to the new
version rather than it using the original.</p>
</section>
<sectionid="examples-of-commom-web-changes">
<h2>Examples of commom web changes<aclass="headerlink"href="#examples-of-commom-web-changes"title="Permalink to this headline">¶</a></h2>
<divclass="admonition important">
<pclass="admonition-title">Important</p>
<p>Django is a very mature web-design framework. There are endless
internet-tutorials, courses and books available to explain how to use Django.
So these examples only serve as a first primer to get you started.</p>
</div>
<sectionid="change-title-and-blurb">
<h3>Change Title and blurb<aclass="headerlink"href="#change-title-and-blurb"title="Permalink to this headline">¶</a></h3>
<p>The website’s title and blurb are simply changed by tweaking
<codeclass="docutils literal notranslate"><spanclass="pre">settings.SERVERNAME</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">settings.GAME_SLOGAN</span></code>. Your settings file is in
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/conf/settings.py</span></code>, just set/add</p>
GAME_SLOGAN = "The best game in the world"
</pre></div>
</div>
</section>
<sectionid="change-the-logo">
<h3>Change the Logo<aclass="headerlink"href="#change-the-logo"title="Permalink to this headline">¶</a></h3>
<p>The Evennia googly-eyed snake logo is probably not what you want for your game.
The template looks for a file <codeclass="docutils literal notranslate"><spanclass="pre">web/static/website/images/evennia_logo.png</span></code>. Just
plop your own PNG logo (64x64 pixels large) in there and name it the same.</p>
</section>
<sectionid="change-front-page-html">
<h3>Change front page HTML<aclass="headerlink"href="#change-front-page-html"title="Permalink to this headline">¶</a></h3>
<p>The front page of the website is usually referred to as the ‘index’ in HTML
parlance.</p>
<p>The frontpage template is found in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/templates/website/index.html</span></code>.
Just copy this to the equivalent place in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/</span></code>. Modify it there and
reload the server to see your changes.</p>
<p>Django templates has a few special features that separate them from normal HTML
documents - they contain a special templating language marked with <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">...</span><spanclass="pre">%}</span></code> and
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">extends</span><spanclass="pre">"base.html"</span><spanclass="pre">%}</span></code> - This is equivalent to a Python
<codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">othermodule</span><spanclass="pre">import</span><spanclass="pre">*</span></code> statement, but for templates. It allows a given template
to use everything from the imported (extended) template, but also to override anything
it wants to change. This makes it easy to keep all pages looking the same and avoids
a lot of boiler plate.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">block</span><spanclass="pre">blockname</span><spanclass="pre">%}...{%</span><spanclass="pre">endblock</span><spanclass="pre">%}</span></code> - Blocks are inheritable, named pieces of code
that are modified in one place and then used elsewhere. This works a bit in reverse to
normal inheritance, because it’s commonly in such a way that <codeclass="docutils literal notranslate"><spanclass="pre">base.html</span></code> defines an empty
block, let’s say <codeclass="docutils literal notranslate"><spanclass="pre">contents</span></code>: <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">block</span><spanclass="pre">contents</span><spanclass="pre">%}{%</span><spanclass="pre">endblock</span><spanclass="pre">%}</span></code> but makes sure to put
that <em>in the right place</em>, say in the main body, next to the sidebar etc. Then each page
does <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">extends</span><spanclass="pre">"base.html</span><spanclass="pre">%"}</span></code> and makes their own <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">block</span><spanclass="pre">contents}</span><spanclass="pre"><actual</span><spanclass="pre">content></span><spanclass="pre">{%</span><spanclass="pre">endblock</span><spanclass="pre">%}</span></code>.
Their <codeclass="docutils literal notranslate"><spanclass="pre">contents</span></code> block will now override the empty one in <codeclass="docutils literal notranslate"><spanclass="pre">base.html</span></code> and appear in the right
place in the document, without the extending template having to specifying everything else
around it!</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">{{</span><spanclass="pre">...</span><spanclass="pre">}}</span></code> are ‘slots’ usually embedded inside HTML tags or content. They reference a
<em>context</em> (basically a dict) that the Python <em>view</em> makes available to it.
Keys on the context are accessed with dot-notation, so if you provide a
context <codeclass="docutils literal notranslate"><spanclass="pre">{"stats":</span><spanclass="pre">{"hp":</span><spanclass="pre">10,</span><spanclass="pre">"mp":</span><spanclass="pre">5}}</span></code> to your template, you could access
that as <codeclass="docutils literal notranslate"><spanclass="pre">{{</span><spanclass="pre">stats.hp</span><spanclass="pre">}}</span></code> to display <codeclass="docutils literal notranslate"><spanclass="pre">10</span></code> at that location to display <codeclass="docutils literal notranslate"><spanclass="pre">10</span></code> at
that location.</p></li>
</ul>
<p>This allows for template inheritance (making it easier to make all
pages look the same without rewriting the same thing over and over)</p>
<p>There’s a lot more information to be found in the <aclass="reference external"href="https://docs.djangoproject.com/en/3.2/ref/templates/language/">Django template language documentation</a>.</p>
</section>
<sectionid="change-webpage-colors-and-styling">
<h3>Change webpage colors and styling<aclass="headerlink"href="#change-webpage-colors-and-styling"title="Permalink to this headline">¶</a></h3>
<p>You can tweak the <aclass="reference external"href="https://en.wikipedia.org/wiki/Cascading_Style_Sheets">CSS</a> of the entire
website. If you investigate the <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/templates/website/base.html</span></code> file you’ll see that we
use the <aclass="reference external"href="https://getbootstrap.com/docs/4.6/getting-started/introduction/">Bootstrap
4</a> toolkit.</p>
<p>Much structural HTML functionality is actually coming from bootstrap, so you
will often be able to just add bootstrap CSS classes to elements in the HTML
file to get various effects like text-centering or similar.</p>
<p>The website’s custom CSS is found in
<codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/static/website/css/website.css</span></code> but we also look for a (currently
empty) <codeclass="docutils literal notranslate"><spanclass="pre">custom.css</span></code> in the same location. You can override either, but it may
be easier to revert your changes if you only add things to <codeclass="docutils literal notranslate"><spanclass="pre">custom.css</span></code>.</p>
<p>Copy the CSS file you want to modify to the corresponding location in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web</span></code>.
Modify it and reload the server to see your changes.</p>
<p>You can also apply static files without reloading, but running this in the
<p>(this is run automatically when reloading the server).</p>
<blockquote>
<div><p>Note that before you see new CSS files applied you may need to refresh your
browser without cache (Ctrl-F5 in Firefox, for example).</p>
</div></blockquote>
<p>As an example, add/copy <codeclass="docutils literal notranslate"><spanclass="pre">custom.css</span></code> to <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/static/website/css/</span></code> and
<p>Reload and your website now has a red theme!</p>
<blockquote>
<div><p>Hint: Learn to use your web browser’s <aclass="reference external"href="https://torquemag.io/2020/06/browser-developer-tools-tutorial/">Developer tools</a>.
These allow you to tweak CSS ‘live’ to find a look you like and copy it into
the .css file only when you want to make the changes permanent.</p>
</div></blockquote>
</section>
<sectionid="change-front-page-functionality">
<h3>Change front page functionality<aclass="headerlink"href="#change-front-page-functionality"title="Permalink to this headline">¶</a></h3>
<p>The logic is all in the view. To find where the index-page view is found, we
look in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/website/urls.py</span></code>. Here we find the following line:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in evennia/web/website/urls.py</span>
<p>The first <codeclass="docutils literal notranslate"><spanclass="pre">""</span></code> is the empty url - root - what you get if you just enter <codeclass="docutils literal notranslate"><spanclass="pre">localhost:4001/</span></code>
with no extra path. As expected, this leads to the index page. By looking at the imports
we find the view is in in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/website/views/index.py</span></code>.</p>
<p>Copy this file to the corresponding location in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web</span></code>. Then tweak your <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/website/urls.py</span></code>
file to point to the new file:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/web/website/urls.py</span>
<p>So we just import <codeclass="docutils literal notranslate"><spanclass="pre">index</span></code> from the new location and point to it. After a reload
the front page will now redirect to use your copy rather than the original.</p>
<p>The frontpage view is a class <codeclass="docutils literal notranslate"><spanclass="pre">EvenniaIndexView</span></code>. This is a <aclass="reference external"href="https://docs.djangoproject.com/en/3.2/topics/class-based-views/">Django class-based view</a>.
It’s a little less visible what happens in a class-based view than in a function (since
the class implements a lot of functionality as methods), but it’s powerful and
much easier to extend/modify.</p>
<p>The class property <codeclass="docutils literal notranslate"><spanclass="pre">template_name</span></code> sets the location of the template used under
the <codeclass="docutils literal notranslate"><spanclass="pre">templates/</span></code> folder. So <codeclass="docutils literal notranslate"><spanclass="pre">website/index.html</span></code> points to
<codeclass="docutils literal notranslate"><spanclass="pre">web/templates/website/index.html</span></code> (as we already explored above.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">get_context_data</span></code> is a convenient method for providing the context for the
template. In the index-page’s case we want the game stats (number of recent
players etc). These are then made available to use in <codeclass="docutils literal notranslate"><spanclass="pre">{{</span><spanclass="pre">...</span><spanclass="pre">}}</span></code> slots in the
template as described in the previous section.</p>
</section>
<sectionid="change-other-website-pages">
<h3>Change other website pages<aclass="headerlink"href="#change-other-website-pages"title="Permalink to this headline">¶</a></h3>
<p>The other sub pages are handled in the same way - copy the template or static
resource to the right place, or copy the view and repoint your <codeclass="docutils literal notranslate"><spanclass="pre">website/urls.py</span></code> to
your copy. Just remember to reload.</p>
</section>
</section>
<sectionid="adding-a-new-web-page">
<h2>Adding a new web page<aclass="headerlink"href="#adding-a-new-web-page"title="Permalink to this headline">¶</a></h2>
<sectionid="using-flat-pages">
<h3>Using Flat Pages<aclass="headerlink"href="#using-flat-pages"title="Permalink to this headline">¶</a></h3>
<p>The absolutely simplest way to add a new web page is to use the <codeclass="docutils literal notranslate"><spanclass="pre">Flat</span><spanclass="pre">Pages</span></code>
app available in the <aclass="reference internal"href="Web-Admin.html"><spanclass="doc std std-doc">Web Admin</span></a>. The page will appear with the same
styling as the rest of the site.</p>
<p>For the <codeclass="docutils literal notranslate"><spanclass="pre">Flat</span><spanclass="pre">pages</span></code> module to work you must first set up a <em>Site</em> (or
domain) to use. You only need to this once.</p>
<ulclass="simple">
<li><p>Go to the Web admin and select <codeclass="docutils literal notranslate"><spanclass="pre">Sites</span></code>. If your
game is at <codeclass="docutils literal notranslate"><spanclass="pre">mygreatgame.com</span></code>, that’s the domain you need to add. For local
experimentation, add the domain <codeclass="docutils literal notranslate"><spanclass="pre">localhost:4001</span></code>. Note the <codeclass="docutils literal notranslate"><spanclass="pre">id</span></code> of the domain
(look at the url when you click on the new domain, if it’s for example
<codeclass="docutils literal notranslate"><spanclass="pre">http://localhost:4001/admin/sites/site/2/change/</span></code>, then the id is <codeclass="docutils literal notranslate"><spanclass="pre">2</span></code>).</p></li>
<li><p>Now add the line <codeclass="docutils literal notranslate"><spanclass="pre">SITE_ID</span><spanclass="pre">=</span><spanclass="pre"><id></span></code> to your settings file.</p></li>
</ul>
<p>Next you create new pages easily.</p>
<ulclass="simple">
<li><p>Go the <codeclass="docutils literal notranslate"><spanclass="pre">Flat</span><spanclass="pre">Pages</span></code> web admin and choose to add a new flat page.</p></li>
<li><p>Set the url. If you want the page to appear as e.g. <codeclass="docutils literal notranslate"><spanclass="pre">localhost:4001/test/</span></code>, then
add <codeclass="docutils literal notranslate"><spanclass="pre">/test/</span></code> here. You need to add both leading and trailing slashes.</p></li>
<li><p>Set <codeclass="docutils literal notranslate"><spanclass="pre">Title</span></code> to the name of the page.</p></li>
<li><p>The <codeclass="docutils literal notranslate"><spanclass="pre">Content</span></code> is the HTML content of the body of the page. Go wild!</p></li>
<li><p>Finally pick the <codeclass="docutils literal notranslate"><spanclass="pre">Site</span></code> you made before, and save.</p></li>
<li><p>(in the advanced section you can make it so that you have to login to see the page etc).</p></li>
</ul>
<p>You can now go to <codeclass="docutils literal notranslate"><spanclass="pre">localhost:4001/test/</span></code> and see your new page!</p>
</section>
<sectionid="add-custom-new-page">
<h3>Add Custom new page<aclass="headerlink"href="#add-custom-new-page"title="Permalink to this headline">¶</a></h3>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">Flat</span><spanclass="pre">Pages</span></code> page doesn’t allow for (much) dynamic content and customization. For
this you need to add the needed components yourself.</p>
<p>Let’s see how to make a <codeclass="docutils literal notranslate"><spanclass="pre">/test/</span></code> page from scratch.</p>
<ul>
<li><p>Add a new <codeclass="docutils literal notranslate"><spanclass="pre">test.html</span></code> file under <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/templates/website/</span></code>. Easiest is to base
this off an existing file. Make sure to <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">extend</span><spanclass="pre">base.html</span><spanclass="pre">%}</span></code> if you want to
get the same styling as the rest of your site.</p></li>
<li><p>Add a new view <codeclass="docutils literal notranslate"><spanclass="pre">testview.py</span></code> under <codeclass="docutils literal notranslate"><spanclass="pre">mygame/web/website/views/</span></code> (don’t name it <codeclass="docutils literal notranslate"><spanclass="pre">test.py</span></code> or
Django/Evennia will think it contains unit tests). Add a view there to process
your page. This is a minimal view to start from (read much more <aclass="reference external"href="https://docs.djangoproject.com/en/3.2/topics/class-based-views/">in the Django docs</a>):</p>
<li><p>Reload the server and your new page is available. You can now continue to add
all sorts of advanced dynamic content through your view and template!</p></li>
</ul>
</section>
</section>
<sectionid="user-forms">
<h2>User forms<aclass="headerlink"href="#user-forms"title="Permalink to this headline">¶</a></h2>
<p>All the pages created so far deal with <em>presenting</em> information to the user.
It’s also possible for the user to <em>input</em> data on the page through <em>forms</em>. An
example would be a page of fields and sliders you fill in to create a
character, with a big ‘Submit’ button at the bottom.</p>
<p>Firstly, this must be represented in HTML. The <codeclass="docutils literal notranslate"><spanclass="pre"><form></span><spanclass="pre">...</span><spanclass="pre"></form></span></code> is a
standard HTML element you need to add to your template. It also has some other
requirements, such as <codeclass="docutils literal notranslate"><spanclass="pre"><input></span></code> and often Javascript components as well (but
usually Django will help with this). If you are unfamiliar with how HTML forms
work, <aclass="reference external"href="https://docs.djangoproject.com/en/3.2/topics/forms/#html-forms">read about them here</a>.</p>
<p>The basic gist of it is that when you click to ‘submit’ the form, a POST HTML
request will be sent to the server containing the data the user entered. It’s
now up to the server to make sure the data makes sense (validation) and then
process the input somehow (like creating a new character).</p>
<p>On the backend side, we need to specify the logic for validating and processing
the form data. This is done by the <codeclass="docutils literal notranslate"><spanclass="pre">Form</span></code><aclass="reference external"href="https://docs.djangoproject.com/en/3.2/topics/forms/#forms-in-django">Django class</a>.
This specifies <em>fields</em> on itself that define how to validate that piece of data.</p>
<p>The form is then linked into the view-class by adding <codeclass="docutils literal notranslate"><spanclass="pre">form_class</span><spanclass="pre">=</span><spanclass="pre">MyFormClass</span></code> to
the view (next to <codeclass="docutils literal notranslate"><spanclass="pre">template_name</span></code>).</p>
<p>There are several example forms in <codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/website/forms.py</span></code>. It’s also a good
idea to read <aclass="reference external"href="https://docs.djangoproject.com/en/3.2/topics/forms/#building-a-form-in-django">Building a form in Django</a>
on the Django website - it covers all you need.</p>