Changeset 4586
- Timestamp:
- 05/16/08 03:39:02 (2 months ago)
- Files:
-
- trunk/docs/2.0/Controllers.rst (modified) (22 diffs)
- trunk/docs/2.0/QuickStart.rst (modified) (1 diff)
- trunk/docs/2.0/SQLAlchemy.rst (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/docs/2.0/Controllers.rst
r4408 r4586 25 25 26 26 Suppose using ``tg-admin quickstart`` you generate a TurboGears project named 27 " gs". Your default controller code would be created in the file28 `` gs/gs/controllers/root.py``.27 "HelloWorld". Your default controller code would be created in the file 28 ``HelloWorld/helloworld/controllers/root.py``. 29 29 30 30 Modify the default ``controllers.py`` to read as follows: … … 33 33 34 34 """Main Controller""" 35 from gs.lib.base import BaseController35 from helloworld.lib.base import BaseController 36 36 from tg import expose, flash 37 37 from pylons.i18n import ugettext as _ 38 38 #from tg import redirect, validate 39 #from gs.model import DBSession39 #from helloworld.model import DBSession 40 40 41 41 class RootController(BaseController): … … 59 59 60 60 URLs not explicitly mapped to other methods of the controller will generally be 61 directed to the method named ``default()`` . With the above example, requesting61 directed to the method named ``default()``. With the above example, requesting 62 62 any URL besides ``/index``, for example ``http://localhost:8080/hello``, will 63 63 return the message "This page is not ready". … … 88 88 89 89 """Main Controller""" 90 from gs.lib.base import BaseController90 from helloworld.lib.base import BaseController 91 91 from tg import expose, flash 92 92 from pylons.i18n import ugettext as _ 93 93 #from tg import redirect, validate 94 #from gs.model import DBSession94 #from helloworld.model import DBSession 95 95 96 96 First you need to import the required modules. … … 102 102 BaseController from the lib module of your own project, and not from TurboGears. 103 103 104 TurboGears provides a base TGController, but it's imported in lib so that you105 can modify it to suit the needs of your appication. For example you104 TurboGears provides a base TGController, but it's imported in lib folder of current project (HelloWorld/helloworld/lib). 105 So that you can modify it to suit the needs of your appication. For example you 106 106 can define actions which will happen on every request, add parameters 107 107 to every template call, and otherwise do what you need to the request on the way … … 110 110 The next thing to notice is that we are importing `expose` from `tg`. 111 111 `BaseController`` classes and the expose decorator are the basis of TurboGears 112 controllers. The @expose decorator declarairs that your method should be112 controllers. The `@expose` decorator declairs that your method should be 113 113 *exposed to the web*, and provides you with the ability to say how the results 114 of the controller should be rendered. 115 116 The other imports are there incase you do internationalization, or use the 114 of the controller should be rendered. 115 116 The other imports are there incase you do the internationalization, 117 or use the http redirect function, validate inputs/outputs, or use the models. 117 118 118 119 :: … … 120 121 class RootController(BaseController): 121 122 122 The required standard name for the RootController class of a TurboGears 123 application is ``RootController`` and it should be inherited from 123 ``RootController`` is the required standard name for the RootController class of a TurboGears application and it should be inherited from 124 124 ``BaseController`` class. It is thereby specified as the request handler class 125 125 for the website's root. … … 129 129 class. 130 130 131 We look at the methods of the ``Root`` class next::131 :: 132 132 133 133 def index(self): … … 137 137 .. _three urls: 138 138 139 The ``index`` method is the start point of any TurboGears/CherryPy class. When 140 you access a URL like 139 We look at the methods of the ``Root`` class next. 140 141 The ``index`` method is the start point of any TurboGears controller class. When 142 you access a URL like 141 143 142 144 * http://localhost:8080 … … 146 148 they are all mapped to the ``RootController.index()`` method. 147 149 148 If a URL is requested thatdoes not map to a specific method, the150 If a URL is requested and does not map to a specific method, the 149 151 ``default()`` method of the controller class is called:: 150 152 … … 157 159 158 160 As you can see from the examples, the response to a given URL is determined by 159 the method it maps to. 161 the method it maps to. 160 162 161 163 :: … … 163 165 @expose() 164 166 165 The ``@expose()`` seen before each controller method directs TurboGears to make167 The ``@expose()`` seen before each controller method directs TurboGears controllers to make 166 168 the method accessible through the web server. Methods in the controller class 167 169 that are *not* "exposed" can not be called directly by requesting a URL from the … … 171 173 sophisticated rendering features that we will explore shortly. 172 174 173 Are you sure you wanted to ``expose`` that?174 --------------------------------------------- 175 Are you sure you wanted to ``expose`` strings all the time? 176 ------------------------------------------------------------ 175 177 176 178 As shown above, controller methods return the data of your website. So far, we 177 179 have returned this data as literal strings. You could produce a whole site by 178 returning only strings containing raw HTML from your controller methods but it180 returning only strings containing raw HTML from your controller methods, but it 179 181 would be difficult to maintain, since Python code and HTML code would not be 180 182 cleanly separated. … … 207 209 </html> 208 210 209 By adding a method to the controller like this ... 211 The ``${param}`` syntax in template means there's some undetermined values need to be filled. 212 213 We did that by adding a method to the controller like this ... 210 214 211 215 :: 212 216 213 @expose(template=" gs.templates.sample")217 @expose(template="helloworld.templates.sample") 214 218 def example(self): 215 219 mydata = {'person':'Tony Blair','office':'President'} … … 226 230 * The web user sees a marked up page saying: 227 231 228 **I just want to say that Tony Blair should be the next President 229 of the United States.** 232 The result is:: 233 234 **I just want to say that Tony Blair should be the next President of the United States.** 230 235 231 236 Template files can thus house all markup information, maintaining clean 232 237 separation from controller code. 233 238 234 Passing Arguments to the Controller235 ---------------------------------------236 237 HTTP get request will have the query parameters turned into a dictionary,238 which is then turned into keyword arguments passed into your controller239 methods. Likewise HTTP POST requests will have the form arguments turned240 into a dictionary which is similarly turned into parameter values241 passed into your controller.242 243 239 SubControllers and the URL Hierarcy 244 240 ----------------------------------- … … 250 246 251 247 To make a sub-controller, all you need to do is make your sub-controller 252 inherit from the object class. However there's a SubController class in 253 lib.base for you to use if you want a central place to add helper methods 254 or other functionality to your SubControllers:: 255 256 from lib.base import BaseController, SubController 248 inherit from the object class. However there's a SubController class ``Controller`` in 249 your project's lib.base (HelloWorld/helloworld/lib/base.py) for you to use if you want a central place to add helper methods or other functionality to your SubControllers:: 250 251 from lib.base import BaseController, Controller 257 252 from tg import redirect 258 253 259 class MovieController(SubController): 254 class MovieController(Controller): 255 @expose() 260 256 def index(self): 261 257 redirect('list/') 262 258 259 @expose() 263 260 def list(self): 264 261 return 'hello' … … 267 264 movie = MovieController() 268 265 269 Once you've done this you can go to:266 Once you've done, you can follow the link: 270 267 271 268 * http://localhost:8080/movie/ … … 276 273 * http://localhost:8080/movie/list/ 277 274 278 Unlike turbogears 1 going to http://localhost:8080/movie **will not** redirect275 Unlike turbogears 1, going to http://localhost:8080/movie **will not** redirect 279 276 you to http://localhost:8080/movie/list. This is due to some interesting bit 280 277 about the way WSGI works. But it's also the right thing to do from the … … 291 288 exactly where you wanted to go, no matter where you came from. 292 289 290 Passing Arguments to the Controller 291 --------------------------------------- 292 293 HTTP GET request will have the query parameters turned into a dictionary, 294 which is then turned into keyword arguments passed into your controller 295 methods. Likewise HTTP POST requests will have the form arguments turned 296 into a dictionary which is similarly turned into parameter values 297 passed into your controller. 298 299 When you got the parameters, those parameters are in plain string format. 300 You should translate those plain strings to some useful format(type) for further process. 301 TurboGears helps you to translate and validate those parameters by ``validate`` module and widget framework. But it's the another topic. 302 293 303 294 304 What's new in TG2 … … 296 306 297 307 Here are the major differences in dispatch between CherryPy/Turbogears1 298 and TurboGears 2.308 and TurboGears 2. 299 309 300 310 * We have not yet implemented cherrypy's mechanism that replaces dots in the … … 307 317 * Redirect does not know "where you are" in the object tree and move you on 308 318 from there, it just joins the URL the user requested, with the absolute 309 or relative URL you provide. Using abosolute URLs is recom ended.319 or relative URL you provide. Using abosolute URLs is recommended. 310 320 311 321 The new TG2 Lookup Method 312 322 -------------------------- 313 323 314 Lookup and defaultare called in identical situations: when "normal"324 ``Lookup`` and ``default`` are called in identical situations: when "normal" 315 325 object traversal is not able to find an exposed method, it begins 316 326 popping the stack of "not found" handlers. If the handler is a … … 363 373 editing hierarchical data (/client/1/project/2/task/3/edit). 364 374 365 The benefit over "default" handlers is that you _return_an object that acts366 as a sub-controller and continue traversing rather than _being_a controller375 The benefit over "default" handlers is that you *return* an object that acts 376 as a sub-controller and continue traversing rather than *being* a controller 367 377 and stopping traversal altogether. This allows you to use actual objects with 368 378 datain your controllers. trunk/docs/2.0/QuickStart.rst
r4575 r4586 30 30 Let's go in there and you can take a look around:: 31 31 32 $ cd helloworld32 $ cd HelloWorld 33 33 34 34 trunk/docs/2.0/SQLAlchemy.rst
r4396 r4586 75 75 >>> dir(types) 76 76 77 Data Types 78 ~~~~~~~~~~~ 79 77 80 main types are: 78 81 … … 92 95 93 96 Properties 94 ----------- 97 ~~~~~~~~~~~ 98 99 While you define the Columns, you could specify several properties to control the column's behaviors. 95 100 96 101 ============ ========== … … 105 110 --------------------------------- 106 111 107 Once you've got a table, such as the movie_table we're using in this example you can create a Movie class to support a more object oriented way of looking atyour data::112 Once you've got a table, such as the movie_table we're using in this example, you can create a Movie class to support a more object oriented way of manipulating your data:: 108 113 109 114 class Movie(object): … … 112 117 self.year = year 113 118 self.description = description 114 119 115 120 def __repr__(self): 116 121 return "<Movie('%s','%s', '%s')>" % (self.title, self.year, self.description) 117 122 118 123 119 If you're following along with the tuturial, you'll want to make sure you custom __init__ method. We'll use this to creae new Movie instances, and set their data all at once througout the rest of the tutorial. 120 121 122 If you don't define the __init__ method. You will need to update the properties of a movie object after it's been created like this:: 124 If you don't define the __init__ method. You will need to update the properties of a movie object after it's been created. like this:: 123 125 124 126 >>> entry = Movie() … … 127 129 >>> entry.description = 'vampire movie' 128 130 129 But if the __init__ method we defined allows you to initialize the properties at the same time you create the object:: 131 If you're following along with the tuturial, you'll want to make sure that you've defined the __init__ method. We'll use the Movie class to creae new Movie instances, and set their data all at once througout the rest of the tutorial. 132 133 If you defined the __init__ method, it allows you to initialize the properties at the same time while you create the object:: 130 134 131 135 >>> entry = Movie(title='Dracula', year='1931', description='vampire movie') … … 135 139 >>> entry = Movie('Dracula', '1931', 'vampire movie') 136 140 141 It looks better. 142 143 137 144 Quick database creation 138 145 -------------------------- 139 146 140 Once you've got your database table objects defined (and imported into __init__.py if you didn't define them there), you can create the tables in the database with one simple command, just run::147 Once you've got your database table objects defined (and imported into __init__.py if you didn't define your model in __init__.py), you can create the tables in the database with one simple command, just run:: 141 148 142 149 paster setup-app development.ini … … 144 151 from within your project's home directory. 145 152 146 Pylons defines a setup-app function that paster will connect to the database and create all the tables we've defined.153 Pylons (The TurboGears 2 underground framework) defines a setup-app function that paster will connect to the database and create all the tables we've defined. 147 154 148 The re is a default database setup defined in development.ini. So if you just run this it will create a single-file database in your project directory called devdata.db. If you change your data model, delete this and rerun the setup-app command.155 The default database setup configurations are defined in development.ini. So if you just run the script without modification of development.ini, the script will create a single-file database, which called 'devdata.db', in your project directory. If you change your data model and want to apply the new database, go delete 'devdata.db' and run the 'paster setup-app' command again. 149 156 150 TurboGears 2 does support database migrations. But that's another tutorial.157 TurboGears 2 does support database migrations. But that's another tutorial. 151 158 152 159 Reference: