[ADD] tutorial beginning
authorXavier Morel <xmo@openerp.com>
Mon, 20 Jan 2014 13:13:10 +0000 (14:13 +0100)
committerXavier Morel <xmo@openerp.com>
Mon, 19 May 2014 06:23:13 +0000 (08:23 +0200)
blocked at introducing qweb template, ir.qweb lives in the registry but nodb -> no database
with --db-filter there's a database in the session (kinda) but need to fetch it and manually get the corresponding registry...

doc/conf.py
doc/howto/howto_website.rst [new file with mode: 0644]
doc/howto/howto_website/basic-controller [new file with mode: 0644]
doc/howto/howto_website/basic-page [new file with mode: 0644]
doc/howto/howto_website/manifest [new file with mode: 0644]
doc/howto/howto_website/module-init [new file with mode: 0644]
doc/howto/howto_website/series [new file with mode: 0644]
doc/howto/howto_website/ta-controller [new file with mode: 0644]
doc/howto/howto_website/templates-basic [new file with mode: 0644]
doc/howto/howto_website/url-pattern [new file with mode: 0644]
doc/index.rst

index 19f2c9b..051fcde 100644 (file)
@@ -28,7 +28,7 @@ sys.path.append(os.path.abspath('../openerp'))
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode']
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode', 'patchqueue']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst
new file mode 100644 (file)
index 0000000..69486d7
--- /dev/null
@@ -0,0 +1,142 @@
+===================================
+Howto: build a website with OpenERP
+===================================
+
+.. queue:: howto_website/series
+
+.. warning::
+
+   This guide assumes `basic knowledge of python
+   <http://docs.python.org/2/tutorial/>`_.
+
+   This guide assumes :ref:`an OpenERP installed and ready for
+   development <getting_started_installation_source-link>`.
+
+   For production deployment, see the dedicated guides
+   :ref:`using-gunicorn` and :ref:`using-mod-wsgi`.
+
+Minimal website module
+======================
+
+Hello, world!
+-------------
+
+In OpenERP, doing things takes the form of creating modules, and these
+modules customize the behavior of the OpenERP installation. The first
+step is thus to create a module:
+
+.. todo:: code generator in oe?
+
+    * Create empty module (mandatory name, category)
+    * Create controller (parent class?)
+    * Create model (concrete/abstract? Inherit?)
+    * Add field?
+
+* Create a new folder called :file:`academy` in a module directory,
+  inside it create an empty file called :file:`__openerp__.py` with
+  the following content:
+
+  .. patch::
+
+* Create a second file :file:`controllers.py`. This is where the code
+  interacting directly with your web browser will live. For starters,
+  just include the following in it:
+
+  .. patch::
+
+* Finally, create a third file :file:`__init__.py` containing just:
+
+  .. patch::
+
+  This makes :file:`controllers.py` "visible" to openerp (by running
+  the code it holds).
+
+.. todo::
+
+   * instructions for start & install
+   * db handling
+     - if existing db, automatically selected
+     - if no existing db, nodb -> login -> login of first db
+     - dbfilter
+
+Now start your OpenERP server and install your module in it, open a
+web browser and navigate to http://localhost:8069. A page should
+appear with just the words "Hello, world!" on it.
+
+The default response type is HTML (although we only sent some text,
+browsers are pretty good at finding ways to turn stuff into things
+they can display). Let's prettify things a bit: instead of returning
+just a bit of text, we can return a page, and use a tool/library like
+bootstrap_ to get a nicer rendering than the default.
+
+Change the string returned by the ``index`` method to get a more page-ish
+output:
+
+.. patch::
+
+.. note::
+
+   this example requires internet access at all time, as we're
+   accessing a :abbr:`CDN (Content Delivery Network, large distributed
+   networks hosting static files and trying to provide
+   high-performance and high-availability of these files)`-hosted
+   file.
+
+Data input: URL and query
+-------------------------
+
+Being able to build a static page in code is nice, but makes for limited
+usefulness (you could do that with static files in the first place, after all).
+
+But you can also create controllers which use data provided in the access URL,
+for instance so you have a single controller generating multiple pages. Any
+query parameter (``?name=value``) is passed as a parameter to the controller
+function, and is a string.
+
+.. patch::
+
+No validation is performed on query input values, it could be missing
+altogether (if a user accesses ``/tas/`` directly) or it could be incorrectly
+formatted. For this reason, query parameters are generally used to provide
+"options" to a given page, and "required" data tends (when possible) to be
+inserted directly in the URL.
+
+This can be done by adding `converter patterns`_ to the URL in ``@http.route``:
+
+.. patch::
+
+These patterns can perform conversions directly (in this case the conversion
+from a string URL section to a python integer) and will perform a some
+validation (if the ``id`` is not a valid integer, the converter will return
+a ``404 Not Found`` instead of generating a server error when the conversion
+fails).
+
+Templating: better experience in editing
+----------------------------------------
+
+So far we've created HTML output by munging together Python strings using
+string concatenation and formatting. It works, but is not exactly fun to edit
+(and somewhat unsafe to boot) as even advanced text editors have a hard time
+understanding they're dealing with HTML embedded in Python code.
+
+The usual solution is to use templates_, documents with placeholders which
+can be "rendered" to produce final pages (or others). OpenERP lets you use
+any Python templating system you want, but bundles its own
+:doc:`QWeb </06_ir_qweb>` templating system which we'll later see offers
+some useful features.
+
+Let's move our 2 pseudo-templates from inline strings to actual templates:
+
+.. patch::
+
+.. FIXME how can I access a QWeb template from a auth=none controller?
+         explicitly fetch a registry using request.session.db? That's a bit
+         horrendous now innit?
+
+.. todo:: reload/update of module?
+
+.. _bootstrap: http://getbootstrap.com
+
+.. _converter patterns: http://werkzeug.pocoo.org/docs/routing/#rule-format
+
+.. _templates: http://en.wikipedia.org/wiki/Web_template
diff --git a/doc/howto/howto_website/basic-controller b/doc/howto/howto_website/basic-controller
new file mode 100644 (file)
index 0000000..4415d95
--- /dev/null
@@ -0,0 +1,15 @@
+# HG changeset patch
+# Parent 458a542843918f6899fe64bfe1cead00972ef68a
+
+diff --git a/controllers.py b/controllers.py
+new file mode 100644
+--- /dev/null
++++ b/controllers.py
+@@ -0,0 +1,7 @@
++from openerp import http
++from openerp.addons.web.controllers import main
++
++class Home(main.Home):
++    @http.route('/', auth='none')
++    def index(self):
++        return "Hello, world!"
diff --git a/doc/howto/howto_website/basic-page b/doc/howto/howto_website/basic-page
new file mode 100644 (file)
index 0000000..5a60c34
--- /dev/null
@@ -0,0 +1,29 @@
+# HG changeset patch
+# Parent b377930cec8f9445882bb3268f9f5fac71dd8c15
+
+diff --git a/controllers.py b/controllers.py
+--- a/controllers.py
++++ b/controllers.py
+@@ -4,4 +4,21 @@ from openerp.addons.web.controllers impo
+ class Home(main.Home):
+     @http.route('/', auth='none')
+     def index(self):
+-        return "Hello, world!"
++        return """<!doctype html>
++<html>
++    <head>
++        <title>AcademyAcademy</title>
++        <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
++    </head>
++    <body class="container">
++        <h1>Introduction to a thing</h1>
++        <h2>Course description</h2>
++        <p>
++            This course will provide a basic introduction to a thing, for
++            motivated students with no prior experience in things. The course
++            will focus on the discovery of things and the planning and
++            organization necessary to handle things.
++        </p>
++    </body>
++</html>
++"""
diff --git a/doc/howto/howto_website/manifest b/doc/howto/howto_website/manifest
new file mode 100644 (file)
index 0000000..3cf359c
--- /dev/null
@@ -0,0 +1,11 @@
+# HG changeset patch
+# Parent 0000000000000000000000000000000000000000
+diff --git a/__openerp__.py b/__openerp__.py
+new file mode 100644
+--- /dev/null
++++ b/__openerp__.py
+@@ -0,0 +1,4 @@
++{
++    'name': "Academy",
++    'category': "Tools",
++}
diff --git a/doc/howto/howto_website/module-init b/doc/howto/howto_website/module-init
new file mode 100644 (file)
index 0000000..4484236
--- /dev/null
@@ -0,0 +1,8 @@
+# HG changeset patch
+# Parent 2d3441ff4321c4a931940e64fcfb2fe54bd0ad17
+diff --git a/__init__.py b/__init__.py
+new file mode 100644
+--- /dev/null
++++ b/__init__.py
+@@ -0,0 +1,1 @@
++import controllers
diff --git a/doc/howto/howto_website/series b/doc/howto/howto_website/series
new file mode 100644 (file)
index 0000000..4b45d06
--- /dev/null
@@ -0,0 +1,7 @@
+manifest
+basic-controller
+module-init
+basic-page
+ta-controller
+url-pattern
+templates-basic
diff --git a/doc/howto/howto_website/ta-controller b/doc/howto/howto_website/ta-controller
new file mode 100644 (file)
index 0000000..5b8d0b7
--- /dev/null
@@ -0,0 +1,57 @@
+# HG changeset patch
+# Parent 30a859b5dc378c0da751537b1342e8d22775ad44
+
+diff --git a/controllers.py b/controllers.py
+--- a/controllers.py
++++ b/controllers.py
+@@ -1,9 +1,22 @@
+ from openerp import http
+ from openerp.addons.web.controllers import main
++teaching_assistants = [
++    {'name': "Diana Padilla"},
++    {'name': "Jody Carroll"},
++    {'name': "Lester Vaughn"},
++    {'name': "Paul Jimenez"},
++    {'name': "Tanya Harris"},
++]
++
+ class Home(main.Home):
+     @http.route('/', auth='none')
+     def index(self):
++        tas = [
++            '<li><a href="/tas/?id=%d">%s</a></li>' % (i, ta['name'])
++            for i, ta in enumerate(teaching_assistants)
++        ]
++
+         return """<!doctype html>
+ <html>
+     <head>
+@@ -19,6 +32,26 @@ class Home(main.Home):
+             will focus on the discovery of things and the planning and
+             organization necessary to handle things.
+         </p>
++        <h2>Teaching Assistants</h2>
++        <ul>
++            %(tas)s
++        </ul>
+     </body>
+ </html>
+-"""
++""" % {
++        'tas': '\n'.join(tas)
++    }
++
++    @http.route('/tas', auth='none')
++    def ta(self, id):
++        return """<!doctype html>
++<html>
++    <head>
++        <title>AcademyAcademy TA %(name)s</title>
++        <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
++    </head>
++    <body class="container">
++        <h1>%(name)s</h1>
++    </body>
++</html>
++""" % teaching_assistants[int(id)]
diff --git a/doc/howto/howto_website/templates-basic b/doc/howto/howto_website/templates-basic
new file mode 100644 (file)
index 0000000..5f0aefe
--- /dev/null
@@ -0,0 +1,108 @@
+# HG changeset patch
+# Parent 559e3266ed1eeba384445016ffd1438eed54f144
+
+diff --git a/__openerp__.py b/__openerp__.py
+--- a/__openerp__.py
++++ b/__openerp__.py
+@@ -1,4 +1,7 @@
+ {
+     'name': "Academy",
+     'category': "Tools",
++    'data': [
++        'views/templates.xml',
++    ]
+ }
+diff --git a/controllers.py b/controllers.py
+--- a/controllers.py
++++ b/controllers.py
+@@ -17,41 +17,11 @@ class Home(main.Home):
+             for i, ta in enumerate(teaching_assistants)
+         ]
+-        return """<!doctype html>
+-<html>
+-    <head>
+-        <title>AcademyAcademy</title>
+-        <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
+-    </head>
+-    <body class="container">
+-        <h1>Introduction to a thing</h1>
+-        <h2>Course description</h2>
+-        <p>
+-            This course will provide a basic introduction to a thing, for
+-            motivated students with no prior experience in things. The course
+-            will focus on the discovery of things and the planning and
+-            organization necessary to handle things.
+-        </p>
+-        <h2>Teaching Assistants</h2>
+-        <ul>
+-            %(tas)s
+-        </ul>
+-    </body>
+-</html>
+-""" % {
+-        'tas': '\n'.join(tas)
+-    }
++        # how in fuck do I get a db here?
++        return "" % {
++            'tas': '\n'.join(tas)
++        }
+     @http.route('/tas/<int:id>/', auth='none')
+     def ta(self, id):
+-        return """<!doctype html>
+-<html>
+-    <head>
+-        <title>AcademyAcademy TA %(name)s</title>
+-        <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
+-    </head>
+-    <body class="container">
+-        <h1>%(name)s</h1>
+-    </body>
+-</html>
+-""" % teaching_assistants[id]
++        return "" % teaching_assistants[id]
+diff --git a/views/templates.xml b/views/templates.xml
+new file mode 100644
+--- /dev/null
++++ b/views/templates.xml
+@@ -0,0 +1,39 @@
++<openerp>
++    <data>
++<template id="academy.index" name="Index">
++    <html>
++        <head>
++            <title>AcademyAcademy</title>
++            <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"/>
++        </head>
++        <body class="container">
++            <h1>Introduction to a thing</h1>
++            <h2>Course description</h2>
++            <p>
++                This course will provide a basic introduction to a thing, for
++                motivated students with no prior experience in things. The course
++                will focus on the discovery of things and the planning and
++                organization necessary to handle things.
++            </p>
++            <h2>Teaching Assistants</h2>
++            <ul>
++                <t t-raw="tas"/>
++            </ul>
++        </body>
++    </html>
++</template>
++
++<template id="academy.ta" name="Teaching Assistant">
++    <html>
++        <head>
++            <title>AcademyAcademy TA <t t-esc="name"/></title>
++            <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"/>
++        </head>
++        <body class="container">
++            <h1><t t-esc="name"/></h1>
++        </body>
++    </html>
++</template>
++
++    </data>
++</openerp>
diff --git a/doc/howto/howto_website/url-pattern b/doc/howto/howto_website/url-pattern
new file mode 100644 (file)
index 0000000..8f37b1b
--- /dev/null
@@ -0,0 +1,29 @@
+# HG changeset patch
+# Parent a436864e066f91e51d30cc47f03fc42401c4296a
+diff --git a/controllers.py b/controllers.py
+--- a/controllers.py
++++ b/controllers.py
+@@ -13,7 +13,7 @@ class Home(main.Home):
+     @http.route('/', auth='none')
+     def index(self):
+         tas = [
+-            '<li><a href="/tas/?id=%d">%s</a></li>' % (i, ta['name'])
++            '<li><a href="/tas/%d/">%s</a></li>' % (i, ta['name'])
+             for i, ta in enumerate(teaching_assistants)
+         ]
+@@ -42,7 +42,7 @@ class Home(main.Home):
+         'tas': '\n'.join(tas)
+     }
+-    @http.route('/tas', auth='none')
++    @http.route('/tas/<int:id>/', auth='none')
+     def ta(self, id):
+         return """<!doctype html>
+ <html>
+@@ -54,4 +54,4 @@ class Home(main.Home):
+         <h1>%(name)s</h1>
+     </body>
+ </html>
+-""" % teaching_assistants[int(id)]
++""" % teaching_assistants[id]
index 4b988e7..a61de5c 100644 (file)
@@ -4,6 +4,14 @@
 OpenERP Server Developers Documentation
 ========================================
 
+Howto
+'''''
+
+.. toctree::
+    :maxdepth: 1
+
+    howto/howto_website
+
 OpenERP Server
 ''''''''''''''