<% header('MiddleKit Quick Start', None,
'''span.menuCmd {
	font-size: smaller;
	font-weight: bolder;
}
table.cmd {
	font-size: smaller;
	background-color: #EEE;
	margin-left: 2.5em;
}
table.cmd td {
    padding: 2pt;
}
table.dataTable {
	font-size: smaller;
}
tr.dataTableHeading {
}
td.dataTableHeading {
	color: white;
	background-color: black;
	font-weight: bolder;
	white-space: nowrap;
}
tr.dataTable1, tr.dataTable2 {
}
td.dataTable1 {
	background-color: #EEE;
	white-space: nowrap;
}
td.dataTable2 {
	background-color: #EEE;
	white-space: nowrap;
}''')
%>

<p class="right"><% name %> version <% versionString %></p>

<!-- contents -->


<a name="WhatYouNeed"></a><h2>What you need</h2>

<p>To perform the steps in this Quick Start you need:</p>

<ul>
	<li>Python 2.0 or greater, found at <a href="http://www.python.org">python.org</a></li>
	<li>mx.DateTime as found in <a href="http://www.lemburg.com/files/python/eGenix-mx-Extensions.html#Download-mxBASE">egenix-mx-base</a></li>
	<li>and MiddleKit, of course.</li>
</ul>


<a name="CreateObjModel"></a><h2>Create an object model</h2>

<p>Our example will be an application for tracking "videos", such as movies and TV series. Feel free to create your own application as you step through this guide to learn how to use MiddleKit (MK).</p>

<p>Note for Windows users: Our command line examples use forward slashes for the path names. You will have to use backslashes instead. In Python however, you can freely use forward slashes and probably should (since backslashes in Python are used for special characters such as \n and \t).</p>

<p>Create the directories for the project:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">mkdir -p Videos/Middle/Videos.mkmodel</span><br>
&gt; <span class="typed">cd Videos/Middle</span><br>
</td></tr></table>

<p>You could create the required MK files by hand, but we'll use the included template instead. Copy <span class="filename">MiddleKit/Resources/Template.mkmodel/Classes.csv</span> to <span class="filename">Videos/Middle/Videos.mkmodel</span>. Note that an MK model is specified by a directory that contains additional files.</p>

<p>You can edit the object model with popular spreadsheet programs such as Excel, StarOffice, etc. For new files, use the <span class="menuCmd">Save as...</span> command to choose the CSV or "comma-separated value" format. If necessary, you can create the file with a common text editor, but this method of editing becomes tedious because there is no column alignment (which is what the spreadsheet programs give you).</p>

<p>Open <span class="filename">Classes.csv</span> and edit it to become the following table. Or, you can grab this from:</p>
<pre class="filename">MiddleKit/Docs/Videos/Middle/Videos.mkmodel/Classes.csv</pre>

<table class="dataTable">
<tr class="dataTableHeading">
<td class="dataTableHeading"> Class</td><td class="dataTableHeading"> Attribute</td><td class="dataTableHeading"> Type</td><td class="dataTableHeading"> isRequired</td><td class="dataTableHeading"> Min</td><td class="dataTableHeading"> Max</td><td class="dataTableHeading"> Extras</td></tr>
<tr class="dataTable1"><td class="dataTable1">Video</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">isAbstract=1</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">title</td><td class="dataTable2">string</td><td class="dataTable2">1</td><td class="dataTable2">1</td><td class="dataTable2">100</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">directors</td><td class="dataTable1">list of Person</td><td class="dataTable1">0</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">10</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">cast</td><td class="dataTable2">list of Role</td><td class="dataTable2">0</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">Movie (Video)</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">year</td><td class="dataTable2">int</td><td class="dataTable2">1</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">rating</td><td class="dataTable1">enum</td><td class="dataTable1">1</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">Enums='g, pg, pg13, r, nc17, x, nr, other'</td></tr>
<tr class="dataTable2"><td class="dataTable2">TVSeries (Video)</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">years</td><td class="dataTable1">int</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">Comment='@@ supposed to be pickle; a list of ints'</td></tr>
<tr class="dataTable2"><td class="dataTable2">Person</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">video</td><td class="dataTable1">Video</td><td class="dataTable1">0</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">Comment='back pointer to View for directors attr'</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">name</td><td class="dataTable2">string</td><td class="dataTable2">1</td><td class="dataTable2">1</td><td class="dataTable2">100</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">birthDate</td><td class="dataTable1">date</td><td class="dataTable1">0</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">50</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">Role</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">video</td><td class="dataTable1">Video</td><td class="dataTable1">1</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">karacter</td><td class="dataTable2">string</td><td class="dataTable2">1</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">100</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">person</td><td class="dataTable1">Person</td><td class="dataTable1">1</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td></tr>
</table>

