Updated HTML docs

This commit is contained in:
Griatch 2021-10-26 21:41:11 +02:00
parent 66d0ad0bc9
commit 7900aad365
2073 changed files with 32986 additions and 41197 deletions

View file

@ -14,6 +14,8 @@
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"processClass": "tex2jax_process|mathjax_process|math|output_area"}})</script>
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
@ -38,7 +40,7 @@
<div class="bodywrapper">
<div class="body" role="main">
<section id="new-models">
<section class="tex2jax_ignore mathjax_ignore" id="new-models">
<h1>New Models<a class="headerlink" href="#new-models" title="Permalink to this headline"></a></h1>
<p><em>Note: This is considered an advanced topic.</em></p>
<p>Evennia offers many convenient ways to store object data, such as via Attributes or Scripts. This is
@ -46,7 +48,7 @@ sufficient for most use cases. But if you aim to build a large stand-alone syste
your storage requirements into those may be more complex than you bargain for. Examples may be to
store guild data for guild members to be able to change, tracking the flow of money across a game-
wide economic system or implement other custom game systems that requires the storage of custom data
in a quickly accessible way. Whereas <a class="reference internal" href="../Components/Tags.html"><span class="doc">Tags</span></a> or <a class="reference internal" href="../Components/Scripts.html"><span class="doc">Scripts</span></a> can handle many situations,
in a quickly accessible way. Whereas <a class="reference internal" href="../Components/Tags.html"><span class="doc std std-doc">Tags</span></a> or <a class="reference internal" href="../Components/Scripts.html"><span class="doc std std-doc">Scripts</span></a> can handle many situations,
sometimes things may be easier to handle by adding your own database model.</p>
<section id="overview-of-database-tables">
<h2>Overview of database tables<a class="headerlink" href="#overview-of-database-tables" title="Permalink to this headline"></a></h2>
@ -61,21 +63,21 @@ retrieving text stored in tables. A table may look like this</p>
<p>Each line is considerably longer in your database. Each column is referred to as a “field” and every
row is a separate object. You can check this out for yourself. If you use the default sqlite3
database, go to your game folder and run</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">evennia</span> <span class="n">dbshell</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia dbshell
</pre></div>
</div>
<p>You will drop into the database shell. While there, try:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">sqlite</span><span class="o">&gt;</span> <span class="o">.</span><span class="n">help</span> <span class="c1"># view help</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> sqlite&gt; .help # view help
<span class="n">sqlite</span><span class="o">&gt;</span> <span class="o">.</span><span class="n">tables</span> <span class="c1"># view all tables</span>
sqlite&gt; .tables # view all tables
<span class="c1"># show the table field names for objects_objectdb</span>
<span class="n">sqlite</span><span class="o">&gt;</span> <span class="o">.</span><span class="n">schema</span> <span class="n">objects_objectdb</span>
# show the table field names for objects_objectdb
sqlite&gt; .schema objects_objectdb
<span class="c1"># show the first row from the objects_objectdb table</span>
<span class="n">sqlite</span><span class="o">&gt;</span> <span class="n">select</span> <span class="o">*</span> <span class="kn">from</span> <span class="nn">objects_objectdb</span> <span class="n">limit</span> <span class="mi">1</span><span class="p">;</span>
# show the first row from the objects_objectdb table
sqlite&gt; select * from objects_objectdb limit 1;
<span class="n">sqlite</span><span class="o">&gt;</span> <span class="o">.</span><span class="n">exit</span>
sqlite&gt; .exit
</pre></div>
</div>
<p>Evennia uses <a class="reference external" href="https://docs.djangoproject.com">Django</a>, which abstracts away the database SQL
@ -92,8 +94,8 @@ extend and build on.</p>
For this example well call it “myapp”. Run the following (you need to have a working Evennia
running before you do this, so make sure you have run the steps in [Setup Quickstart](Getting-
Started) first):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">cd</span> <span class="n">mygame</span><span class="o">/</span><span class="n">world</span>
<span class="n">evennia</span> <span class="n">startapp</span> <span class="n">myapp</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> cd mygame/world
evennia startapp myapp
</pre></div>
</div>
</li>
@ -112,14 +114,14 @@ you put <code class="docutils literal notranslate"><span class="pre">myapp</span
</div>
</li>
<li><p>From <code class="docutils literal notranslate"><span class="pre">mygame/</span></code>, run</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">evennia</span> <span class="n">makemigrations</span> <span class="n">myapp</span>
<span class="n">evennia</span> <span class="n">migrate</span>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia makemigrations myapp
evennia migrate
</pre></div>
</div>
</li>
</ol>
<p>This will add your new database table to the database. If you have put your game under version
control (if not, <a class="reference internal" href="../Coding/Version-Control.html"><span class="doc">you should</span></a>), dont forget to <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">add</span> <span class="pre">myapp/*</span></code> to add all items
control (if not, <a class="reference internal" href="../Coding/Version-Control.html"><span class="doc std std-doc">you should</span></a>), dont forget to <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">add</span> <span class="pre">myapp/*</span></code> to add all items
to version control.</p>
</section>
<section id="defining-your-models">
@ -131,17 +133,7 @@ database.</p>
<p>We wont describe all aspects of Django models here, for that we refer to the vast <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/db/models/">Django
documentation</a> on the subject. Here is a
(very) brief example:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="k">class</span> <span class="nc">MyDataStore</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
<span class="s2">&quot;A simple model for storing some data&quot;</span>
@ -153,12 +145,12 @@ documentation</a> on the subject. Here is a
<span class="n">db_date_created</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateTimeField</span><span class="p">(</span><span class="s1">&#39;date created&#39;</span><span class="p">,</span> <span class="n">editable</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">auto_now_add</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">db_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>We create four fields: two character fields of limited length and one text field which has no
maximum length. Finally we create a field containing the current time of us creating this object.</p>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">db_date_created</span></code> field, with exactly this name, is <em>required</em> if you want to be able to store
instances of your custom model in an Evennia <a class="reference internal" href="../Components/Attributes.html"><span class="doc">Attribute</span></a>. It will automatically be set
instances of your custom model in an Evennia <a class="reference internal" href="../Components/Attributes.html"><span class="doc std std-doc">Attribute</span></a>. It will automatically be set
upon creation and can after that not be changed. Having this field will allow you to do e.g.
<code class="docutils literal notranslate"><span class="pre">obj.db.myinstance</span> <span class="pre">=</span> <span class="pre">mydatastore</span></code>. If you know youll never store your model instances in Attributes
the <code class="docutils literal notranslate"><span class="pre">db_date_created</span></code> field is optional.</p>
@ -180,31 +172,25 @@ point for your models.</p>
<section id="creating-a-new-model-instance">
<h2>Creating a new model instance<a class="headerlink" href="#creating-a-new-model-instance" title="Permalink to this headline"></a></h2>
<p>To create a new row in your table, you instantiate the model and then call its <code class="docutils literal notranslate"><span class="pre">save()</span></code> method:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia.myapp</span> <span class="kn">import</span> <span class="n">MyDataStore</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia.myapp</span> <span class="kn">import</span> <span class="n">MyDataStore</span>
<span class="n">new_datastore</span> <span class="o">=</span> <span class="n">MyDataStore</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;LargeSword&quot;</span><span class="p">,</span>
<span class="n">db_category</span><span class="o">=</span><span class="s2">&quot;weapons&quot;</span><span class="p">,</span>
<span class="n">db_text</span><span class="o">=</span><span class="s2">&quot;This is a huge weapon!&quot;</span><span class="p">)</span>
<span class="c1"># this is required to actually create the row in the database!</span>
<span class="n">new_datastore</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Note that the <code class="docutils literal notranslate"><span class="pre">db_date_created</span></code> field of the model is not specified. Its flag <code class="docutils literal notranslate"><span class="pre">at_now_add=True</span></code>
makes sure to set it to the current date when the object is created (it can also not be changed
further after creation).</p>
<p>When you update an existing object with some new field value, remember that you have to save the
object afterwards, otherwise the database will not update:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">my_datastore</span><span class="o">.</span><span class="n">db_key</span> <span class="o">=</span> <span class="s2">&quot;Larger Sword&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">my_datastore</span><span class="o">.</span><span class="n">db_key</span> <span class="o">=</span> <span class="s2">&quot;Larger Sword&quot;</span>
<span class="n">my_datastore</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</td></tr></table></div>
</div>
<p>Evennias normal models dont need to explicitly save, since they are based on <code class="docutils literal notranslate"><span class="pre">SharedMemoryModel</span></code>
rather than the raw django model. This is covered in the next section.</p>
</section>
@ -221,26 +207,24 @@ will automatically create field wrappers for them. This happens in the models
<a class="reference external" href="http://en.wikibooks.org/wiki/Python_Programming/Metaclasses">Metaclass</a> so there is no speed
penalty for this. The name of the wrapper will be the same name as the field, minus the <code class="docutils literal notranslate"><span class="pre">db_</span></code>
prefix. So the <code class="docutils literal notranslate"><span class="pre">db_key</span></code> field will have a wrapper property named <code class="docutils literal notranslate"><span class="pre">key</span></code>. You can then do:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">my_datastore</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;Larger Sword&quot;</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">my_datastore</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;Larger Sword&quot;</span>
</pre></div>
</td></tr></table></div>
</div>
<p>and dont have to explicitly call <code class="docutils literal notranslate"><span class="pre">save()</span></code> afterwards. The saving also happens in a more efficient
way under the hood, updating only the field rather than the entire model using django optimizations.
Note that if you were to manually add the property or method <code class="docutils literal notranslate"><span class="pre">key</span></code> to your model, this will be used
instead of the automatic wrapper and allows you to fully customize access as needed.</p>
<p>To explain the second and more important point, consider the following example using the default
Django model parent:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">shield</span> <span class="o">=</span> <span class="n">MyDataStore</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;SmallShield&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">shield</span> <span class="o">=</span> <span class="n">MyDataStore</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;SmallShield&quot;</span><span class="p">)</span>
<span class="n">shield</span><span class="o">.</span><span class="n">cracked</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># where cracked is not a database field</span>
</pre></div>
</td></tr></table></div>
</div>
<p>And then later:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="n">shield</span> <span class="o">=</span> <span class="n">MyDataStore</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;SmallShield&quot;</span><span class="p">)</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">shield</span> <span class="o">=</span> <span class="n">MyDataStore</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;SmallShield&quot;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">shield</span><span class="o">.</span><span class="n">cracked</span><span class="p">)</span> <span class="c1"># error!</span>
</pre></div>
</td></tr></table></div>
</div>
<p>The outcome of that last print statement is <em>undefined</em>! It could <em>maybe</em> randomly work but most
likely you will get an <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code> for not finding the <code class="docutils literal notranslate"><span class="pre">cracked</span></code> property. The reason is that
<code class="docutils literal notranslate"><span class="pre">cracked</span></code> doesnt represent an actual field in the database. It was just added at run-time and thus
@ -262,16 +246,7 @@ idmapper.</p>
<p>To use the idmapper and the field-wrapper functionality you just have to have your model classes
inherit from <code class="docutils literal notranslate"><span class="pre">evennia.utils.idmapper.models.SharedMemoryModel</span></code> instead of from the default
<code class="docutils literal notranslate"><span class="pre">django.db.models.Model</span></code>:</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.idmapper.models</span> <span class="kn">import</span> <span class="n">SharedMemoryModel</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia.utils.idmapper.models</span> <span class="kn">import</span> <span class="n">SharedMemoryModel</span>
<span class="k">class</span> <span class="nc">MyDataStore</span><span class="p">(</span><span class="n">SharedMemoryModel</span><span class="p">):</span>
<span class="c1"># the rest is the same as before, but db_* is important; these will</span>
@ -282,24 +257,14 @@ inherit from <code class="docutils literal notranslate"><span class="pre">evenni
<span class="n">db_date_created</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateTimeField</span><span class="p">(</span><span class="s1">&#39;date created&#39;</span><span class="p">,</span> <span class="n">editable</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">auto_now_add</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">db_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
</section>
<section id="searching-for-your-models">
<h2>Searching for your models<a class="headerlink" href="#searching-for-your-models" title="Permalink to this headline"></a></h2>
<p>To search your new custom database table you need to use its database <em>manager</em> to build a <em>query</em>.
Note that even if you use <code class="docutils literal notranslate"><span class="pre">SharedMemoryModel</span></code> as described in the previous section, you have to use
the actual <em>field names</em> in the query, not the wrapper name (so <code class="docutils literal notranslate"><span class="pre">db_key</span></code> and not just <code class="docutils literal notranslate"><span class="pre">key</span></code>).</p>
<div class="highlight-python notranslate"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">world.myapp</span> <span class="kn">import</span> <span class="n">MyDataStore</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">world.myapp</span> <span class="kn">import</span> <span class="n">MyDataStore</span>
<span class="c1"># get all datastore objects exactly matching a given key</span>
<span class="n">matches</span> <span class="o">=</span> <span class="n">MyDataStore</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">db_key</span><span class="o">=</span><span class="s2">&quot;Larger Sword&quot;</span><span class="p">)</span>
@ -311,7 +276,7 @@ the actual <em>field names</em> in the query, not the wrapper name (so <code cla
<span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">matches2</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">match</span><span class="o">.</span><span class="n">db_text</span><span class="p">)</span>
</pre></div>
</td></tr></table></div>
</div>
<p>See the <a class="reference external" href="https://docs.djangoproject.com/en/2.2/topics/db/queries/">Django query documentation</a> for a
lot more information about querying the database.</p>
</section>
@ -370,7 +335,7 @@ lot more information about querying the database.</p>
<h3>Versions</h3>
<ul>
<li><a href="New-Models.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
<li><a href="../../0.95/index.html">0.95 (v0.9.5 branch)</a></li>
</ul>
</div>