========================================== Create the first App Table (``vehicle``) ========================================== One thing to note before we dig into this: Wutta Framework tends to prefer "singular" as opposed to "plural" table names. For instance ``widget`` instead of ``widgets``, and ``person`` instead of ``people``. This is not a strict requirement, however the logic used to generate other names (e.g. routes, permissions) in the web app will often "just work" if the table name is singular. If you have a plural-named table you may need to override more names, but even with singular name you may find you have to override something later anyway. We'll go with ``vehicle`` for our first table in this tutorial. New App Table Wizard -------------------- The web app comes with a wizard for creating a new table. You typically need to "become root" in order to access it. This whole idea generally assumes you'll use it for local development only, with an "editable" install (``pip install -e``) of your project. The wizard can generate new Python modules directly in your source tree. Under the Admin menu choose App Info. From there you can click either App Tables or else Alembic Dashboard; either will give you a page which then has a button to start the new table wizard. The wizard has several steps, and we'll go over each below. But at a high level it's just: * collect info * generate python module for table model * generate alembic revision script * run alembic to migrate database At the end you have a fully functional table, backed by Python code which you can modify further as needed. Enter Details ~~~~~~~~~~~~~ Hopefully this part is straightforward enough, just have to provide all the naming variations and then define whatever columns are needed. Note that each table is automatically given a UUID column for primary key, so you only need to define "other" columns. If you have Continuum versioning enabled then you can choose whether or not that should apply to the table overall, and each column individually. .. note:: One last note about naming (!): It's probably a good idea to use a custom prefix for your table names. This will help to avoid collisions when many related packages are installed. It may seem (and be) irrelevant but it's an easy thing to future-proof. We'll use ``poser_`` as table prefix, so here are the values for our vehicle example: * **Table Name** - ``poser_vehicle`` * **Model Class** - ``Vehicle`` * **Model Title** - ``Vehicle`` * **Model Title Plural** - ``Vehicles`` * **Description** - Represents a vehicle for which mileage is tracked. * **Versioning** - enabled And for **Columns** (all with versioning enabled): * ``name`` - string, length 50, not nullable * ``make`` - string, length 50, not nullable * ``model`` - string, length 50, not nullable * ``year`` - integer, not nullable Click the "Details are complete" button when finished. Write Model ~~~~~~~~~~~ This asks where on disk the wizard should write a new Python module file, containing the table model class. Even if you intend to add the code to an existing module, you should let the wizard create a new file and then you can cut/paste by hand after this step. Click the button to write a new file when ready. Confirm Model ~~~~~~~~~~~~~ At this point the code for the new table exists, but it is not yet part of the running app. You should first review the new code, do a basic sanity check and ideally define a ``__str__()`` method for the model class. (And here's where you would cut/paste the code to an existing module, if that's your intention.) Once you're happy with the model class definition, add an ``import`` statement for it within the ``__init__.py`` module. All relevant file paths and example ``import`` statement should be on screen for reference. Technically the running app may need a restart at this point, to reload all modules. But if you're running the web app with ``-r`` in local dev, you should not need to manually restart. The ultimate test is whether the running app is "aware" of the new model class; you can click "Check for Model" to confirm that. Write Migration ~~~~~~~~~~~~~~~ Next we let Alembic work its magic; it knows how to compare the Python model definitions with current database schema, and generate a script which would migrate the DB to match the model. The main thing here is to choose the correct *branch*. If this is your first table for a new project, you'll need to create a new branch. The wizard should auto-suggest that for you in this case. In many cases you won't need to change anything here, just click the button to generate a new script when ready. Confirm Migration ~~~~~~~~~~~~~~~~~ As with the model class, you should review the code generated for the migration. Path to the new script is on screen for reference. It is important to sanity check everything. Although in many cases the code is fine, there can be some edge cases. Thankfully for the "new table wizard" scenario, the risk of edge case is fairly low. Migrate Database ~~~~~~~~~~~~~~~~ Moment of truth, this will run the new migration script against the app's database. Confirm Table ~~~~~~~~~~~~~ The new table should now exist in your DB; click "Check for Table" to confirm. Commit Code ~~~~~~~~~~~ This is just an "outro" page with a reminder to commit all that code you just generated. From here the last button will take you to view your new "App Table" details, described next. Viewing the Table ----------------- You may already be viewing the table details, but if not you can always find your table via the App Tables area. This shows various info such as the Python module file in which the table model class is defined, as well as the column details. In the Cross-Reference panel on the right, you'll see button link(s) to some "master" view(s) for the table. As well as a button to create a new master view. What you *won't* see here, is the table data. That's what a master view is for, which we'll go over in the next section.