<p>Create a <span class="filename">Settings.config</span> file inside <span class="filename">Videos.mkmodel/</span>:</p>

<pre class="py">{
    'Package': 'Middle',
    #'SQLLog': { 'File': 'mk-sql.log' },
}</pre>

<p>The <span class="name">Package</span> setting tells MiddleKit that we want the classes for our object model to reside in a package named <span class="filename">Middle</span>. Python packages are useful for putting related modules (and classes) in a logical group. This also prevents name collisions between the package modules and other modules that may be on your Python path. Note that we chose the name of the directory containing the model.</p>

<p>The <span class="name">SQLLog</span> setting is commented out above, but you can uncomment it in order to see all the SQL that MiddleKit executes at run time. You can also change the filename to be 'stdout' or 'stderr'.</p>

<a name="GenCode"></a><h2>Generate code</h2>

<p>We now want to run the MK Generate program to create the necessary Python and SQL code to support our application. Locate the Generate program, found in <span class="filename">MiddleKit/Design/</span>:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">python /Projects/Webware/MiddleKit/Design/Generate.py</span><br>
Generate.py: error: Missing options.<br>
Usage: Generate.py --db DBNAME --model FILENAME [--sql] [--py] [--config FILENAME] [--outdir DIRNAME]<br>
       Generate.py -h | --help<br>
<br>
       * Known databases include: MSSQL, MySQL, PostgreSQL<br>
       * If neither --sql nor --py are specified, both are generated.<br>
       * If --outdir is not specified, then the base filename (sans extension) is used.<br>
       * --config lets you specify a different config filename inside the model.<br>
         This is mostly useful for the regression test suite.<br>
&gt;
</td></tr></table>

<p>Now try again with the database and model as arguments:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">python /Projects/Webware/MiddleKit/Design/Generate.py --db MySQL --model Videos</span><br>
Generating SQL...<br>
Generating Python...
</td></tr></table>

<p>In the current directory, you will find:</p>

<ul>
	<li>Python files that are stubs for your custom code (<span class="filename">Video.py</span>, <span class="filename">Movie.py</span>, etc.).</li>
	<li>The directory <span class="filename">GeneratedPy/</span>, containing base classes for each of your classes. These base classes hold any code MK found necessary to generate.</li>
	<li>The directory <span class="filename">GeneratedSQL/</span>, containing <span class="filename">Create.sql</span>.</li>
</ul>

<p>You will find that as you update your object model and its sample data, you often need to re-generate. For this purpose, create a <span class="filename">generate</span> script:</p>

<p>UNIX:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">cat &gt; generate<br>
python /Projects/Webware/MiddleKit/Design/Generate.py --db MySQL --model Videos<br>
^D<br></span>
> <span class="typed">chmod u+x generate</span><br>
> <span class="typed">./generate</span><br>
Generating SQL...<br>
Generating Python...
</td></tr></table>

<p>Windows:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">copy con generate.bat<br>
python C:\Projects\Webware\MiddleKit\Design\Generate.py --db MySQL --model Videos<br>
^Z<br></span>
> <span class="typed">generate</span><br>
Generating SQL...<br>
Generating Python...
</td></tr></table>


<a name="CreateData"></a><h2>Create sample data</h2>

Copy the template file <span class="filename">MiddleKit/Resources/Template.mkmodel/Samples.csv</span> to <span class="filename">Videos/Middle/Videos.mkmodel</span> and edit it to contain the following sample data. Or, you can grab this file from:</p>

<pre class="filename">MiddleKit/Docs/Videos/Middle/Videos.mkmodel/Samples.csv</pre>

