[FIX] doc: typos and code samples from howtos
[odoo/odoo.git] / doc / howtos / website.rst
1 .. queue:: website/series
2
3 ==================
4 Building a Website
5 ==================
6
7 .. warning::
8
9     * This guide assumes `basic knowledge of Python
10       <http://docs.python.org/2/tutorial/>`_
11     * This guide assumes an installed Odoo
12
13 Creating a basic module
14 =======================
15
16 In Odoo, tasks are performed by creating modules.
17
18 Modules customize the behavior of an Odoo installation, either by adding new
19 behaviors or by altering existing ones (including behaviors added by other
20 modules).
21
22 First let's create a *module directory* which will contain a single module in
23 our case but may store multiple related (a project's) or not really related
24 (a company's) modules:
25
26 .. code-block:: console
27
28     $ mkdir my-modules
29
30 then let's create the module's own directory:
31
32 .. code-block:: console
33
34     $ mkdir my-modules/academy
35
36 An Odoo module is a valid `Python package
37 <http://docs.python.org/2/tutorial/modules.html#packages>`_ so it needs an
38 empty ``__init__.py`` file.
39
40 Finally the mark of an Odoo module is the
41 :ref:`manifest file <reference/module/manifest>`, a Python dictionary describing
42 various module metadata.
43
44 .. patch::
45
46 A demonstration module
47 ======================
48
49 We have a "complete" module ready for installation.
50
51 Although it does absolutely nothing yet we can install it:
52
53 * start the Odoo server
54
55     .. code-block:: console
56
57         $ ./odoo.py --addons-path addons,my-modules
58
59 * go to http://localhost:8069
60 * create a new database including demonstration data
61 * to go :menuselection:`Settings --> Modules --> Installed Modules`
62 * in the top-right corner remove the *Installed* filter and search for
63   *academy*
64 * click the :guilabel:`Install` button for the *Academy* module
65
66 .. seealso::
67
68     * In a production development setting, modules should generally be created
69       using :ref:`Odoo's scaffolding <reference/cmdline/scaffold>` rather than by
70       hand
71
72 To the browser
73 ==============
74
75 :ref:`Controllers <reference/http/controllers>` interpret browser requests and
76 send data back.
77
78 Add a simple controller and import it (so Odoo can find it):
79
80 .. patch::
81
82 Shut down your server (:kbd:`^C`) then restart it:
83
84 .. code-block:: console
85
86     $ ./odoo.py --addons-path addons,my-modules
87
88 and open a page to http://localhost:8069/academy/, you should see your "page"
89 appear:
90
91 .. figure:: website/helloworld.png
92
93 Templates
94 =========
95
96 Generating HTML in Python isn't very pleasant.
97
98 The usual solution is templates_, pseudo-documents with placeholders and
99 display logic. Odoo allows any Python templating system, but provides its
100 own :ref:`QWeb <reference/qweb>` templating system which integrates with other
101 Odoo features.
102
103 Let's create an XML file for our first template, register the template in the
104 manifest and alter the controller to use our template:
105
106 .. patch::
107
108 The templates iterates (``t-foreach``) on all the teachers (passed through the
109 *template context*), and prints each teacher in its own paragraph.
110
111 Finally restart Odoo and update the module's data (to install the template)
112 by going to :menuselection:`Settings --> Modules --> Installed Modules -->
113 Academy` and clicking :guilabel:`Upgrade`.
114
115 .. tip::
116
117     Alternatively, Odoo can be restarted :option:`and update modules at
118     the same time<odoo.py -u>`:
119
120     .. code-block:: console
121
122         $ odoo.py --addons-path addons,my-modules -d academy -u academy
123
124 Going to http://localhost:8069/academy/ should now result in:
125
126 .. image:: website/basic-list.png
127
128 Storing data in Odoo
129 ====================
130
131 :ref:`Odoo models <reference/orm/model>` map to database tables.
132
133 In the previous section we just displayed a list of string entered statically
134 in the Python code. This doesn't allow modifications and persistent storage
135 thereof, so we're now going to move our data to the database.
136
137 Defining the data model
138 -----------------------
139
140 First define an Odoo model file and import it:
141
142 .. patch::
143
144 Then setup :ref:`basic access control <reference/security/acl>` for the model
145 and add them to the manifest:
146
147 .. patch::
148
149 this simply gives read access (``perm_read``) to all users (``group_id:id``
150 left empty).
151
152 .. note::
153
154     :ref:`Data files <reference/data>` (XML or CSV) have to be added to the
155     module manifest, Python files (models or controllers) don't but have to
156     be imported from ``__init__.py`` (directly or indirectly)
157
158 .. warning::
159
160     the administrator user bypasses access control, he has access to all
161     models even if not given access
162
163 Demonstration data
164 ------------------
165
166 The second step is to add some demonstration data to the system so it's
167 possible to test it easily. This is done by adding a ``demo``
168 :ref:`data file <reference/data>` to the manifest:
169
170 .. patch::
171
172 .. tip::
173
174     :ref:`Data files <reference/data>` can be used for demo and non-demo data.
175     Demo data are only loaded in "demonstration mode" and can be used for flow
176     testing and demonstration, non-demo data are always loaded and used as
177     initial system setup.
178
179     In this case we're using demonstration data because an actual user of the
180     system would want to input or import their own teachers list, this list
181     is only useful for testing.
182
183 Accessing the data
184 ------------------
185
186 The last step is to alter model and template to use our demonstration data:
187
188 #. fetch the records from the database instead of having a static list
189 #. Because :meth:`~openerp.models.Model.search` returns a set of records
190    matching the filter ("all records" here), alter the template to print each
191    teacher's ``name``
192
193 .. patch::
194
195 Restart the server and update the module (in order to update the manifest
196 and templates and load the demo file) then navigate to
197 http://localhost:8069/academy/. The page should look little different: names
198 should simply be prefixed by a number (the database identifier for the
199 teacher).
200
201 Website support
202 ===============
203
204 Odoo bundles a module dedicated to building websites.
205
206 So far we've used controllers fairly directly, but Odoo 8 added deeper
207 integration and a few other services (e.g. default styling, theming) via the
208 ``website`` module.
209
210 #. first, add ``website`` as a dependency to ``academy``
211 #. then add the ``website=True`` flag on the controller, this sets up a few
212    new variables on :ref:`the request object <reference/http/request>` and
213    allows using the website layout in our template
214 #. use the website layout in the template
215
216 .. patch::
217
218 After restarting the server while updating the module (in order to update the
219 manifest and template) access http://localhost:8069/academy/ should yield a
220 nicer looking page with branding and a number of built-in page elements
221 (top-level menu, footer, …)
222
223 .. image:: website/layout.png
224
225 The website layout also provides support for edition tools: click
226 :guilabel:`Sign In` (in the top-right), fill the credentials in (``admin`` /
227 ``admin`` by default) then click :guilabel:`Log In`.
228
229 You're now in Odoo "proper": the administrative interface. For now click on
230 the :guilabel:`Website` menu item (top-left corner.
231
232 We're back in the website but as an administrator, with access to advanced
233 edition features provided by the *website* support:
234
235 * a template code editor (:menuselection:`Customize --> HTML Editor`) where
236   you can see and edit all templates used for the current page
237 * the :guilabel:`Edit` button in the top-left switches to "edition mode" where
238   blocks (snippets) and rich text edition are available
239 * a number of other features such as mobile preview or :abbr:`SEO (Search
240   Engine Optimization)`
241
242 URLs and routing
243 ================
244
245 Controller methods are associated with *routes* via the
246 :func:`~openerp.http.route` decorator which takes a routing string and a
247 number of attributes to customise its behavior or security.
248
249 We've seen a "literal" routing string, which matches a URL section exactly,
250 but routing strings can also use `converter patterns`_ which match bits
251 of URLs and make those available as local variables. For instance we can
252 create a new controller method which takes a bit of URL and prints it out:
253
254 .. patch::
255
256 restart Odoo, access http://localhost:8069/academy/Alice/ and
257 http://localhost:8069/academy/Bob/ and see the difference.
258
259 As the name indicates, `converter patterns`_ don't just do extraction, they
260 also do *validation* and *conversion*, so we can change the new controller
261 to only accept integers:
262
263 .. patch::
264
265 Restart Odoo, access http://localhost:8069/academy/2, note how the old value
266 was a string, but the new one was converted to an integers. Try accessing
267 http://localhost:8069/academy/Carol/ and note that the page was not found:
268 since "Carol" is not an integer, the route was ignored and no route could be
269 found.
270
271 Odoo provides an additional converter called ``model`` which provides records
272 directly when given their id, let's use that and create a generic page for
273 teacher biographies:
274
275 .. patch::
276
277 then change the list of model to link to our new controller:
278
279 .. patch::
280
281 Restart Odoo and upgrade the module, then you can visit each teacher's page.
282 As an exercise, try adding blocks to a teacher's page to write a biography,
283 then go to another teacher's page and so forth. You will discover, that your
284 biography is shared between all teachers, because blocks are added to the
285 *template*, and the *biography* template is shared between all teachers, when
286 one page is edited they're all edited at the same time.
287
288 Field edition
289 =============
290
291 Data which is specific to a record should be saved on that record, so let us
292 add a new biography field to our teachers:
293
294 .. patch::
295
296 Restart Odoo and update the views, reload the teacher's page and… the field
297 is invisible since it contains nothing.
298
299 .. todo:: the view has been set to noupdate because modified previously,
300           force via ``-i`` or do something else?
301
302 For record fields, templates can use a special ``t-field`` directive which
303 allows editing the field content from the website using field-specific
304 interfaces. Change the *person* template to use ``t-field``:
305
306 .. patch::
307
308 Restart Odoo and upgrade the module, there is now a placeholder under the
309 teacher's name and a new zone for blocks in :guilabel:`Edit` mode. Content
310 dropped there is stored in the corresponding teacher's ``biography`` field, and
311 thus specific to that teacher.
312
313 The teacher's name is also editable, and when saved the change is visible on
314 the index page.
315
316 ``t-field`` can also take formatting options which depend on the exact field.
317 For instance if we display the modification date for a teacher's record:
318
319 .. patch::
320
321 it is displayed in a very "computery" manner and hard to read, but we could
322 ask for a human-readable version:
323
324 .. patch::
325
326 or a relative display:
327
328 .. patch::
329
330 Administration and ERP integration
331 ==================================
332
333 A brief and incomplete introduction to the Odoo administration
334 --------------------------------------------------------------
335
336 The Odoo administration was briefly seen during the `website support` section.
337 We can go back to it using :menuselection:`Administrator --> Administrator` in
338 the menu (or :guilabel:`Sign In` if you're signed out).
339
340 The conceptual structure of the Odoo backend is simple:
341
342 #. first are menus, a tree (menus can have sub-menus) of records. Menus
343    without children map to…
344 #. actions. Actions have various types: links, reports, code which Odoo should
345    execute or data display. Data display actions are called *window actions*,
346    and tell Odoo to display a given *model* according to a set of views…
347 #. a view has a type, a broad category to which it corresponds (a list,
348    a graph, a calendar) and an *architecture* which customises the way the
349    model is displayed inside the view.
350
351 Editing in the Odoo administration
352 ----------------------------------
353
354 By default, an Odoo model is essentially invisible to a user. To make it
355 visible it must be available through an action, which itself needs to be
356 reachable, generally through a menu.
357
358 Let's create a menu for our model:
359
360 .. patch::
361
362 then accessing http://localhost:8069/web/ in the top left should be a menu
363 :guilabel:`Academy`, which is selected by default, as it is the first menu,
364 and having opened a listing of teachers. From the listing it is possible to
365 :guilabel:`Create` new teacher records, and to switch to the "form" by-record
366 view.
367
368 If there is no definition of how to present records (a
369 :ref:`view <reference/views>`) Odoo will automatically create a basic one
370 on-the-fly. In our case it works for the "list" view for now (only displays
371 the teacher's name) but in the "form" view the HTML ``biography`` field is
372 displayed side-by-side with the ``name`` field and not given enough space.
373 Let's define a custom form view to make viewing and editing teacher records
374 a better experience:
375
376 .. patch::
377
378 Relations between models
379 ------------------------
380
381 We have seen a pair of "basic" fields stored directly in the record. There are
382 :ref:`a number of basic fields <reference/orm/fields/basic>`. The second
383 broad categories of fields are :ref:`relational
384 <reference/orm/fields/relational>` and used to link records to one another
385 (within a model or across models).
386
387 For demonstration, let's create a *courses* model. Each course should have a
388 ``teacher`` field, linking to a single teacher record, but each teacher can
389 teach many courses:
390
391 .. patch::
392
393 let's also add views so we can see and edit a course's teacher:
394
395 .. patch::
396
397 It should also be possible to create new courses directly from a teacher's
398 page, or to see all the courses a teacher gives, so add
399 :class:`the inverse relationship <openerp.fields.One2many` to the *teachers*
400 model:
401
402 .. patch::
403
404 Discussions and notifications
405 -----------------------------
406
407 Odoo provides technical models, which don't fulfill business needs in and of
408 themselves but add capabilities to business objects without having to build
409 them by hand.
410
411 One of these is the *Chatter* system, part of Odoo's email and messaging
412 system, which can add notifications and discussion threads to any model.
413 The model simply has to :attr:`~openerp.models.Model._inherit`
414 ``mail.thread``, and add the ``message_ids`` field to its form view to display
415 the discussion thread. Discussion threads are per-record.
416
417 For our academy, it makes sense to allow discussing courses to handle e.g.
418 scheduling changes or discussions between teachers and assistants:
419
420 .. patch::
421
422 At the bottom of each course form, there is now a discussion thread and the
423 possibility for users of the system to leave messages and follow or unfollow
424 discussions linked to specific courses.
425
426 Selling courses
427 ---------------
428
429 Odoo also provides business models which allow using or opting in business
430 needs more directly. For instance the ``website_sale`` module sets up an
431 e-commerce site based on the products in the Odoo system. We can easily make
432 course subscriptions sellable by making our courses specific kinds of
433 products.
434
435 Rather than the previous classical inheritance, this means replacing our
436 *course* model by the *product* model, and extending products in-place (to
437 add anything we need to it).
438
439 First of all we need to add a dependency on ``website_sale`` so we get both
440 products (via ``sale``) and the ecommerce interface:
441
442 .. patch::
443
444 restart Odoo, update your module, there is now a :guilabel:`Shop` section in
445 the website, listing a number of pre-filled (via demonstration data) products.
446
447 The second step is to replace the *courses* model by ``product.template``,
448 and add a new category of product for courses:
449
450 .. patch::
451
452 With this installed, a few courses are now available in the :guilabel:`Shop`,
453 though they may have to be looked for.
454
455 .. note::
456
457     * to extend a model in-place, it's :attr:`inherited
458       <openerp.models.Model._inherit>` without giving it a new
459       :attr:`~openerp.models.Model._name`
460     * ``product.template`` already uses the discussions system, so we can
461       remove it from our extension model
462     * we're creating our courses as *published* by default so they can be
463       seen without having to log in
464
465 Altering existing views
466 -----------------------
467
468 So far, we have briefly seen:
469
470 * the creation of new models
471 * the creation of new views
472 * the creation of new records
473 * the alteration of existing models
474
475 We're left with the alteration of existing records and the alteration of
476 existing views. We'll do both on the :guilabel:`Shop` pages.
477
478 View alteration is done by creating *extension* views, which are applied on
479 top of the original view and alter it. These alteration views can be added or
480 removed without modifying the original, making it easier to try things out and
481 roll changes back.
482
483 Since our courses are free, there is no reason to display their price on the
484 shop page, so we're going to alter the view and hide the price if it's 0. The
485 first task is finding out which view displays the price, this can be done via
486 :menuselection:`Customize --> HTML Editor` which lets us read the various
487 templates involved in rendering a page. Going through a few of them, "Product
488 item" looks a likely culprit.
489
490 Altering view architectures is done in 3 steps:
491
492 #. Create a new view
493 #. Extend the view to modify by setting the new view's ``inherit_id`` to the
494    modified view's external id
495 #. In the architecture, use the ``xpath`` tag to select and alter elements
496    from the modified view
497
498 .. patch::
499
500 The second thing we will change is making the product categories sidebar
501 visible by default: :menuselection:`Customize --> Product Categories` lets
502 you toggle a tree of product categories (used to filter the main display) on
503 and off.
504
505 This is done via the ``customize_show`` and ``active`` fields of extension
506 templates: an extension template (such as the one we've just created) can be
507 *customize_show=True*. This choice will display the view in the :guilabel:`Customize`
508 menu with a check box, allowing administrators to activate or disable them
509 (and easily customize their website pages).
510
511 We simply need to modify the *Product Categories* record and set its default
512 to *active="True"*:
513
514 .. patch::
515
516 With this, the *Product Categories* sidebar will automatically be enabled when
517 the *Academy* module is installed.
518
519 .. _templates: http://en.wikipedia.org/wiki/Web_template
520 .. _postgres:
521 .. _postgresql:
522     http://www.postgresql.org
523 .. _converter pattern:
524 .. _converter patterns:
525     http://werkzeug.pocoo.org/docs/routing/#rule-format