<p>The first thing to consider is the base type of the thing you are searching for. Evennia organizes
its database into a few main tables: <aclass="reference internal"href="Objects.html"><spanclass="doc">Objects</span></a>, <aclass="reference internal"href="Accounts.html"><spanclass="doc">Accounts</span></a>, <aclass="reference internal"href="Scripts.html"><spanclass="doc">Scripts</span></a>,
<aclass="reference external"href="Communications.html#channels">Channels</a>, <aclass="reference external"href="Communication#Msg">Messages</a> and <aclass="reference internal"href="Help-System.html"><spanclass="doc">Help Entries</span></a>.
Most of the time you’ll likely spend your time searching for Objects and the occasional Accounts.</p>
<li><p>The <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is the name of the entity. While you can get this from <codeclass="docutils literal notranslate"><spanclass="pre">obj.key</span></code> the <em>database field</em>
is actually named <codeclass="docutils literal notranslate"><spanclass="pre">obj.db_key</span></code> - this is useful to know only when you do <aclass="reference external"href="Tutorial-Searching-For-Objects.html#queries-in-django">direct database
queries</a>. The one exception is <codeclass="docutils literal notranslate"><spanclass="pre">Accounts</span></code>, where
the database field for <codeclass="docutils literal notranslate"><spanclass="pre">.key</span></code> is instead named <codeclass="docutils literal notranslate"><spanclass="pre">username</span></code> (this is a Django requirement). When you
don’t specify search-type, you’ll usually search based on key. <em>Aliases</em> are extra names given to
Objects using something like <codeclass="docutils literal notranslate"><spanclass="pre">@alias</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">obj.aliases.add('name')</span></code>. The main search functions (see
below) will automatically search for aliases whenever you search by-key.</p></li>
<li><p><aclass="reference internal"href="Tags.html"><spanclass="doc">Tags</span></a> are the main way to group and identify objects in Evennia. Tags can most often be
used (sometimes together with keys) to uniquely identify an object. For example, even though you
have two locations with the same name, you can separate them by their tagging (this is how Evennia
implements ‘zones’ seen in other systems). Tags can also have categories, to further organize your
data for quick lookups.</p></li>
<li><p>An object’s <aclass="reference internal"href="Attributes.html"><spanclass="doc">Attributes</span></a> can also used to find an object. This can be very useful but
since Attributes can store almost any data they are far less optimized to search for than Tags or
keys.</p></li>
<li><p>The object’s <aclass="reference internal"href="Typeclasses.html"><spanclass="doc">Typeclass</span></a> indicate the sub-type of entity. A Character, Flower or
Sword are all types of Objects. A Bot is a kind of Account. The database field is called
<codeclass="docutils literal notranslate"><spanclass="pre">typeclass_path</span></code> and holds the full Python-path to the class. You can usually specify the
<codeclass="docutils literal notranslate"><spanclass="pre">typeclass</span></code> as an argument to Evennia’s search functions as well as use the class directly to limit
queries.</p></li>
<li><p>The <codeclass="docutils literal notranslate"><spanclass="pre">location</span></code> is only relevant for <aclass="reference internal"href="Objects.html"><spanclass="doc">Objects</span></a> but is a very common way to weed down the
number of candidates before starting to search. The reason is that most in-game commands tend to
operate on things nearby (in the same room) so the choices can be limited from the start.</p></li>
<li><p>The database id or the ‘#dbref’ is unique (and never re-used) within each database table. So while
there is one and only one Object with dbref <codeclass="docutils literal notranslate"><spanclass="pre">#42</span></code> there could also be an Account or Script with the
dbref <codeclass="docutils literal notranslate"><spanclass="pre">#42</span></code> at the same time. In almost all search methods you can replace the “key” search
criterion with <codeclass="docutils literal notranslate"><spanclass="pre">"#dbref"</span></code> to search for that id. This can occasionally be practical and may be what
you are used to from other code bases. But it is considered <em>bad practice</em> in Evennia to rely on
hard-coded #dbrefs to do your searches. It makes your code tied to the exact layout of the database.
It’s also not very maintainable to have to remember abstract numbers. Passing the actual objects
around and searching by Tags and/or keys will usually get you what you need.</p></li>
<p>All in-game <aclass="reference internal"href="Objects.html"><spanclass="doc">Objects</span></a> have a <codeclass="docutils literal notranslate"><spanclass="pre">.contents</span></code> property that returns all objects ‘inside’ them
(that is, all objects which has its <codeclass="docutils literal notranslate"><spanclass="pre">.location</span></code> property set to that object. This is a simple way to
get everything in a room and is also faster since this lookup is cached and won’t hit the database.</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">roomobj.contents</span></code> returns a list of all objects inside <codeclass="docutils literal notranslate"><spanclass="pre">roomobj</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">obj.contents</span></code> same as for a room, except this usually represents the object’s inventory</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">roomobj.exits</span></code> returns all exits starting from <codeclass="docutils literal notranslate"><spanclass="pre">roomobj</span></code> (Exits are here defined as Objects with
their <codeclass="docutils literal notranslate"><spanclass="pre">destination</span></code> field set).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">obj.location.contents_get(exclude=obj)</span></code> - this helper method returns all objects in <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>’s
<h2>Searching using <codeclass="docutils literal notranslate"><spanclass="pre">Object.search</span></code><aclass="headerlink"href="#searching-using-object-search"title="Permalink to this headline">¶</a></h2>
<p>Say you have a <aclass="reference internal"href="Commands.html"><spanclass="doc">command</span></a>, and you want it to do something to a target. You might be
wondering how you retrieve that target in code, and that’s where Evennia’s search utilities come in.
In the most common case, you’ll often use the <codeclass="docutils literal notranslate"><spanclass="pre">search</span></code> method of the <codeclass="docutils literal notranslate"><spanclass="pre">Object</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">Account</span></code>
typeclasses. In a command, the <codeclass="docutils literal notranslate"><spanclass="pre">.caller</span></code> property will refer back to the object using the command
(usually a <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>, which is a type of <codeclass="docutils literal notranslate"><spanclass="pre">Object</span></code>) while <codeclass="docutils literal notranslate"><spanclass="pre">.args</span></code> will contain Command’s arguments:</p>
<p>By default, the search method of a Character will attempt to find a unique object match for the
string sent to it (<codeclass="docutils literal notranslate"><spanclass="pre">self.args</span></code>, in this case, which is the arguments passed to the command by the
player) in the surroundings of the Character - the room or their inventory. If there is no match
found, the return value (which is assigned to <codeclass="docutils literal notranslate"><spanclass="pre">target</span></code>) will be <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, and an appropriate failure
message will be sent to the Character. If there’s not a unique match, <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> will again be returned,
and a different error message will be sent asking them to disambiguate the multi-match. By default,
the user can then pick out a specific match using with a number and dash preceding the name of the
object: <codeclass="docutils literal notranslate"><spanclass="pre">character.search("2-pink</span><spanclass="pre">unicorn")</span></code> will try to find the second pink unicorn in the room.</p>
<p>The search method has many <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia.objects.objects#defaultcharactersearch">arguments</a> that
allow you to refine the search, such as by designating the location to search in or only matching
<h2>Searching using <codeclass="docutils literal notranslate"><spanclass="pre">utils.search</span></code><aclass="headerlink"href="#searching-using-utils-search"title="Permalink to this headline">¶</a></h2>
<p>Sometimes you will want to find something that isn’t tied to the search methods of a character or
account. In these cases, Evennia provides a <aclass="reference external"href="https://github.com/evennia/evennia/blob/master/evennia.utils.search">utility module with a number of search
functions</a>. For example, suppose you want a command that will find and
display all the rooms that are tagged as a ‘hangout’, for people to gather by. Here’s a simple
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="n">f</span><spanclass="s2">"Hangouts available: {', '.join(str(ob) for ob in hangouts)}"</span><spanclass="p">)</span>
<p>This uses the <codeclass="docutils literal notranslate"><spanclass="pre">search_tag</span></code> function to find all objects previously tagged with <aclass="reference internal"href="Tags.html"><spanclass="doc">Tags</span></a>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_tag</span></code> - find Objects with a given Tag. <aclass="reference external"href="Tags.html#searching-for-objects-with-a-given-tag">See also here for how to search by
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_account_tag</span></code> - find Accounts with a given Tag.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_script_tag</span></code> - find Scripts with a given Tag.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_channel_tag</span></code> - find Channels with a given Tag.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_object_attribute</span></code> - find Objects with a given Attribute.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_account_attribute</span></code> - find Accounts with a given Attribute.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">search_attribute_object</span></code> - this returns the actual Attribute, not the object it sits on.</p></li>
<div><p>Note: All search functions return a Django <codeclass="docutils literal notranslate"><spanclass="pre">queryset</span></code> which is technically a list-like
representation of the database-query it’s about to do. Only when you convert it to a real list, loop
over it or try to slice or access any of its contents will the datbase-lookup happen. This means you
could yourself customize the query further if you know what you are doing (see the next section).</p>
<p>Evennia’s search methods should be sufficient for the vast majority of situations. But eventually
you might find yourself trying to figure out how to get searches for unusual circumstances: Maybe
you want to find all characters who are <em>not</em> in rooms tagged as hangouts <em>and</em> have the lycanthrope
tag <em>and</em> whose names start with a vowel, but <em>not</em> with ‘Ab’, and <em>only if</em> they have 3 or more
objects in their inventory … You could in principle use one of the earlier search methods to find
all candidates and then loop over them with a lot of if statements in raw Python. But you can do
this much more efficiently by querying the database directly.</p>
<p>Enter <aclass="reference external"href="https://docs.djangoproject.com/en/1.11/ref/models/querysets/">django’s querysets</a>. A QuerySet
is the representation of a database query and can be modified as desired. Only once one tries to
retrieve the data of that query is it <em>evaluated</em> and does an actual database request. This is
useful because it means you can modify a query as much as you want (even pass it around) and only
hit the database once you are happy with it.
Evennia’s search functions are themselves an even higher level wrapper around Django’s queries, and
many search methods return querysets. That means that you could get the result from a search
function and modify the resulting query to your own ends to further tweak what you search for.</p>
<p>Evaluated querysets can either contain objects such as Character objects, or lists of values derived
from the objects. Queries usually use the ‘manager’ object of a class, which by convention is the
<codeclass="docutils literal notranslate"><spanclass="pre">.objects</span></code> attribute of a class. For example, a query of Accounts that contain the letter ‘a’ could
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">filter</span></code> method of a manager takes arguments that allow you to define the query, and you can
continue to refine the query by calling additional methods until you evaluate the queryset, causing
the query to be executed and return a result. For example, if you have the result above, you could,
without causing the queryset to be evaluated yet, get rid of matches that contain the letter ‘e by
<div><p>You could also have chained <codeclass="docutils literal notranslate"><spanclass="pre">.exclude</span></code> directly to the end of the previous line.</p>
</div></blockquote>
<p>Once you try to access the result, the queryset will be evaluated automatically under the hood:</p>
8</pre></div></td><tdclass="code"><divclass="highlight"><pre><span></span><spanclass="n">accounts</span><spanclass="o">=</span><spanclass="nb">list</span><spanclass="p">(</span><spanclass="n">queryset</span><spanclass="p">)</span><spanclass="c1"># this fills list with matches</span>
<spanclass="c1"># do something with account</span>
<spanclass="n">accounts</span><spanclass="o">=</span><spanclass="n">queryset</span><spanclass="p">[:</span><spanclass="mi">4</span><spanclass="p">]</span><spanclass="c1"># get first four matches</span>
<spanclass="n">account</span><spanclass="o">=</span><spanclass="n">queryset</span><spanclass="p">[</span><spanclass="mi">0</span><spanclass="p">]</span><spanclass="c1"># get first match</span>
<spanclass="c1"># etc</span>
</pre></div>
</td></tr></table></div>
<divclass="section"id="limiting-by-typeclass">
<h3>Limiting by typeclass<aclass="headerlink"href="#limiting-by-typeclass"title="Permalink to this headline">¶</a></h3>
<p>Although <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>s, <codeclass="docutils literal notranslate"><spanclass="pre">Exit</span></code>s, <codeclass="docutils literal notranslate"><spanclass="pre">Room</span></code>s, and other children of <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> all shares the same
underlying database table, Evennia provides a shortcut to do more specific queries only for those
typeclasses. For example, to find only <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code>s whose names start with ‘A’, you might do:</p>
<p>If Character has a subclass <codeclass="docutils literal notranslate"><spanclass="pre">Npc</span></code> and you wanted to find only Npc’s you’d instead do</p>
<p>If you wanted to search both Characters and all its subclasses (like Npc) you use the <codeclass="docutils literal notranslate"><spanclass="pre">*_family</span></code>
<p>The higher up in the inheritance hierarchy you go the more objects will be included in these
searches. There is one special case, if you really want to include <em>everything</em> from a given
database table. You do that by searching on the database model itself. These are named <codeclass="docutils literal notranslate"><spanclass="pre">ObjectDB</span></code>,
<p>Here are the most commonly used methods to use with the <codeclass="docutils literal notranslate"><spanclass="pre">objects</span></code> managers:</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">filter</span></code> - query for a listing of objects based on search criteria. Gives empty queryset if none
were found.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">get</span></code> - query for a single match - raises exception if none were found, or more than one was
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">all</span></code> - get all instances of the particular type.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">filter_family</span></code> - like <codeclass="docutils literal notranslate"><spanclass="pre">filter</span></code>, but search all sub classes as well.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">get_family</span></code> - like <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code>, but search all sub classes as well.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">all_family</span></code> - like <codeclass="docutils literal notranslate"><spanclass="pre">all</span></code>, but return entities of all subclasses as well.</p></li>
</ul>
</div>
</div>
<divclass="section"id="multiple-conditions">
<h2>Multiple conditions<aclass="headerlink"href="#multiple-conditions"title="Permalink to this headline">¶</a></h2>
<p>If you pass more than one keyword argument to a query method, the query becomes an <codeclass="docutils literal notranslate"><spanclass="pre">AND</span></code>
relationship. For example, if we want to find characters whose names start with “A” <em>and</em> are also
werewolves (have the <codeclass="docutils literal notranslate"><spanclass="pre">lycanthrope</span></code> tag), we might do:</p>
<p>To exclude lycanthropes currently in rooms tagged as hangouts, we might tack on an <codeclass="docutils literal notranslate"><spanclass="pre">.exclude</span></code> as
<p>Note the syntax of the keywords in building the queryset. For example, <codeclass="docutils literal notranslate"><spanclass="pre">db_location</span></code> is the name of
the database field sitting on (in this case) the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> (Object). Double underscore <codeclass="docutils literal notranslate"><spanclass="pre">__</span></code> works
like dot-notation in normal Python (it’s used since dots are not allowed in keyword names). So the
instruction <codeclass="docutils literal notranslate"><spanclass="pre">db_location__db_tags__db_key="hangout"</span></code> should be read as such:</p>
<li><p>“On the <codeclass="docutils literal notranslate"><spanclass="pre">Character</span></code> object … (this comes from us building this queryset using the
<li><p>… get the value of the <codeclass="docutils literal notranslate"><spanclass="pre">db_location</span></code> field … (this references a Room object, normally)</p></li>
<li><p>… on that location, get the value of the <codeclass="docutils literal notranslate"><spanclass="pre">db_tags</span></code> field … (this is a many-to-many field that
can be treated like an object for this purpose. It references all tags on the location)</p></li>
<li><p>… through the <codeclass="docutils literal notranslate"><spanclass="pre">db_tag</span></code> manager, find all Tags having a field <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code> set to the value
<p>This may seem a little complex at first, but this syntax will work the same for all queries. Just
remember that all <em>database-fields</em> in Evennia are prefaced with <codeclass="docutils literal notranslate"><spanclass="pre">db_</span></code>. So even though Evennia is
nice enough to alias the <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code> field so you can normally just do <codeclass="docutils literal notranslate"><spanclass="pre">char.key</span></code> to get a character’s
name, the database field is actually called <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code> and the real name must be used for the purpose
<div><p>Don’t confuse database fields with <aclass="reference internal"href="Attributes.html"><spanclass="doc">Attributes</span></a> you set via <codeclass="docutils literal notranslate"><spanclass="pre">obj.db.attr</span><spanclass="pre">=</span><spanclass="pre">'foo'</span></code> or
<codeclass="docutils literal notranslate"><spanclass="pre">obj.attributes.add()</span></code>. Attributes are custom database entities <em>linked</em> to an object. They are not
separate fields <em>on</em> that object like <codeclass="docutils literal notranslate"><spanclass="pre">db_key</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">db_location</span></code> are. You can get attached Attributes
manually through the <codeclass="docutils literal notranslate"><spanclass="pre">db_attributes</span></code> many-to-many field in the same way as <codeclass="docutils literal notranslate"><spanclass="pre">db_tags</span></code> above.</p>
<p>What if you want to have a query with with <codeclass="docutils literal notranslate"><spanclass="pre">OR</span></code> conditions or negated requirements (<codeclass="docutils literal notranslate"><spanclass="pre">NOT</span></code>)? Enter
objects take a normal django keyword query as its arguments. The special thing is that these Q
objects can then be chained together with set operations: <codeclass="docutils literal notranslate"><spanclass="pre">|</span></code> for OR, <codeclass="docutils literal notranslate"><spanclass="pre">&</span></code> for AND, and preceded with
<codeclass="docutils literal notranslate"><spanclass="pre">~</span></code> for NOT to build a combined, complex query.</p>
<p>In our original Lycanthrope example we wanted our werewolves to have names that could start with any
<p>In the above example, we construct our query our of several Q objects that each represent one part
of the query. We iterate over the list of vowels, and add an <codeclass="docutils literal notranslate"><spanclass="pre">OR</span></code> condition to the query using <codeclass="docutils literal notranslate"><spanclass="pre">|=</span></code>
(this is the same idea as using <codeclass="docutils literal notranslate"><spanclass="pre">+=</span></code> which may be more familiar). Each <codeclass="docutils literal notranslate"><spanclass="pre">OR</span></code> condition checks that
the name starts with one of the valid vowels. Afterwards, we add (using <codeclass="docutils literal notranslate"><spanclass="pre">&=</span></code>) an <codeclass="docutils literal notranslate"><spanclass="pre">AND</span></code> condition
that is negated with the <codeclass="docutils literal notranslate"><spanclass="pre">~</span></code> symbol. In other words we require that any match should <em>not</em> start
with the string “ab”. Note that we don’t actually hit the database until we convert the query to a
list at the end (we didn’t need to do that either, but could just have kept the query until we
<h3>Annotations and <codeclass="docutils literal notranslate"><spanclass="pre">F</span></code> objects<aclass="headerlink"href="#annotations-and-f-objects"title="Permalink to this headline">¶</a></h3>
<p>What if we wanted to filter on some condition that isn’t represented easily by a field on the
object? Maybe we want to find rooms only containing five or more objects?</p>
<p>We <em>could</em> retrieve all interesting candidates and run them through a for-loop to get and count
their <codeclass="docutils literal notranslate"><spanclass="pre">.content</span></code> properties. We’d then just return a list of only those objects with enough
contents. It would look something like this (note: don’t actually do this!):</p>
<spanclass="n">queryset</span><spanclass="o">=</span><spanclass="n">Room</span><spanclass="o">.</span><spanclass="n">objects</span><spanclass="o">.</span><spanclass="n">all</span><spanclass="p">()</span><spanclass="c1"># get all Rooms</span>
<p>Here we first create an annotation <codeclass="docutils literal notranslate"><spanclass="pre">num_objects</span></code> of type <codeclass="docutils literal notranslate"><spanclass="pre">Count</span></code>, which is a Django class. Note that
use of <codeclass="docutils literal notranslate"><spanclass="pre">location_set</span></code> in that <codeclass="docutils literal notranslate"><spanclass="pre">Count</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">*_set</span></code> is a back-reference automatically created by
Django. In this case it allows you to find all objects that <em>has the current object as location</em>.
Once we have those, they are counted.
Next we filter on this annotation, using the name <codeclass="docutils literal notranslate"><spanclass="pre">num_objects</span></code> as something we can filter for. We
use <codeclass="docutils literal notranslate"><spanclass="pre">num_objects__gte=5</span></code> which means that <codeclass="docutils literal notranslate"><spanclass="pre">num_objects</span></code> should be greater than 5. This is a little
harder to get one’s head around but much more efficient than lopping over all objects in Python.</p>
<p>What if we wanted to compare two parameters against one another in a query? For example, what if
instead of having 5 or more objects, we only wanted objects that had a bigger inventory than they
<p>Suppose you used tags to mark someone belonging an organization. Now you want to make a list and
need to get the membership count of every organization all at once. That’s where annotations and the
<codeclass="docutils literal notranslate"><spanclass="pre">.values_list</span></code> queryset method come in. Values/Values Lists are an alternate way of returning a
queryset - instead of objects, you get a list of dicts or tuples that hold selected properties from
the the matches. It also allows you a way to ‘group up’ queries for returning information. For
example, to get a display about each tag per Character and the names of the tag:</p>