<table class="dataTable">
<tr class="dataTable1"><td class="dataTable1">Movie objects</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">title</td><td class="dataTable2">year</td><td class="dataTable2">rating</td></tr>
<tr class="dataTable1"><td class="dataTable1">American Beauty</td><td class="dataTable1">1999</td><td class="dataTable1">r</td></tr>
<tr class="dataTable2"><td class="dataTable2">American Pie</td><td class="dataTable2">1999</td><td class="dataTable2">r</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">Person objects</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">video</td><td class="dataTable1">name</td><td class="dataTable1">birthDate</td></tr>
<tr class="dataTable2"><td class="dataTable2">1</td><td class="dataTable2">Paul Weitz</td><td class="dataTable2">1/1/1966</td></tr>
<tr class="dataTable1"><td class="dataTable1">2</td><td class="dataTable1">Sam Mendes</td><td class="dataTable1">9/1/1965</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">Kevin Spacey</td><td class="dataTable2">7/26/1959</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">Mena Suvari</td><td class="dataTable1">2/9/1979</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">Jason Biggs</td><td class="dataTable2">5/12/1978</td></tr>
<tr class="dataTable1"><td class="dataTable1">&nbsp;</td><td class="dataTable1">Shannon Elizabeth</td><td class="dataTable1">9/7/1976</td></tr>
<tr class="dataTable2"><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td><td class="dataTable2">&nbsp;</td></tr>
<tr class="dataTable1"><td class="dataTable1">Role objects</td><td class="dataTable1">&nbsp;</td><td class="dataTable1">&nbsp;</td></tr>
<tr class="dataTable2"><td class="dataTable2">video</td><td class="dataTable2">karacter</td><td class="dataTable2">person</td></tr>
<tr class="dataTable1"><td class="dataTable1">1</td><td class="dataTable1">Lester Burnham</td><td class="dataTable1">3</td></tr>
<tr class="dataTable2"><td class="dataTable2">1</td><td class="dataTable2">Angela Hayes</td><td class="dataTable2">4</td></tr>
<tr class="dataTable1"><td class="dataTable1">2</td><td class="dataTable1">Jim</td><td class="dataTable1">5</td></tr>
<tr class="dataTable2"><td class="dataTable2">2</td><td class="dataTable2">Heather</td><td class="dataTable2">4</td></tr>
<tr class="dataTable1"><td class="dataTable1">2</td><td class="dataTable1">Nadia</td><td class="dataTable1">5</td></tr>
</table>

<p>You can see that in sample data, references to objects (sometimes called "obj refs", "references" or "pointers") are made by referring to the implicit serial number of the target object (1, 2, 3, ...).  Alternatively, you may specify the serial numbers explicitly by adding a "serialNum" column and putting in a serial number for each object.  This is useful since it allows you to remove objects from your Samples.csv file without affecting the numbering of other objects of that class.</p>

<p>Warning: If an obj ref attribute points to a base class that has subclasses (such as Video) you may need to qualify your sample data by specifying the exact class of the reference. For example, instead of simply a number, an obj ref could be Movie.2 or TVSeries.2.</p>

<p>Now run <span class="filename">generate</span> again. You will find a new file at <span class="filename">GeneratedSQL/InsertSamples.sql</span>.</p>


<a name="CreateDB"></a><h2>Create the database</h2>

<p>Create the database:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">mysql -u <i>user</i> -p<i>password</i> &lt; GeneratedSQL/Create.sql</span>
</td></tr></table>

<p>Now insert the sample data:</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">mysql -u <i>user</i> -p<i>password</i> &lt; GeneratedSQL/InsertSamples.sql</span>
</td></tr></table>

<p>As you change the object model, you will need to issue these commands again. Make it easy on yourself by putting these in <span class="filename">create</span> and <span class="filename">insert</span> scripts, like we did with <span class="filename">generate</span>.</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">generate</span><br>
python /Projects/Webware/MiddleKit/Design/Generate.py --db MySQL --model Videos<br>
Generating SQL...<br>
Generating Python...<br>
<br>
&gt; <span class="typed">create</span><br>
mysql &lt; GeneratedSQL\Create.sql
Tables_in_Videos<br>
_MKClassIds<br>
Movie<br>
Person<br>
Role<br>
TVSeries<br>
<br>
&gt; <span class="typed">insert</span><br>
mysql &lt; GeneratedSQL\InsertSamples.sql
</td></tr></table>


