Changes between Version 12 and Version 13 of TutorialDivingIn

Show
Ignore:
Timestamp:
11/02/07 21:35:44 (6 years ago)
Author:
guest (IP: 207.255.245.5)
Comment:

Corrected some typos and made a few minor stylistic (wording) changes (ie: altered a series of sentences that all start with 'also').

Legend:

Unmodified
Added
Removed
Modified
  • TutorialDivingIn

    v12 v13  
    3939}}} 
    4040 
    41 What does this snippet do? First of all it connects to an SQLite-database^2^. Then it turns on `echo` on our connection to that database. This means that all SQL statements that gets sent to that database will be also displayed on the console. Pretty handy to understand what happens behind the scene and for debugging. Remember you can turn it off whenever you like by simply setting it to `False`. 
     41What does this snippet do? First of all it connects to an SQLite-database^2^. Then it turns on `echo` on our connection to that database. This means that all SQL statements that get sent to that database will also be displayed on the console. Pretty handy to understand what happens behind the scene and for debugging. Remember you can turn it off whenever you like by simply setting it to `False`. 
    4242 
    4343Then it declares a `Movie`-entity (ie. a class, that inherits Elixir's `Entity`-baseclass). This entity will hold three fields: 
     
    7676}}} 
    7777     
    78 With that `setup_all()` call, you have created an SQLAlchemy's Table object as well as a Mapper object for the Movie class. The Table object is a python object describing what the table in your database will look like. The mapper is another python object describing how your class ''maps'' to that table. Both these objects are automatically generated based on the definition of your class. 
     78With that `setup_all()` call, you have created an SQLAlchemy Table object as well as a Mapper object for the Movie class. The Table object is a python object describing what the table in your database will look like. The mapper is another python object describing how your class ''maps'' to that table. Both of these objects are automatically generated based on the definition of your class. 
    7979 
    8080Then, by calling, `create_all()`, you've told Elixir to take all the Table objects it knows of, and create real tables by issuing SQL statements on the database. As you'll see on your console, here is the SQL that gets generated for the above entity: 
     
    9191}}} 
    9292 
    93 There are two important points to notice here. First, the name of the table: by default Elixir, takes the name of the module followed by the name of your class lower cased. You can change that by [wiki:TutorialDivingIn#a7.Usingoptions using options], as we'll see later on. The other point is that Elixir generated an `id` column and used it as the primary key for our Entity. This is because we didn't provide a primary key ourselves. If you want to specify the primary key yourself, no problem just pass `primary_key=True` to the field(s) you want to act as the primary key. 
    94  
    95 Now, we'll instantiate a first movie-object. You could add more movies here, but so far "Blade Runner" does the job. 
     93There are two important points to notice here. First, the name of the table: By default Elixir, takes the name of the module followed by the name of your class lower cased. You can change that by [wiki:TutorialDivingIn#a7.Usingoptions using options], as we'll see later on. The other point is that Elixir generated an `id` column and used it as the primary key for our Entity. This is because we didn't provide a primary key ourselves. If you want to specify the primary key yourself, no problem just pass `primary_key=True` to the field(s) you want to act as the primary key. 
     94 
     95Now, we'll instantiate our first movie-object. You could add more movies here, but so far "Blade Runner" does the job. 
    9696 
    9797{{{ 
     
    128128 
    129129^3^ ''Make sure, you're running your interpreter from the directory where you saved the `model.py` file.'' [[BR]] 
    130 ^4^ ''If you're using any other DBMS than SQLite, just drop the created table (most probably something like "`DROP TABLE model_movie;`").'' 
     130^4^ ''If you're using any DBMS other than SQLite, just drop the created table (most probably something like "`DROP TABLE model_movie;`").'' 
    131131 
    132132 
     
    245245== 5. More querying == 
    246246 
    247 Now, putting data into a database isn't of much use if you can't use it afterwards, is it?. As the observant reader will have noticed, you usually query the database by using the `query` attribute on your entities (for example: `Movie.query.all()`)^6^. But what is that query attribute? It's a property which gives you an SQLAlchemy Query object. This object lets your query your database in a lot of interesting and powerful ways. Here are only a few examples of what you could do^7^: 
     247Now, putting data into a database isn't of much use if you can't use it afterwards, is it?. As the observant reader will have noticed, you usually query the database by using the `query` attribute on your entities (for example: `Movie.query.all()`)^6^. But what is that query attribute? It's a property which gives you an SQLAlchemy Query object. This object lets you query your database in a lot of interesting and powerful ways. Here are only a few examples of what you could do^7^: 
    248248 
    249249{{{ 
     
    271271}}} 
    272272 
    273 You can also note we used the `get_by` Elixir-specific shortcut, which is equivalent to the following SQLAlchemy query: session.query(Director).filter_by(name='Ridley Scott').first() 
     273You can also note we used the `get_by` Elixir-specific shortcut, which is equivalent to the following SQLAlchemy query: `session.query(Director).filter_by(name='Ridley Scott').first()` 
    274274 
    275275For more information on what you can do with query objects, please look at the  
     
    282282== 6. Many to Many relationships (and composite primary keys) == 
    283283 
    284 Now, we think it would make a nice addition to our little application to relate movies to their genres. As most movie fall into several genres and that (hopefully) several movies belong to the same genre, we'll model that with a ManyToMany relationship. 
    285  
    286 We would also like to not use the default surrogate 'id' primary key that we've had in the Movie entity so far. We could like to accept two movies with the same `title` but not on the same `year`. So a composite primary key on `title` and `year` seems like a good idea. 
     284Now, we think it would make a nice addition to our little application to relate movies to their genres. As most movies fall into several genres and (hopefully) several movies belong to the same genre, we'll model that with a ManyToMany relationship. 
     285 
     286We would also like to not use the default surrogate 'id' primary key that we've had in the Movie entity so far. We would like to accept two movies with the same `title` but not on the same `year`. So a composite primary key on `title` and `year` seems like a good idea. 
    287287 
    288288So we'll add a new entity "`Genre`" and modify the existing `Movie` entity in our `model.py`: 
     
    318318}}} 
    319319 
    320 we will now re-add some data (you'll find this batch in [attachment:section6.py]). 
     320we will re-add some data (you'll find this batch in [attachment:section6.py]). 
    321321 
    322322{{{ 
     
    353353}}} 
    354354 
    355 There are quite a few available options to control many aspects of your entities: specify the ordering of results, the inheritance type or simply, as above, the table name; load the table columns from the database instead of defining them as python attribute, add the necessary hooks to check for concurrent access, ... 
     355There are quite a few available options to control many aspects of your entities: specify the ordering of results; the inheritance type or simply, as above, the table name; load the table columns from the database instead of defining them as python attribute; add the necessary hooks to check for concurrent access, ... 
    356356 
    357357For the full list of available options and a detailed description for each of them, please look at the [http://elixir.ematia.de/apidocs/elixir.options.html options section of the API documentation]. 
     
    370370  object with a particular primary key" - this pattern is called the Identity Map. 
    371371 
    372 Elixir provides a default global contextual (thread-local) session for you to use, and Elixir entities are by default linked to that session by using that session's contextual mapper. It just means that whenever you create an instance of any of your entities, that instance is automatically added (save'd) to the session. If you want to use another session (for example, to not use a global/contextual session at all), that's fine, you just need to tell Elixir by using the corresponding option. 
     372Elixir provides a default global contextual (thread-local) session for you to use, and Elixir entities are by default linked to that session by using that session's contextual mapper. It just means that whenever you create an instance of any of your entities, that instance is automatically added (saved) to the session. If you want to use another session (for example, to not use a global/contextual session at all), that's fine, you just need to tell Elixir by using the corresponding option. 
    373373 
    374374You'll find much more information about sessions and what you can do with sessions in [http://www.sqlalchemy.org/docs/04/session.html the corresponding section of SQLAlchemy documentation]. 
     
    411411}}} 
    412412 
    413 Several points are important to notice. First, we used multi-table inheritance. Which means that each of these entities will get a table for themselves (with foreign keys to link them). For an explanation of the different kind of inheritance you can do, and what that involves, please refer once again to the [http://www.sqlalchemy.org/docs/04/mappers.html#advdatamapping_mapper_inheritance corresponding SQLAlchemy documentation]. Note that Elixir currently only supports "single table" and "joined/multi-table" inheritance (both in their polymorphic and non polymorphic versions). Elixir generate the correct tables and mappers for you but it's still important for you to realize what that is. 
    414  
    415 Secondly, when using inheritance with Elixir (and not using the default values), you have to tell Elixir what kind of inheritance you want in each and every entity, including the parent one. This is because some work needs to be done on the parent too for the inheritance to work and that entity needs to know that this extra processing needs to be done. 
     413Several points are important to notice. First, we used multi-table inheritance. Which means that each of these entities will get a table for themselves (with foreign keys to link them). For an explanation of the different kind of inheritance you can do, and what that involves, please refer once again to the [http://www.sqlalchemy.org/docs/04/mappers.html#advdatamapping_mapper_inheritance corresponding SQLAlchemy documentation]. Note that Elixir currently only supports "single table" and "joined/multi-table" inheritance (both in their polymorphic and non polymorphic versions). Elixir generates the correct tables and mappers for you but it's still important for you to realize what that is. 
     414 
     415Secondly, when using inheritance with Elixir (and not using the default values), you have to tell Elixir what kind of inheritance you want in each and every entity, including the parent one. This is because some work also needs to be done on the parent for the inheritance to work and that entity needs to know that this extra processing needs to be done. 
    416416 
    417417Let's input more data (you'll find this batch in [attachment:section9.py]). 
     
    459459== 10. Where to go from here? == 
    460460 
    461 By now, you should know how to create simple models and set up relationships between them. The next steps would be to first play a bit more with the model we've created. In case you lost it, or didn't follow the whole tutorial, you can use the [attachment:model.py complete model], as well as an [attachment:alltogether.py aggregated data set] you can play with. Then we suggest you to explore further the possibilities of Elixir by looking at our [http://elixir.ematia.de/apidocs/elixir.html API-docs] which is quite thorough and the [source:/elixir/trunk/tests/ testcases] which provide some nice examples. Also, the more experienced (or adventurous) programmers will probably be interested in what happens [wiki:BehindTheScene behind the scene]. 
    462  
    463 And also, please remember than once the setup phase is done. Working with Elixir is just as working with plain SQLAlchemy (with a few shortcuts syntaxes provided for convenience), so reading the [http://www.sqlalchemy.org/docs/ SQLAlchemy documentation] is always a good idea. 
     461By now, you should know how to create simple models and set up relationships between them. The next step would be to play a bit more with the model we've created. In case you lost it, or didn't follow the whole tutorial, you can use the [attachment:model.py complete model], as well as an [attachment:alltogether.py aggregated data set] you can play with. Then we suggest you to explore further the possibilities of Elixir by looking at our rather thorough [http://elixir.ematia.de/apidocs/elixir.html API-docs] and the [source:/elixir/trunk/tests/ testcases] which provide some nice examples. Additionaly, the more experienced (or adventurous) programmers will probably be interested in what happens [wiki:BehindTheScene behind the scene]. 
     462 
     463Furthermore, please remember than once the setup phase is done. Working with Elixir is just as working with plain SQLAlchemy (with a few shortcuts syntaxes provided for convenience), so reading the [http://www.sqlalchemy.org/docs/ SQLAlchemy documentation] is always a good idea. 
    464464 
    465465Enjoy database development the easy way and let us know when you created something cool!