<h1>Web Character View Tutorial<aclass="headerlink"href="#web-character-view-tutorial"title="Permalink to this headline">¶</a></h1>
<p><strong>Before doing this tutorial you will probably want to read the intro in <aclass="reference internal"href="Web-Changing-Webpage.html"><spanclass="doc std std-doc">Changing The Web Page tutorial</span></a>.</strong></p>
<p>In this tutorial we will create a web page that displays the stats of a game character. For this, and all other pages we want to make specific to our game, we’ll need to create our own Django “app”. We’ll call our app <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code>, since it will be dealing with character information. From your game dir, run</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>evennia startapp character
</pre></div>
</div>
<p>This will create a new directory named <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code> inside <codeclass="docutils literal notranslate"><spanclass="pre">mygame</span></code>. To keep
things tidy, let’s move it into the <codeclass="docutils literal notranslate"><spanclass="pre">web/</span></code> subdirectory.</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>mv character web (linux/mac)
move character web (windows)
</pre></div>
</div>
<p>We put it in <codeclass="docutils literal notranslate"><spanclass="pre">web/</span></code> to keep things tidy, but you could place it wherever you
like. It contains all basic files that a Django app needs.</p>
<p>Note that we will not edit all files in this new directory, many of the generated files are outside the scope of this tutorial.</p>
<p>In order for Django to find our new web app, we’ll need to add it to the <codeclass="docutils literal notranslate"><spanclass="pre">INSTALLED_APPS</span></code> setting. Evennia’s default installed apps are already set, so in <codeclass="docutils literal notranslate"><spanclass="pre">server/conf/settings.py</span></code>, we’ll just extend them:</p>
<div><p>Note: That end comma is important. It makes sure that Python interprets the addition as a tuple instead of a string.</p>
</div></blockquote>
<p>The first thing we need to do is to create a <em>view</em> and an <em>URL pattern</em> to point to it. A view is a
function that generates the web page that a visitor wants to see, while the URL pattern lets Django know what URL should trigger the view. The pattern may also provide some information of its own as we shall see.</p>
<p>Here is our <codeclass="docutils literal notranslate"><spanclass="pre">character/urls.py</span></code> file (<strong>Note</strong>: you may have to create this file if a blank one
wasn’t generated for you):</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># URL patterns for the character app</span>
<p>This file contains all of the URL patterns for the application. The <codeclass="docutils literal notranslate"><spanclass="pre">url</span></code> function in the
<codeclass="docutils literal notranslate"><spanclass="pre">urlpatterns</span></code> list are given three arguments. The first argument is a pattern-string used to
identify which URLs are valid. Patterns are specified as <em>regular expressions</em>. Regular expressions are used to match strings and are written in a special, very compact, syntax. A detailed description of regular expressions is beyond this tutorial but you can learn more about them <aclass="reference external"href="https://docs.python.org/2/howto/regex.html">here</a>. For now, just accept that this regular expression requires that the visitor’s URL looks something like this:</p>
<p>That is, <codeclass="docutils literal notranslate"><spanclass="pre">sheet/</span></code> followed by a number, rather than some other possible URL pattern. We will interpret this number as object ID. Thanks to how the regular expression is formulated, the pattern recognizer stores the number in a variable called <codeclass="docutils literal notranslate"><spanclass="pre">object_id</span></code>. This will be passed to the view (see below). We add the imported view function (<codeclass="docutils literal notranslate"><spanclass="pre">sheet</span></code>) in the second argument. We also add the <codeclass="docutils literal notranslate"><spanclass="pre">name</span></code> keyword to identify the URL pattern itself. You should always name your URL patterns, this makes them easy to refer to in html templates using the <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">url</span><spanclass="pre">%}</span></code> tag (but we won’t get more into that in this tutorial).</p>
<blockquote>
<div><p>Security Note: Normally, users do not have the ability to see object IDs within the game (it’s restricted to superusers only). Exposing the game’s object IDs to the public like this enables griefers to perform what is known as an <aclass="reference external"href="http://www.sans.edu/research/security-laboratory/article/attacks-browsing">account enumeration attack</a> in the efforts of hijacking your superuser account. Consider this: in every Evennia installation, there are two objects that we can <em>always</em> expect to exist and have the same object IDs– Limbo (#2) and the superuser you create in the beginning (#1). Thus, the griefer can get 50% of the information they need to hijack the admin account (the admin’s username) just by navigating to <codeclass="docutils literal notranslate"><spanclass="pre">sheet/1</span></code>!</p>
</div></blockquote>
<p>Next we create <codeclass="docutils literal notranslate"><spanclass="pre">views.py</span></code>, the view file that <codeclass="docutils literal notranslate"><spanclass="pre">urls.py</span></code> refers to.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># Views for our character app</span>
<spanclass="k">raise</span><spanclass="n">Http404</span><spanclass="p">(</span><spanclass="s2">"I couldn't find a character with that ID."</span><spanclass="p">)</span>
<spanclass="k">raise</span><spanclass="n">Http404</span><spanclass="p">(</span><spanclass="s2">"I couldn't find a character with that ID. "</span>
<p>As explained earlier, the URL pattern parser in <codeclass="docutils literal notranslate"><spanclass="pre">urls.py</span></code> parses the URL and passes <codeclass="docutils literal notranslate"><spanclass="pre">object_id</span></code> to our view function <codeclass="docutils literal notranslate"><spanclass="pre">sheet</span></code>. We do a database search for the object using this number. We also make sure such an object exists and that it is actually a Character. The view function is also handed a <codeclass="docutils literal notranslate"><spanclass="pre">request</span></code> object. This gives us information about the request, such as if a logged-in user viewed it - we won’t use that information here but it is good to keep in mind.</p>
<p>On the last line, we call the <codeclass="docutils literal notranslate"><spanclass="pre">render</span></code> function. Apart from the <codeclass="docutils literal notranslate"><spanclass="pre">request</span></code> object, the <codeclass="docutils literal notranslate"><spanclass="pre">render</span></code>
function takes a path to an html template and a dictionary with extra data you want to pass into said template. As extra data we pass the Character object we just found. In the template it will be available as the variable “character”.</p>
<p>The html template is created as <codeclass="docutils literal notranslate"><spanclass="pre">templates/character/sheet.html</span></code> under your <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code> app folder. You may have to manually create both <codeclass="docutils literal notranslate"><spanclass="pre">template</span></code> and its subfolder <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code>. Here’s the template to create:</p>
<spanclass="p"><</span><spanclass="nt">li</span><spanclass="p">></span>This character has no skills yet.<spanclass="p"></</span><spanclass="nt">li</span><spanclass="p">></span>
<spanclass="p"><</span><spanclass="nt">p</span><spanclass="na">class</span><spanclass="o">=</span><spanclass="s">"success"</span><spanclass="p">></span>This character has been approved!<spanclass="p"></</span><spanclass="nt">p</span><spanclass="p">></span>
{% else %}
<spanclass="p"><</span><spanclass="nt">p</span><spanclass="na">class</span><spanclass="o">=</span><spanclass="s">"warning"</span><spanclass="p">></span>This character has not yet been approved!<spanclass="p"></</span><spanclass="nt">p</span><spanclass="p">></span>
{% endif %}
{% endblock %}
</pre></div>
</div>
<p>In Django templates, <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">...</span><spanclass="pre">%}</span></code> denotes special in-template “functions” that Django understands. The <codeclass="docutils literal notranslate"><spanclass="pre">{{</span><spanclass="pre">...</span><spanclass="pre">}}</span></code> blocks work as “slots”. They are replaced with whatever value the code inside the block returns.</p>
<p>The first line, <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">extends</span><spanclass="pre">"base.html"</span><spanclass="pre">%}</span></code>, tells Django that this template extends the base template that Evennia is using. The base template is provided by the theme. Evennia comes with the open-source third-party theme <codeclass="docutils literal notranslate"><spanclass="pre">prosimii</span></code>. You can find it and its <codeclass="docutils literal notranslate"><spanclass="pre">base.html</span></code> in
<codeclass="docutils literal notranslate"><spanclass="pre">evennia/web/templates/prosimii</span></code>. Like other templates, these can be overwritten.</p>
<p>The next line is <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">block</span><spanclass="pre">content</span><spanclass="pre">%}</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">base.html</span></code> file has <codeclass="docutils literal notranslate"><spanclass="pre">block</span></code>s, which are placeholders
that templates can extend. The main block, and the one we use, is named <codeclass="docutils literal notranslate"><spanclass="pre">content</span></code>.</p>
<p>We can access the <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code> variable anywhere in the template because we passed it in the <codeclass="docutils literal notranslate"><spanclass="pre">render</span></code> call at the end of <codeclass="docutils literal notranslate"><spanclass="pre">view.py</span></code>. That means we also have access to the Character’s <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> attributes, much like you would in normal Python code. You don’t have the ability to call functions with arguments in the template– in fact, if you need to do any complicated logic, you should do it in <codeclass="docutils literal notranslate"><spanclass="pre">view.py</span></code> and pass the results as more variables to the template. But you still have a great deal of flexibility in how you display the data.</p>
<p>We can do a little bit of logic here as well. We use the <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">for</span><spanclass="pre">%}</span><spanclass="pre">...</span><spanclass="pre">{%</span><spanclass="pre">endfor</span><spanclass="pre">%}</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">{%</span><spanclass="pre">if</span><spanclass="pre">%}</span><spanclass="pre">...</span><spanclass="pre">{%</span><spanclass="pre">else</span><spanclass="pre">%}</span><spanclass="pre">...</span><spanclass="pre">{%</span><spanclass="pre">endif</span><spanclass="pre">%}</span></code> structures to change how the template renders depending on how many skills the user has, or if the user is approved (assuming your game has an approval system).</p>
<p>The last file we need to edit is the master URLs file. This is needed in order to smoothly integrate the URLs from your new <codeclass="docutils literal notranslate"><spanclass="pre">character</span></code> app with the URLs from Evennia’s existing pages. Find the file <codeclass="docutils literal notranslate"><spanclass="pre">web/website/urls.py</span></code> and update its <codeclass="docutils literal notranslate"><spanclass="pre">patterns</span></code> list as follows:</p>
<p>Now reload the server with <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span><spanclass="pre">reload</span></code> and visit the page in your browser. If you haven’t
changed your defaults, you should be able to find the sheet for character <codeclass="docutils literal notranslate"><spanclass="pre">#1</span></code> at
<p>Doing so will give you a ‘view on site’ button in the top right of the Django Admin Objects
changepage that links to your new character sheet, and allow you to get the link to a character’s page by using <codeclass="docutils literal notranslate"><spanclass="pre">{{</span><spanclass="pre">object.get_absolute_url</span><spanclass="pre">}}</span></code> in any template where you have a given object.</p>
<p><em>Now that you’ve made a basic page and app with Django, you may want to read the full Django tutorial to get a better idea of what it can do. <aclass="reference external"href="https://docs.djangoproject.com/en/4.1/intro/tutorial01/">You can find Django’s tutorial