<a name="CompleteDirStruct"></a><h2>Complete the directory structure</h2>

<p>Let's write some Python code that uses the middle objects. We're going to put the code next door to the model by created a new <span class="filename">Command</span> directory.</p>

<table class="cmd"><tr><td>
&gt; <span class="typed">cd Videos</span><br>
&gt; <span class="typed">mkdir Command</span><br>
&gt; <span class="typed">cd Command</span>
</td></tr></table>

<p>Create a file named <span class="filename">main.py</span>. Our file system now looks like this:</p>

<pre>
    Videos/
        Middle/
            generate*
            create*
            insert*
            Videos.mkmodel/
                Classes.csv
                Samples.csv
                Settings.config
            GeneratedPy/
                GenVideo.py, GenMovie.py, ...
            GeneratedSQL/
                Create.sql
                InsertSamples.sql
                Info.text
            Video.py
            Movie.py
            ...
        Command/
            main.py
</pre>


<a name="SetUpStore"></a><h2>Set up the store</h2>

<p>We'll first create an object store, which (largely) hides you from the database while allowing you to work in a fully object-oriented, Python-centric frame of mind. Put this <span class="filename">main.py</span> file in the <span class="filename">Command/</span> directory:</p>

<pre class="py">
# Gain access to the Middle package
import os, sys
sys.path.insert(1, os.path.abspath(os.pardir))

from mx.DateTime import DateFrom
from MiddleKit.Run.MySQLObjectStore import MySQLObjectStore
# For MSSQL:
# from MiddleKit.Run.MSSQLObjectStore import MSSQLObjectStore


def main():
    # Set up the store
    store = MySQLObjectStore(user='user', passwd='password')
    # For MSSQL:
    # store = MSSQLObjectStore(dsn='dsn',user='user',password='password',clear_auto_commit=0)
    store.readModelFileNamed('../Middle/Videos')

if __name__=='__main__':
    main()
</pre>

<p>If you get an error that MiddleKit cannot be imported, make sure that <span class="filename">Webware/</span> is in your path. You can do this temporarily for your command line session by setting PYTHONPATH:</p>

<p>Windows (and UNIX.csh):</p>

<table class="cmd"><tr><td>
> <span class="typed">set PYTHONPATH=C:\Projects\Webware</span>
</td></tr></table>

<p>UNIX.sh:</p>

<table class="cmd"><tr><td>
> <span class="typed">export PYTHONPATH=/Projects/Webware</span>
</td></tr></table>


<a name="CreateObj"></a><h2>Create a new object</h2>

<p>Now create a new object. Augment <span class="name">main()</span> with this:</p>

<pre class="py">
# Gain access to the Middle package
import os, sys
sys.path.insert(1, os.path.abspath(os.pardir))

from mx.DateTime import DateFrom
from MiddleKit.Run.MySQLObjectStore import MySQLObjectStore
<b>from Middle.Movie import Movie</b>

def main():
    # Set up the store
    store = MySQLObjectStore(user='user', passwd='password')
    store.readModelFileNamed('../Middle/Videos')

<b>    movie = Movie()
    movie.setTitle('The Terminator')
    movie.setYear(1984)
    movie.setRating('r')
    store.addObject(movie)
    store.saveChanges()</b>

if __name__=='__main__':
    main()
</pre>

<p>Note that you create and modify a <span class="name">Movie</span> just like you would any Python object. However, you do have to add the object to the MK store and eventually tell the MK store to save its changes to the persistent store (the SQL database in our case).</p>


<a name="CreateMoreObjs"></a><h2>Create more objects</h2>

<p>Let's add more objects to our store. Add these imports after the import of Movie:</p>

<pre class="py">from Middle.Person import Person
from Middle.Role import Role
</pre>


<p>In between readModelFileNamed() and saveChanges(), add these:</p>

<pre class="py">
    movie = Movie()
    movie.setTitle('The Terminator')
    movie.setYear(1984)
    movie.setRating('r')
    store.addObject(movie)

    james = Person()
    james.setName('James Cameron')
    james.setBirthDate('8/16/1954')
    movie.addToDirectors(james)

    ahnuld = Person()
    ahnuld.setName('Arnold Schwarzenegger')
    ahnuld.setBirthDate('7/30/1947')
    store.addObject(ahnuld)

    terminator = Role()
    terminator.setKaracter('Terminator')
    terminator.setPerson(ahnuld)
    movie.addToCast(terminator)
