From 6d130a2088b878fd6051aca0caab3ab7d6458cda Mon Sep 17 00:00:00 2001 From: ianb Date: Sun, 15 May 2005 21:38:36 +0000 Subject: Renamed file --- docs/BlogTutorial.txt | 187 ------------------------------------------------- docs/blog-tutorial.txt | 187 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/rebuild | 2 +- 3 files changed, 188 insertions(+), 188 deletions(-) delete mode 100644 docs/BlogTutorial.txt create mode 100644 docs/blog-tutorial.txt diff --git a/docs/BlogTutorial.txt b/docs/BlogTutorial.txt deleted file mode 100644 index fdc0762..0000000 --- a/docs/BlogTutorial.txt +++ /dev/null @@ -1,187 +0,0 @@ -+++++++++++++ -Blog Tutorial -+++++++++++++ - -:author: Ian Bicking -:revision: $Rev: 2321 $ -:date: $LastChangedDate: 2005-04-09 17:55:39 -0500 (Sat, 09 Apr 2005) $ - -.. contents:: - -.. note:: - - This tutorial is not yet finished. What you see is what you get, - and yeah that's not a whole lot. - -Introduction -============ - -This tutorial will go through the process of creating a blog using -`Python Paste `_, SQLObject_, and `Zope Page -Templates`_. This blog will rely heavily on static publishing -- that -is, when at all possible flat HTML pages will be written to disk. For -some parts (e.g., posting a new item) this will of course be -infeasible, but for most of the site this should work fine. - -.. _SQLObject: http://sqlobject.org -.. _Zope Page Templates: http://www.zope.org/DevHome/Wikis/DevSite/Projects/ZPT/FrontPage - -As much as possible, this code will be accompanied by unit tests, and -test-driven methodologies. Doing test-driven documenting of the -incremental process of creating test-driven software may get a little -hairy, but wish me luck! - -This tutorial presupposes you are somewhat comfortable with the basic -stack -- the `To-Do Tutorial`_ is a better place to start for a -beginner. - -.. _To-Do Tutorial: TodoTutorial.html - -Setting Up The App -================== - -.. note:: - - We're doing all this in the Python interpreter, even though you'd normally do - some of this in the shell. This way the authors of this tutorial - can use something called doctest_, which allows this tutorial to - be tested Python in an automated way. - - .. _doctest: http://python.org/doc/current/lib/module-doctest.html - -.. comment: - - >>> from paste.tests.doctest_webapp import * - >>> BASE = '/var/www/example-builds/wkblog' - >>> import sys - >>> clear_dir(BASE) - >>> run("app-setup create --template=webkit_zpt %s" % BASE) - >>> os.chdir(BASE) - -:: - - $ export PYTHONPATH=/path/to/Paste:$PYTHONPATH - $ BASE=/var/www/example-builds/wkblog - $ app-setup create --template=webkit_zpt $BASE - $ cd $BASE - -The Model -========= - -Since we're using SQLObject, we'll be doing the complete model in -that. The predecessor of this blog used flat files, custom-written -indexes, and simple rfc822_ based files for structure. It did not -scale well at all. - -.. _rfc822: http://python.org/doc/current/lib/module-rfc822.html - -Here's the model: - -.. run: - - create_file('db.py', 'v1', r""" - from sqlobject import * - try: - from datetime import datetime - now = datetime.now - except ImportError: - from mx import DateTime - now = DateTime.now - - class Article(SQLObject): - url = StringCol(notNull=True) - title = StringCol() - content = StringCol(notNull=True) - content_mime_type = StringCol(notNull=True) - author = ForeignKey('User') - parent = ForeignKey('Article', default=None) - created = DateTimeCol(notNull=True, default=now) - last_updated = DateTimeCol(default=None) - atom_id = StringCol() - hidden = BoolCol(notNull=True, default=False) - article_type = StringCol(notNull=True, default='article') - categories = RelatedJoin('Category') - - class Category(SQLObject): - name = StringCol(alternateID=True) - articles = RelatedJoin('Article') - - class User(SQLObject): - class sqlmeta: - table = 'user_info' - username = StringCol(alternateID=True) - email = StringCol() - name = StringCol() - password_encoded = StringCol() - role = StringCol(notNull=True, default='user') - """) - -.. raw:: html - :file: resources/BlogTutorial/db.py.v1.gen.html - -A few things to note: - -* Sadly, both datetime_ and mxDateTime_ are pseudo-standards. Well, - datetime is the standard, but mxDateTime has the legacy. So we have - to do this little dance to import one or the other. (We use ``now`` - later as a default) - -.. _datetime: http://python.org/doc/current/lib/module-datetime.html -.. _mxDateTime: http://www.egenix.com/files/python/mxDateTime.html - -* All the columns allow ``NULL`` by default, unless we say - ``notNull=True``. - -* ``ForeignKey('User')`` is a join to another table (the ``User`` - table, of course). We have to use strings to refer to other class, - because in this case the ``User`` class hasn't even been created. - Generally all references between classes are by name. - -* ``created`` has a default. You can give a fixed default (like - ``True`` or ``3``), or you can pass in a function that is called. - In this case, if you don't indicate ``Article(..., - created=something)`` then ``created`` will be the current date and - time. Unless a default is explicitly given, it is an error to leave - a column out of the constructor. ``NULL`` (which is ``None`` in - Python) is *not* considered a default. - -* Some column types don't relate directly to database types. For - instance, though PostgreSQL has a ``BOOLEAN`` type, most databases - don't, so ``BoolCol`` translates to some kind of ``INT`` column on - those database. - -* ``RelatedJoin('Category')`` creates a mapping table - (``article_category``) and is a many-to-many join between articles - and categories. - -* ``user`` isn't a valid table name in many databases, so while the - class is named ``User``, the table actually is ``user_info``. This - kind of extra information about a class is typically passed in - through the ``sqlmeta`` inner class. - -These classes have lots of other *behavior*, but this should be a good -list of actual information. We'll add more behavior later. - -Now we'll create the database. First we configure it, adding these -lines:: - - import os - database = 'sqlite:%s/data.db' % os.path.dirname(__file__) - -You could also use:: - - database = 'mysql://user:passwd@localhost/dbname' - database = 'postgresql://user:password@localhost/dbname' - -.. comment (change server.conf) - - >>> change_file('server.conf', [('insert', 2, r"""import os - ... database = 'sqlite:%s/data.db' % os.path.dirname(__file__) - ... - ... """)]) - -Now we'll use ``sqlobject-admin`` to set up the tables: - -.. comment (do it) - - >>> run('sqlobject-admin create -f server.conf -m wkblog.db') diff --git a/docs/blog-tutorial.txt b/docs/blog-tutorial.txt new file mode 100644 index 0000000..fdc0762 --- /dev/null +++ b/docs/blog-tutorial.txt @@ -0,0 +1,187 @@ ++++++++++++++ +Blog Tutorial ++++++++++++++ + +:author: Ian Bicking +:revision: $Rev: 2321 $ +:date: $LastChangedDate: 2005-04-09 17:55:39 -0500 (Sat, 09 Apr 2005) $ + +.. contents:: + +.. note:: + + This tutorial is not yet finished. What you see is what you get, + and yeah that's not a whole lot. + +Introduction +============ + +This tutorial will go through the process of creating a blog using +`Python Paste `_, SQLObject_, and `Zope Page +Templates`_. This blog will rely heavily on static publishing -- that +is, when at all possible flat HTML pages will be written to disk. For +some parts (e.g., posting a new item) this will of course be +infeasible, but for most of the site this should work fine. + +.. _SQLObject: http://sqlobject.org +.. _Zope Page Templates: http://www.zope.org/DevHome/Wikis/DevSite/Projects/ZPT/FrontPage + +As much as possible, this code will be accompanied by unit tests, and +test-driven methodologies. Doing test-driven documenting of the +incremental process of creating test-driven software may get a little +hairy, but wish me luck! + +This tutorial presupposes you are somewhat comfortable with the basic +stack -- the `To-Do Tutorial`_ is a better place to start for a +beginner. + +.. _To-Do Tutorial: TodoTutorial.html + +Setting Up The App +================== + +.. note:: + + We're doing all this in the Python interpreter, even though you'd normally do + some of this in the shell. This way the authors of this tutorial + can use something called doctest_, which allows this tutorial to + be tested Python in an automated way. + + .. _doctest: http://python.org/doc/current/lib/module-doctest.html + +.. comment: + + >>> from paste.tests.doctest_webapp import * + >>> BASE = '/var/www/example-builds/wkblog' + >>> import sys + >>> clear_dir(BASE) + >>> run("app-setup create --template=webkit_zpt %s" % BASE) + >>> os.chdir(BASE) + +:: + + $ export PYTHONPATH=/path/to/Paste:$PYTHONPATH + $ BASE=/var/www/example-builds/wkblog + $ app-setup create --template=webkit_zpt $BASE + $ cd $BASE + +The Model +========= + +Since we're using SQLObject, we'll be doing the complete model in +that. The predecessor of this blog used flat files, custom-written +indexes, and simple rfc822_ based files for structure. It did not +scale well at all. + +.. _rfc822: http://python.org/doc/current/lib/module-rfc822.html + +Here's the model: + +.. run: + + create_file('db.py', 'v1', r""" + from sqlobject import * + try: + from datetime import datetime + now = datetime.now + except ImportError: + from mx import DateTime + now = DateTime.now + + class Article(SQLObject): + url = StringCol(notNull=True) + title = StringCol() + content = StringCol(notNull=True) + content_mime_type = StringCol(notNull=True) + author = ForeignKey('User') + parent = ForeignKey('Article', default=None) + created = DateTimeCol(notNull=True, default=now) + last_updated = DateTimeCol(default=None) + atom_id = StringCol() + hidden = BoolCol(notNull=True, default=False) + article_type = StringCol(notNull=True, default='article') + categories = RelatedJoin('Category') + + class Category(SQLObject): + name = StringCol(alternateID=True) + articles = RelatedJoin('Article') + + class User(SQLObject): + class sqlmeta: + table = 'user_info' + username = StringCol(alternateID=True) + email = StringCol() + name = StringCol() + password_encoded = StringCol() + role = StringCol(notNull=True, default='user') + """) + +.. raw:: html + :file: resources/BlogTutorial/db.py.v1.gen.html + +A few things to note: + +* Sadly, both datetime_ and mxDateTime_ are pseudo-standards. Well, + datetime is the standard, but mxDateTime has the legacy. So we have + to do this little dance to import one or the other. (We use ``now`` + later as a default) + +.. _datetime: http://python.org/doc/current/lib/module-datetime.html +.. _mxDateTime: http://www.egenix.com/files/python/mxDateTime.html + +* All the columns allow ``NULL`` by default, unless we say + ``notNull=True``. + +* ``ForeignKey('User')`` is a join to another table (the ``User`` + table, of course). We have to use strings to refer to other class, + because in this case the ``User`` class hasn't even been created. + Generally all references between classes are by name. + +* ``created`` has a default. You can give a fixed default (like + ``True`` or ``3``), or you can pass in a function that is called. + In this case, if you don't indicate ``Article(..., + created=something)`` then ``created`` will be the current date and + time. Unless a default is explicitly given, it is an error to leave + a column out of the constructor. ``NULL`` (which is ``None`` in + Python) is *not* considered a default. + +* Some column types don't relate directly to database types. For + instance, though PostgreSQL has a ``BOOLEAN`` type, most databases + don't, so ``BoolCol`` translates to some kind of ``INT`` column on + those database. + +* ``RelatedJoin('Category')`` creates a mapping table + (``article_category``) and is a many-to-many join between articles + and categories. + +* ``user`` isn't a valid table name in many databases, so while the + class is named ``User``, the table actually is ``user_info``. This + kind of extra information about a class is typically passed in + through the ``sqlmeta`` inner class. + +These classes have lots of other *behavior*, but this should be a good +list of actual information. We'll add more behavior later. + +Now we'll create the database. First we configure it, adding these +lines:: + + import os + database = 'sqlite:%s/data.db' % os.path.dirname(__file__) + +You could also use:: + + database = 'mysql://user:passwd@localhost/dbname' + database = 'postgresql://user:password@localhost/dbname' + +.. comment (change server.conf) + + >>> change_file('server.conf', [('insert', 2, r"""import os + ... database = 'sqlite:%s/data.db' % os.path.dirname(__file__) + ... + ... """)]) + +Now we'll use ``sqlobject-admin`` to set up the tables: + +.. comment (do it) + + >>> run('sqlobject-admin create -f server.conf -m wkblog.db') diff --git a/docs/rebuild b/docs/rebuild index de59ef4..26d2dae 100755 --- a/docs/rebuild +++ b/docs/rebuild @@ -7,7 +7,7 @@ export PYTHONPATH=$parent:$PYTHONPATH NORMAL="DeveloperGuidelines Paste servers StyleGuide web/index \ what-is-paste testing-applications" -DOCTEST_BUILD="BlogTutorial TodoTutorial" +DOCTEST_BUILD="blog-tutorial TodoTutorial" for NAME in $NORMAL ; do if [ -e "$NAME.html" -a ! "$NAME.html" -ot "$NAME.txt" ] ; then -- cgit v1.2.1