[ADD] tutorial beginning
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...
This commit is contained in:
parent
50c5a23dec
commit
c2d5bf1bc3
|
@ -28,7 +28,7 @@ sys.path.append(os.path.abspath('../openerp'))
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
# 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.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
|
|
|
@ -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
|
|
@ -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!"
|
|
@ -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>
|
||||||
|
+"""
|
|
@ -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",
|
||||||
|
+}
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
||||||
|
manifest
|
||||||
|
basic-controller
|
||||||
|
module-init
|
||||||
|
basic-page
|
||||||
|
ta-controller
|
||||||
|
url-pattern
|
||||||
|
templates-basic
|
|
@ -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)]
|
|
@ -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>
|
|
@ -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]
|
|
@ -4,6 +4,14 @@
|
||||||
OpenERP Server Developers Documentation
|
OpenERP Server Developers Documentation
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
|
Howto
|
||||||
|
'''''
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
howto/howto_website
|
||||||
|
|
||||||
OpenERP Server
|
OpenERP Server
|
||||||
''''''''''''''
|
''''''''''''''
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue