|
1 .. -*- coding: utf-8 -*- |
|
2 |
|
3 ============= |
|
4 LAX Tutorial |
|
5 ============= |
|
6 |
|
7 Introduction |
|
8 ------------ |
|
9 |
|
10 LAX is a web framework on top of the Google AppEngine datastore. |
|
11 |
|
12 |
|
13 features: schema/data-model at core of app, selection/view mechanism, |
|
14 reuseable components, very fast development |
|
15 |
|
16 |
|
17 Since we are french, let us develop an example application that deals |
|
18 with wine and will allow any wine enthusiast to track the content of |
|
19 its cellar and share his tasting experiences. |
|
20 |
|
21 Schema |
|
22 ------ |
|
23 |
|
24 With LAX, the core of the application is the schema/datamodel. |
|
25 |
|
26 laxctl newapp ? XXX |
|
27 |
|
28 We will start by something simple and define three entities: WineMaker, |
|
29 Wine and Bottle. |
|
30 |
|
31 :: |
|
32 |
|
33 class WineMaker(EntityType): |
|
34 name = String(maxsize=50, required=True) |
|
35 |
|
36 class Wine(EntityType): |
|
37 name = String(required=True, maxsize=100, fulltextindexed=True) |
|
38 vintage = Int(required=True, constraints=[IntervalBoundConstraint(1850,2100)]) |
|
39 grown_by = SubjectRelation('WineMaker', cardinality='?*', |
|
40 description=_('Winemaker who grew the wine')) |
|
41 |
|
42 class Bottle(EntityType): |
|
43 buy_date = Date(description=_('Date when the bottle was bought.'), |
|
44 default='TODAY') |
|
45 bottle_of = SubjectRelation('Wine', cardinality='?*') |
|
46 |
|
47 A WineMaker only has a name which is a string that is required and |
|
48 must be less than 50 characters. |
|
49 |
|
50 A Wine has a name, which is a string that is required, must be less |
|
51 than 100 characters and will be indexed in the full-text index XXX |
|
52 fulltextindex marche pas encore. A Wine |
|
53 also has a vintage year which is an integer that is required and must |
|
54 be between 1850 and 2100. A Wine also has a relationship ``grown_by`` |
|
55 that link it to a WineMaker. Cardinality ``?*`` means that a Wine can |
|
56 have zero or one WineMaker (``?`` means `zero or one`) and that a |
|
57 WineMaker can have any number of Wine entities (``*`` means `any number |
|
58 including zero`). |
|
59 |
|
60 A Bottle has a buy_date attribute, which is a date with a default |
|
61 value of TODAY, meaning that when a new bottle is created, it will |
|
62 have its creation date as buy_date unless the user changes it to some |
|
63 other date. A Bottle also has a relationship ``bottle_of`` that link |
|
64 it to a Wine. The cardinality of that relationship implies that a |
|
65 Bottle can be linked to zero or one Wine and that a Wine can by linked |
|
66 to any number of Bottle entities. |
|
67 |
|
68 |
|
69 Defining this simple schema is enough to get us started, launch the |
|
70 application with the command:: |
|
71 |
|
72 laxctl start Winopedia |
|
73 |
|
74 and point your browser at localhost:8080 |
|
75 |
|
76 You will see the home page of your application. It lists the entity |
|
77 types: WineMaker, Wine, Bottle. |
|
78 |
|
79 Let us create a few of these. Click on the [+] at the right of the |
|
80 link WineMaker. Call this new WineMaker ``Domaine du château`` and |
|
81 validate the form by clicking on ``button_ok``. |
|
82 |
|
83 Click on the logo at top left to get back to the home page, then |
|
84 follow the WineMaker link. You should be seeing a list with a single |
|
85 item ``Domaine du château``. Clicking on this item will get you to |
|
86 its detailed description except that in this case, there is not much |
|
87 to display besides the name. |
|
88 |
|
89 Now get back to the home page by clicking on the top-left logo, then |
|
90 create a new WineMaker called ``Vallon de la Dame`` and get back to the |
|
91 home page again to follow the WineMaker link for the second time. The |
|
92 list now has two items. |
|
93 |
|
94 Get back to the home page and click on [+] at the right of the link |
|
95 Wine. Call this new wine ``Cuvée du Roi`` and enter 2008 as vintage, |
|
96 then click on ``button_ok``. You added a new wine without saying who |
|
97 made it. There is a box on the left entitled "actions", click on the |
|
98 menu item `modify`. You are back to the form to edit the wine entity |
|
99 you just created, except that the form now has another section with a |
|
100 combobox titled "add a relationship". Chose "grown_by" in this |
|
101 menu and a second combobox appears where you pick ``Domaine du |
|
102 château``. Validate the changes by clicking ``button_ok``. The entity |
|
103 Wine that is displayed now includes a link to the entity WineMaker |
|
104 named ``Domaine du château``. |
|
105 |
|
106 Exercise |
|
107 ~~~~~~~~ |
|
108 |
|
109 Create new entities Wine and Bottle. |
|
110 |
|
111 What we learned |
|
112 ~~~~~~~~~~~~~~~ |
|
113 |
|
114 Creating a simple schema was enough to set up a new application that |
|
115 can store WineMaker, Wine, Bottle. |
|
116 |
|
117 What is next ? |
|
118 -------------- |
|
119 |
|
120 Althought the application is fully functionnal, its look is very |
|
121 basic. We will now improve how information is displayed by writing |
|
122 views. |
|
123 |
|
124 |
|
125 Views |
|
126 ====== |
|
127 |
|
128 ... |
|
129 |
|
130 Defining views with selection/views |
|
131 |
|
132 implementing interfaces, calendar for bottles bought and for tasting. |
|
133 calendar with export icalput attribute drink_date on bottle |
|
134 |
|
135 add attribute wine color |
|
136 |
|
137 create view "bottle table" with color, buy_date, drink_date. |
|
138 |
|
139 in view wine, select Wine.bottles and apply view "bottle table" |
|
140 |
|
141 demo ajax with filter on bottle table |
|
142 |
|
143 Components |
|
144 =========== |
|
145 |
|
146 ... |
|
147 |
|
148 |
|
149 |
|
150 customize MainTemplate |
|
151 |
|
152 rss channel of new bottles or wines |
|
153 |
|
154 use URLRewriting for nice urls |
|
155 |
|
156 talk about security access rights |
|
157 |
|
158 talk about rql |