</pre>

<p>Note that for every new object we must either add it to the store directly with store.addObject(), or indirectly, by adding it to an existing object's list (such as addToRoles() and addToCast()).</p>

<p>Of course, a typical application looks very different from our example. Often you will have more generic code for creating new objects, usually in response to user input or processing a data feed.</p>


<a name="FetchObjs"></a><h2>Fetch objects</h2>

<p>You can get a list of objects of a particular class returned to you as a list, like so:</p>

<pre class="py">
    from Middle.Video import Video
    videos = store.fetchObjectsOfClass(Video)
</pre>

<p>This will pick up <i>all</i> Videos, including both Movies and TVSeries, which inherit from Video. An optional keyword argument, isDeep, allows you to turn this off so that the fetch is <i>shallow</i>. In our case, that wouldn't make any sense since Video is an abstract class.</p>

<p>You can also give the name of the class instead of the Python class:</p>

<pre class="py">
    videos = store.fetchObjectsOfClass('Video')
</pre>

<p>You can then filter this list with a Python <i>list comprehension</i> like you normally would:</p>

<pre class="py">    videos = store.fetchObjectsOfClass('Video')
    # Get all videos that start with 'A':
    videos = [video for video in videos if video.title().upper().startswith('A')]
</pre>

<p>If you have a lot of videos, it may be too inefficient to pull them all into memory, just to grab the ones that start with 'A'. You can solve this problem by using a server-side query, e.g., a SQL WHERE clause:</p>

<pre class="py">
    videos = store.fetchObjectsOfClass('Video', clauses="WHERE title LIKE 'A%'")
</pre>

<p>If your SQL clauses are fairly simple, then they should port well between SQL databases.</p>

<p>If the fetched objects already exist in memory, their attributes will be updated with the values from the database. This promotes consistency and avoids having multiple Python instances representing the same object.</p>


<a name="DelObjs"></a><h2>Delete an object</h2>

<p>Deleting objects is well supported in MiddleKit, but not yet described in this Quick Start. See <a href="UsersGuide.html#MT_DeletingObjects">Deleting objects</a> in the User's Guide for more information.</p>


<a name="UserSerialNums"></a><h2>Use serial numbers</h2>

<p>Every new object is given a serial number when changes are saved. The serial number is unique among all objects of it's class. You could store a reference to the class and serial number outside the store (such as in a file, an HTTP cookie, a session object, etc.) and retrieve the object later:</p>

<pre class="py">
    serialNum = video.serialNum()
    .
    .
    video = store.fetchObject(Video, serialNum)
</pre>

<p>The above code will throw an exception if the object is not found. You can specify a default that will returned instead:</p>
<pre class="py">
    video = store.fetchObject(Video, serialNum, None)
    if video is None:
        doSomething()
</pre>


<a name="UseMKBrowser"></a><h2>Use the MKBrowser</h2>

<p>The MKBrowser let's you browse through any MK object store via the web. You will need to have <a href="../../WebKit/Docs/index.html">WebKit</a> installed.</p>

<p>MiddleKit is not only a Python package and a Webware component, but also a plug-in for WebKit. Upon launching WebKit, MiddleKit will install the MKBrowser as a context.</p>

<p>You can go to an example WebKit page and see a list of all contexts in the sidebar. Click on MKBrowser and enter the location of the MK model and connection information for your database. Once connected, you can see a list of all your classes on the left and by clicking on them, see all of their objects.</p>

<p>When viewing objects, you can click their obj ref and list attributes to traverse the object graph.</p>

<p>Note that even compared to other components of MiddleKit (which is an alpha release), the MKBrowser is a bit flaky.</p>

<p>Future versions of MKBrowser will allow queries and editing.</p>

<p>Have fun.</p>


<a name="Next"></a><h2>What's Next?</h2>

<p>Your next steps are to read the <a href="UsersGuide.html">User's Guide</a> which contains more information about using MiddleKit, and build your own MiddleKit application.</p>

<% footer() %>