From 50c5a23dec02472bef9fd6fc163079cd1c999619 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 16 May 2014 16:56:18 +0200 Subject: [PATCH 01/41] [ADD] doc files lost during git conversion --- doc/Makefile | 154 +++++++++++++++++++++++++++++++ doc/_static/openerp.png | Bin 0 -> 3981 bytes doc/_templates/sidebarintro.html | 16 ++++ doc/_templates/sidebarlogo.html | 3 + 4 files changed, 173 insertions(+) create mode 100644 doc/Makefile create mode 100644 doc/_static/openerp.png create mode 100644 doc/_templates/sidebarintro.html create mode 100644 doc/_templates/sidebarlogo.html diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000000..c1eff186583 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,154 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -q +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + sed -i '/-99999/d' _build/dirhtml/_static/flasky.css + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenERPTechnicalDocumentation.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenERPTechnicalDocumentation.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/OpenERPTechnicalDocumentation" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenERPTechnicalDocumentation" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/_static/openerp.png b/doc/_static/openerp.png new file mode 100644 index 0000000000000000000000000000000000000000..d6dbd9d83d1f3c3c2568e7ccac4e031e0f5b3806 GIT binary patch literal 3981 zcmd^C_d6So6Q){fYt^b!v(zYRmYOv`)NZZXqm_bg)8jJ-!9MkGOE zBvBz>|Ht>9=kC4x>3!~f?w;o^R$o_xn&L495fKr!mZqxVE%x5}i~A(Ev1HN+c?&GQ zYNozM9!|dgw%(3J$_^fOjvQK_Z9h61I@&sX^%`@0O+-XOq_1PFc64;KDJunjXDI&i zWo2dM+3_)IZuSg`+)`875EF)2n&;=|pG;4gnVA(86_uBldwF@S3p_i7!CG5ej|YGt z5GX1ts<*e7jg2ieHFZltwzRYqqWfP)Muw%OWoT%qjEoFCJ99%saL3l_-Me>cYHBAF z<2^k+r%>pQll>VChC-pv;P8cog^rGnrluwZ1%-x&hOx0R0|SFCWd(9_@}u5A#l^*k z`MEAGF8%%e0s;bSYirwDYNMm0h~HHZv-j}Q;?vz-SV}U~#c5rLAHBYQ@I9K7lhe)3 z?Hr8`2ng8L)&v{qA{*+0gM(q|sVXWeU0q#tbaYTRm;Lb2&CSgX3DM)@<6Tepii!%< z@-qC_Ph?xGpPwIkb7Ma;d~k4ZFW}48*4F94K~7E%ytpthFi=TJY43~gj=-~{?k-75 zNgW*>EiElxUS4EV<38XUyz*CecJ^Liz{%+7#KgqiyLX3%hG3~F2Z?dJ-kzsmFnVR> zFf)Bq>g9fPq>qnJQc}`USLZnrX=i754u|XN>Y}%|Q40&m_BLco6I5IT>gp^cB*etT zl$DhwCnvXK{b6Qi#>2y-zP_G7AjHSVBM^wVxHvo>KQ}iwKR*wL!*_Oe_V@Q!R#vcB zY;A4r&CN|hLc;3m>g43)zkmNQ7)*G0`1$E61Oi!FT8fR0y}Z0!US7Vsx^j1SzrMc4 z;c!z^Q+0K9v$M0iySt}5keZsBEydRd2M5U3mR%1wFc`ccE{cG|&khfv9&QIo2@ng@ zO*t7T6nZ>7bPyl=@A7hfZffQCEwa0il)_VabWdBg2T6 zroR?u$AbgFq(mGRo06Q|_gWTltH$5af`S70&oa!#1$t|9c4h`$S2JL5yCo@x#bC9xd^I&* zX6XOHOL1R@nURT^O__(E<7I49tbvrqBfFFiK|eCJ&kxtK%iktS=JL;Cok*M^JiGAlx<)KI17v%|s3!d@k2GBK*81?%QXW7_LA}5dW8FIrH%8Bjk^lX2_-}SE-Fqyo-aeQbzE^On` zLs^&ibe#626289nd!gO?40c6z2DGWhl@lZbJ5TnrKG!ps7uO{up*&+0U;bjY41m`n zw`eghl>Yi}3itPQz6y2;P+~q$HH=!ss?EJwplv(I0EOGm3t@45NYdZ5-SlMn{xuDD zRjgmXCJ5eG9P%S}NJ~z{SxRbF^5%XW(Pfuq{%BJc-2G8L?o8|Lc7?+68E%f3WyNai z+)@_nvLy70Q$BwoTQnpaY0N9V{>om}r}M!T@{i>6v`AJ>P0auQl z@0l-JjZxGWkYGEd@Kb3n!RN zD<*u!T`v{lugQ?4f8)(^!`X3JXvkJn#1WbLEqYMet#| zU(SpwKriumxez`@%E}g3^k2+$Ly0I$NVTyo)v$>+T7$%O$-@!XY+LE^duE&EN=RNx zPxw?Yu)pLKZyj=zOt@JKIgJPCIptl}1MrJQJWOmo09^M8DWTe1HeF02gmV~_vBN}+ zz$*9ypBntvowcpx%(Y1q15;y+-I65GFKVy1eS4W)=rHQOE)``+aN=6S%(?$!;XL(i zq9RUAk=*_gA>vc0PmwQY&%X_DBR{*Ae28CW3_EccNB(oWv!qQ{VnoE&LUhL!9i;$U z9XzBjdvved|CLI}lmo=!-u=u$n2~Y&3D^ezvvaSrCL@McwF9WQ_r!T~(hihrW47B! zN{Yc^$=u!M?=}?3rvzGs6ADGZ6Z7ey;2{-Ii#+s~5=~GZl1(f*nA$!>2hXMQ%F{Ga zzXCKL0=*6eDCG1?cJ4~36bh0-we$K|@e2dOu`_Kvfl-uNQi~8_+Rnr)3}qWsBxbSs z{TNbLgm?kHy6a7R$?WcYxOQGo-g$CI#i-Kvx5#NZ%Q1H(%@6EBnxMc!d#+m|@3MW= zsAmxF1v-m+aL43BhU2EeLe-vf2+4*|`gE5`v3MZp0~ffcOr=Ari!89d!~nbA9Bu6Z zEc3KHywA`9uFi^kD~~#Tix!mD{w*bqV~|^#aAjvG{@t6tT0m-*(i$_IH>}y{Y)Ru2 zz-+UEYa(xqk`j!i-L;$cDG~Ws+)%(z_eDz+RpDErDJSLE_ zh5t&YmAppj^4B?UXk(+DIf=~Hp>TmpCL?@ruK;YR*zFU{={ROMSPPbZWA$!VbENs( z4=z9#H-NYPkr8os`B%&YorMpL%$nm`gv!{Ny-DyC*ze6~*C?OPAFe$N%H^K{k6ZyH z27DY}*rqYlNBj`M276P+zdrDh4HR*%8)fGDYX(Jo1knI?b5LGU4bUbhy-06?HBp>! zqUKG3(8b$%a1aatz0eT;Lj4?H7r*ZPz;M&%0qnU1nuxXZV(1m-_4~K^dYg!cQ=JRl z#kdt{v+L!#?OY~Z7k#wAs?hS|x*;Hd9=|W&Prym6S(@hR#oulGMozn*NK%6_ zQ!r!>Oc_~aRg|~zl_gNfZ&Od7bJ6#+8y4Ra(Tw|qJ?VnqUG1(b-{<^MPCgzYJbRf_@|CZ4;8B*kWtYS#XQ7_U>SE?RN&P(=5a)i$>3Igq&-ngaoc)`>T3ph@y|N_rKZFW?F66rz@Gi zZ*Q)$d#SSrCXN*!j|EyiG7-(o!i;rTEbnEWgZ1}m!LoguWyYM31pU+c9?igBMW7hB z)3icG)1Pf6y&%j{8R;FT4Twpb)%S}W{}YXYkH(sEBa}_Qcawy=f4jB*jVn?1p!|e zd+lCigNmLF1-^Fzs81<;`c`K|LTTnsvkd*RisHS{DwC3BLxcpl|LJnoZfBb5So;HR z4~bOS4;l$AH2I{9t6X2c^%&Z7*f%~%<}LPoSX2`cLPw4;7GP}{(X=)JhN`=SR{3Q+ z*x0jD;lpgUhHU55YuiGp=`Yhiju(f$RsCQz_OYMGX2i4VaiW(HeGCiGn}qoh(W?!0 z_}UZFCpg=c4F=#cIEikfxc&XR2f`rMb8~a~4@wl~KMhI)?MB4ji4~XfNp`5mSNC|4 zBpt$=Ad$b-XNXB!WvE?a8R_lmv#WrMq1GmeXW*mDABpAw)0APxRita30QfORQd<*s{a^L}E!$3Wz<=T1>S3#t7))rQxG%K5($_5OC#!%6Dopy??_3?}dH=u>Ef zCLKU1O!^$fDD0k~&knt&ChZtZ+@u1izt(Mr$0~$N1Vn-*IyA$pEyTcx^>r=ER%MxZ zY2o4sT+X#jnYrn_`JyiKO)?}rFI{+u=eru-#51~znn>%;QaousE;C#AiEU~8gVGot z4f&dgY2P-{1nwOh6G(;m!;izcbX^ z3MmQGvwQr~_u8HwL{!!f<_7*FFza8^4oj=qynas?kGsQxERnGid7PqJhzYc0XoLyP z)Xp9HW~v7+@eiLYg^@NcAi9K%e{HEe_A9rXK!? zu&PvG)*6-wja)#$56j@Co9e9Jf$Z7OPD01!02K$LeqHX$I=&69Fl&E#omL>%#k41v%>AQvU#?0DigJ(8An`#2D3sp+cLsn~@75B=%69{>OV literal 0 HcmV?d00001 diff --git a/doc/_templates/sidebarintro.html b/doc/_templates/sidebarintro.html new file mode 100644 index 00000000000..95b047733e3 --- /dev/null +++ b/doc/_templates/sidebarintro.html @@ -0,0 +1,16 @@ + + +

Other Docs

+ + +

Useful Links

+ diff --git a/doc/_templates/sidebarlogo.html b/doc/_templates/sidebarlogo.html new file mode 100644 index 00000000000..de6e3e5c851 --- /dev/null +++ b/doc/_templates/sidebarlogo.html @@ -0,0 +1,3 @@ + From c2d5bf1bc35660a2e5d56552e8ab5c9d2ca99a0c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 20 Jan 2014 14:13:10 +0100 Subject: [PATCH 02/41] [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... --- doc/conf.py | 2 +- doc/howto/howto_website.rst | 142 +++++++++++++++++++++++ doc/howto/howto_website/basic-controller | 15 +++ doc/howto/howto_website/basic-page | 29 +++++ doc/howto/howto_website/manifest | 11 ++ doc/howto/howto_website/module-init | 8 ++ doc/howto/howto_website/series | 7 ++ doc/howto/howto_website/ta-controller | 57 +++++++++ doc/howto/howto_website/templates-basic | 108 +++++++++++++++++ doc/howto/howto_website/url-pattern | 29 +++++ doc/index.rst | 8 ++ 11 files changed, 415 insertions(+), 1 deletion(-) create mode 100644 doc/howto/howto_website.rst create mode 100644 doc/howto/howto_website/basic-controller create mode 100644 doc/howto/howto_website/basic-page create mode 100644 doc/howto/howto_website/manifest create mode 100644 doc/howto/howto_website/module-init create mode 100644 doc/howto/howto_website/series create mode 100644 doc/howto/howto_website/ta-controller create mode 100644 doc/howto/howto_website/templates-basic create mode 100644 doc/howto/howto_website/url-pattern diff --git a/doc/conf.py b/doc/conf.py index 19f2c9b727f..051fcde3ccb 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -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 index 00000000000..69486d79734 --- /dev/null +++ b/doc/howto/howto_website.rst @@ -0,0 +1,142 @@ +=================================== +Howto: build a website with OpenERP +=================================== + +.. queue:: howto_website/series + +.. warning:: + + This guide assumes `basic knowledge of python + `_. + + This guide assumes :ref:`an OpenERP installed and ready for + development `. + + 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 ` 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 index 00000000000..4415d9516bc --- /dev/null +++ b/doc/howto/howto_website/basic-controller @@ -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 index 00000000000..5a60c346acf --- /dev/null +++ b/doc/howto/howto_website/basic-page @@ -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 """ ++ ++ ++ AcademyAcademy ++ ++ ++ ++

Introduction to a thing

++

Course description

++

++ 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. ++

++ ++ ++""" diff --git a/doc/howto/howto_website/manifest b/doc/howto/howto_website/manifest new file mode 100644 index 00000000000..3cf359c9b30 --- /dev/null +++ b/doc/howto/howto_website/manifest @@ -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 index 00000000000..4484236edc9 --- /dev/null +++ b/doc/howto/howto_website/module-init @@ -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 index 00000000000..4b45d06e6d1 --- /dev/null +++ b/doc/howto/howto_website/series @@ -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 index 00000000000..5b8d0b799d5 --- /dev/null +++ b/doc/howto/howto_website/ta-controller @@ -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 = [ ++ '
  • %s
  • ' % (i, ta['name']) ++ for i, ta in enumerate(teaching_assistants) ++ ] ++ + return """ + + +@@ -19,6 +32,26 @@ class Home(main.Home): + will focus on the discovery of things and the planning and + organization necessary to handle things. +

    ++

    Teaching Assistants

    ++
      ++ %(tas)s ++
    + + +-""" ++""" % { ++ 'tas': '\n'.join(tas) ++ } ++ ++ @http.route('/tas', auth='none') ++ def ta(self, id): ++ return """ ++ ++ ++ AcademyAcademy TA %(name)s ++ ++ ++ ++

    %(name)s

    ++ ++ ++""" % teaching_assistants[int(id)] diff --git a/doc/howto/howto_website/templates-basic b/doc/howto/howto_website/templates-basic new file mode 100644 index 00000000000..5f0aefec2fe --- /dev/null +++ b/doc/howto/howto_website/templates-basic @@ -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 """ +- +- +- AcademyAcademy +- +- +- +-

    Introduction to a thing

    +-

    Course description

    +-

    +- 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. +-

    +-

    Teaching Assistants

    +-
      +- %(tas)s +-
    +- +- +-""" % { +- 'tas': '\n'.join(tas) +- } ++ # how in fuck do I get a db here? ++ return "" % { ++ 'tas': '\n'.join(tas) ++ } + + @http.route('/tas//', auth='none') + def ta(self, id): +- return """ +- +- +- AcademyAcademy TA %(name)s +- +- +- +-

    %(name)s

    +- +- +-""" % 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 @@ ++ ++ ++ ++ ++ ++ ++ ++ diff --git a/doc/howto/howto_website/url-pattern b/doc/howto/howto_website/url-pattern new file mode 100644 index 00000000000..8f37b1bdcda --- /dev/null +++ b/doc/howto/howto_website/url-pattern @@ -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 = [ +- '
  • %s
  • ' % (i, ta['name']) ++ '
  • %s
  • ' % (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//', auth='none') + def ta(self, id): + return """ + +@@ -54,4 +54,4 @@ class Home(main.Home): +

    %(name)s

    + + +-""" % teaching_assistants[int(id)] ++""" % teaching_assistants[id] diff --git a/doc/index.rst b/doc/index.rst index 4b988e747b4..a61de5ca0e0 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -4,6 +4,14 @@ OpenERP Server Developers Documentation ======================================== +Howto +''''' + +.. toctree:: + :maxdepth: 1 + + howto/howto_website + OpenERP Server '''''''''''''' From 22dd1a488c0a7a722b24a3306d87d3376f42c612 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 22 Jan 2014 13:38:16 +0100 Subject: [PATCH 03/41] [IMP] notes --- doc/howto/howto_website.rst | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 69486d79734..5c4aa2b73eb 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -129,12 +129,20 @@ 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:: 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? +This simplifies the controller code by moving data formatting out of +it, and generally makes it simpler for designers to edit the markup. + +.. todo:: link to section about reusing/altering existing stuff, + template overriding + + + .. _bootstrap: http://getbootstrap.com .. _converter patterns: http://werkzeug.pocoo.org/docs/routing/#rule-format From 864f4e580526c421bb752f35578f6229bb16cb97 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 23 Jan 2014 16:34:15 +0100 Subject: [PATCH 04/41] [ADD] plan --- doc/howto/howto_website.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 5c4aa2b73eb..21167339956 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -141,7 +141,28 @@ it, and generally makes it simpler for designers to edit the markup. .. todo:: link to section about reusing/altering existing stuff, template overriding +OpenERP's Website support +------------------------- +.. introduce the website module, add as dependency to academy, update db +.. RTE edition of pages, snippets +.. edition of own template pages? +.. ?? customize ?? + +Storing data in OpenERP +----------------------- + +.. calendar model +.. demo data for events dates +.. access & formatting +.. sending & storing comments (?) + +Administration and ERP Integration +---------------------------------- + +.. create menu, action + .. improve generated views +.. create list & form views for events .. _bootstrap: http://getbootstrap.com From a4363385ab22a58b3908c4b0522b3a34c5ca6891 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 27 Jan 2014 16:54:00 +0100 Subject: [PATCH 05/41] [ADD] website introduction --- doc/howto/howto_website.rst | 188 +++++++++++++++++++-- doc/howto/howto_website/series | 2 + doc/howto/howto_website/website-dependency | 58 +++++++ doc/howto/howto_website/website-layoutify | 82 +++++++++ 4 files changed, 315 insertions(+), 15 deletions(-) create mode 100644 doc/howto/howto_website/website-dependency create mode 100644 doc/howto/howto_website/website-layoutify diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 21167339956..9d243d763a7 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -15,11 +15,8 @@ Howto: build a website with OpenERP 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 @@ -83,7 +80,7 @@ output: 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). @@ -112,7 +109,7 @@ 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 @@ -133,8 +130,6 @@ Let's move our 2 pseudo-templates from inline strings to actual templates: controller? explicitly fetch a registry using request.session.db? That's a bit horrendous now innit? -.. todo:: reload/update of module? - This simplifies the controller code by moving data formatting out of it, and generally makes it simpler for designers to edit the markup. @@ -142,23 +137,184 @@ it, and generally makes it simpler for designers to edit the markup. template overriding OpenERP's Website support -------------------------- +========================= -.. introduce the website module, add as dependency to academy, update db -.. RTE edition of pages, snippets -.. edition of own template pages? -.. ?? customize ?? +OpenERP 8 is bundled with new modules dedicated specifically to +building websites (whether it be simply sets of pages or more complex +components such as blogs). + +First, we'll install the ``website`` module: ``oe install website``. + +.. todo:: is it possible that the page has *not* been replaced? + +If you navigate to `your openerp`_, your basic page has now been +replaced by the generic empty index page. Because you are not +logged-in yet, the page has no content and just basic placeholders in +the header and footer. Click on the :guilabel:`Sign In` link, fill in +your credentials (``admin``/``admin`` by default), click +:guilabel:`Log in`. + +You're now in OpenERP "proper", the backend/administrative +interface. We'll deal with it in :ref:`a latter section +`, for how click on the +:guilabel:`Website` menu item, in the top-left of the browser between +:guilabel:`Messaging` and :guilabel:`Settings`. + +You're back to your website, but are now an administrator and thus +have access to the advanced edition features of an OpenERP-build +website. Let's quickly run through them. + +Mobile Preview +-------------- + +.. todo:: insert menu bar, mobile preview icon outlined + +Because the OpenERP website system is built with bootstrap_, it is +easy to build "responsive" websites reacting to the size of the screen +and making best use of the available space. + +The mobile preview does not give you the exact rendering of a +smartphone (if there's such a thing), but it goes some of the way and +lets you know if it's completely unusable without having to actually +switch to a smartphone and try to find out how to see your site with +it (especially during edition). + +.. todo:: screenshot of page in desktop v mobile preview layout + +Promote +------- + +Lets you easily configure how your page should advertise its existence +to search engines: keywords matching the page's subject, nice titles +and descriptions for visitors finding the page via search engines. + +.. todo:: screenshot promote + +Content +------- + +The content menu provides "top level" operations: manipulation of the +main menu (creation of new links, submenus, etc...) and creation of +high-level objects. At the moment only pages (they're the top-level +object for the ``website`` module), but installing the recruitment +module will add an entry to quick-create a new job offer, and the +events module one for a new event. + +Customize +--------- + +The customize menu provides a number of loosely associated features, +broadly split in two sections: + +Templates configuration +``````````````````````` + +Some templates provide alternative versions/structures. These +alternative version can be toggled from the template configuration +checkboxes. Two of these are bundled in ``website``, providing an +alternative blank footer to fill, and the other one replacing your +company's name by your company's logo in the navigation bar. + +Theming +``````` + +As previously mentioned, OpenERP's website module uses bootstrap_ for +much of its basic styles and layout. This, in turns, allows using +existing bootstrap themes to alter the color scheme of your website. + +:guilabel:`Change Theme` opens a picker to a few bundled Bootstrap +themes, and lets you change the look of your site quickly and +on-the-fly. + +.. todo:: creating or installing new boostrap themes? + +HTML Editor +``````````` + +Opens a full-blown code editor on the current template, and lets you +easily edit templates in-place, either for a quick fix which is +simpler to perform in code yet from the page, or to try things out +before moving them to template files. + +Help +---- + +Lists available tutorials, step-by-step lessons in using the website. +``website`` only provides :guilabel:`Insert a banner` which shows some +basic features of the website (snippets, edition, mobile preview) +while guiding the user through. Other modules can provide additional +tutorials for their advanced features. + +Edit +---- + +Starts up the rich text editor, which lets you alter page text, add +links and images, change colors, etc… + +Snippets +```````` + +:guilabel:`Insert Blocks` opens the snippets UI: pre-built layout +blocks which you can then fill with your own content (text, pictures, +…). Simply select a snippet and drag-and-drop it on your page. Guides +should appear when you start dragging a snippet, showing where the +snippet can be dropped. + +Building your pages with OpenERP Website +======================================== + +As we've seen, your index page has "disappeared" and been replaced by +the one provided by ``website``. The page is not lost, but because +``website`` was installed after ``academy`` module, its page takes +over routing. + +To fix, that, we can simply add ``website`` as a dependency to +``academy`` (that is, tell OpenERP that ``academy`` needs ``website`` +to work right): + +.. needs -u all to update metadata + +.. patch:: + +.. todo:: website dispatch overrides blows up on auth=none (implicitly + inherits website's index -> ``website_enabled`` -> tries to + access ``request.registry['website']`` even though + ``request.registry is None`` because ``auth='none'``) + + also template issues (see above) (enabled website to "fix") + +Reload `your openerp`_. Your old index page is back, however none of +the website edition tools are available. That is because much of these +tools are inserted and enabled by the website layout template. Let's +use that instead of our own page structure: + +.. patch:: + +* ``website.layout`` is the main Website layout, it provides standard + headers and footers as well as integration with various + customization tools. + +* there's quite a bit of complex markup, used as hooks for various + features (e.g. snippets). Although technically not entirely + necessary, some things will not work if they're not there. + +* if you go in the HTML editor (:menuselection:`Customize --> HTML + Editor`), you can see and edit your template + +.. todo:: website template generator Storing data in OpenERP ------------------------ +======================= .. calendar model .. demo data for events dates .. access & formatting .. sending & storing comments (?) +.. _howto-website-administration: + Administration and ERP Integration ----------------------------------- +================================== .. create menu, action .. improve generated views @@ -169,3 +325,5 @@ Administration and ERP Integration .. _converter patterns: http://werkzeug.pocoo.org/docs/routing/#rule-format .. _templates: http://en.wikipedia.org/wiki/Web_template + +.. _your openerp: http://localhost:8069/ diff --git a/doc/howto/howto_website/series b/doc/howto/howto_website/series index 4b45d06e6d1..c0d15ab67a6 100644 --- a/doc/howto/howto_website/series +++ b/doc/howto/howto_website/series @@ -5,3 +5,5 @@ basic-page ta-controller url-pattern templates-basic +website-dependency +website-layoutify diff --git a/doc/howto/howto_website/website-dependency b/doc/howto/howto_website/website-dependency new file mode 100644 index 00000000000..e6bceff8883 --- /dev/null +++ b/doc/howto/howto_website/website-dependency @@ -0,0 +1,58 @@ +# HG changeset patch +# Parent 5a5145642f3604f09c5685d37beaddc497d3c850 + +diff --git a/__openerp__.py b/__openerp__.py +--- a/__openerp__.py ++++ b/__openerp__.py +@@ -1,6 +1,7 @@ + { + 'name': "Academy", + 'category': "Tools", ++ 'depends': ['website'], + 'data': [ + 'views/templates.xml', + ] +diff --git a/controllers.py b/controllers.py +--- a/controllers.py ++++ b/controllers.py +@@ -10,18 +10,12 @@ teaching_assistants = [ + ] + + class Home(main.Home): +- @http.route('/', auth='none') ++ @http.route('/', auth='public') + def index(self): +- tas = [ +- '
  • %s
  • ' % (i, ta['name']) +- for i, ta in enumerate(teaching_assistants) +- ] ++ return http.request.website.render('academy.index', { ++ 'tas': teaching_assistants, ++ }) + +- # how in fuck do I get a db here? +- return "" % { +- 'tas': '\n'.join(tas) +- } +- +- @http.route('/tas//', auth='none') ++ @http.route('/tas//', auth='public', website=True) + def ta(self, id): +- return "" % teaching_assistants[id] ++ return http.request.website.render('academy.ta', teaching_assistants[id]) +diff --git a/views/templates.xml b/views/templates.xml +--- a/views/templates.xml ++++ b/views/templates.xml +@@ -17,7 +17,11 @@ +

    +

    Teaching Assistants

    + + + diff --git a/doc/howto/howto_website/website-layoutify b/doc/howto/howto_website/website-layoutify new file mode 100644 index 00000000000..f3bd6ba6142 --- /dev/null +++ b/doc/howto/howto_website/website-layoutify @@ -0,0 +1,82 @@ +# HG changeset patch +# Parent c7be40a51aa39a1562ad0d8e3f75e56ca4ab47fc + +diff --git a/views/templates.xml b/views/templates.xml +--- a/views/templates.xml ++++ b/views/templates.xml +@@ -1,42 +1,42 @@ + + + + + + + From 10fd3d201f39b76d5d3d93bd816b0d418fb5726d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2014 11:51:23 +0100 Subject: [PATCH 06/41] [IMP] some doc wording, remove profane comment --- doc/howto/howto_website.rst | 41 ++++++++++++---------- doc/howto/howto_website/templates-basic | 5 ++- doc/howto/howto_website/website-dependency | 5 ++- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 9d243d763a7..23939bc8eee 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -157,8 +157,8 @@ your credentials (``admin``/``admin`` by default), click You're now in OpenERP "proper", the backend/administrative interface. We'll deal with it in :ref:`a latter section `, for how click on the -:guilabel:`Website` menu item, in the top-left of the browser between -:guilabel:`Messaging` and :guilabel:`Settings`. +:menuselection:`Website` menu item, in the top-left of the browser +between :menuselection:`Messaging` and :menuselection:`Settings`. You're back to your website, but are now an administrator and thus have access to the advanced edition features of an OpenERP-build @@ -222,9 +222,9 @@ As previously mentioned, OpenERP's website module uses bootstrap_ for much of its basic styles and layout. This, in turns, allows using existing bootstrap themes to alter the color scheme of your website. -:guilabel:`Change Theme` opens a picker to a few bundled Bootstrap -themes, and lets you change the look of your site quickly and -on-the-fly. +:menuselection:`Customize --> Change Theme` opens a picker to a few +bundled Bootstrap themes, and lets you change the look of your site +quickly and on-the-fly. .. todo:: creating or installing new boostrap themes? @@ -240,10 +240,10 @@ Help ---- Lists available tutorials, step-by-step lessons in using the website. -``website`` only provides :guilabel:`Insert a banner` which shows some -basic features of the website (snippets, edition, mobile preview) -while guiding the user through. Other modules can provide additional -tutorials for their advanced features. +``website`` only provides :menuselection:`Help --> Insert a banner` +which shows some basic features of the website (snippets, edition, +mobile preview) while guiding the user through. Other modules can +provide additional tutorials for their advanced features. Edit ---- @@ -265,10 +265,11 @@ Building your pages with OpenERP Website As we've seen, your index page has "disappeared" and been replaced by the one provided by ``website``. The page is not lost, but because -``website`` was installed after ``academy`` module, its page takes -over routing. +``website`` was installed after the ``academy`` module, its index +page takes over routing (two index pages exist, and one is picked +over the other). -To fix, that, we can simply add ``website`` as a dependency to +To fix the issue, we can simply add ``website`` as a dependency to ``academy`` (that is, tell OpenERP that ``academy`` needs ``website`` to work right): @@ -283,10 +284,14 @@ to work right): also template issues (see above) (enabled website to "fix") -Reload `your openerp`_. Your old index page is back, however none of -the website edition tools are available. That is because much of these -tools are inserted and enabled by the website layout template. Let's -use that instead of our own page structure: +This will cause ``academy``'s index page to overwrite ``website``'s. + +Reload `your openerp`_. Your old index page is back. + +However, none of the website edition tools are available. That is +because much of these tools are inserted and enabled by the website +layout template. Let's use that layout instead of our own page +structure: .. patch:: @@ -295,8 +300,8 @@ use that instead of our own page structure: customization tools. * there's quite a bit of complex markup, used as hooks for various - features (e.g. snippets). Although technically not entirely - necessary, some things will not work if they're not there. + features (e.g. snippets). Although technically not mandatory, some + things will not work if they're not there. * if you go in the HTML editor (:menuselection:`Customize --> HTML Editor`), you can see and edit your template diff --git a/doc/howto/howto_website/templates-basic b/doc/howto/howto_website/templates-basic index 5f0aefec2fe..ebce6f468bd 100644 --- a/doc/howto/howto_website/templates-basic +++ b/doc/howto/howto_website/templates-basic @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 559e3266ed1eeba384445016ffd1438eed54f144 +# Parent 0e882bf90a845788e155b437baf2b42c98901216 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py @@ -15,7 +15,7 @@ diff --git a/__openerp__.py b/__openerp__.py diff --git a/controllers.py b/controllers.py --- a/controllers.py +++ b/controllers.py -@@ -17,41 +17,11 @@ class Home(main.Home): +@@ -17,41 +17,10 @@ class Home(main.Home): for i, ta in enumerate(teaching_assistants) ] @@ -43,7 +43,6 @@ diff --git a/controllers.py b/controllers.py -""" % { - 'tas': '\n'.join(tas) - } -+ # how in fuck do I get a db here? + return "" % { + 'tas': '\n'.join(tas) + } diff --git a/doc/howto/howto_website/website-dependency b/doc/howto/howto_website/website-dependency index e6bceff8883..51bc6a6c9df 100644 --- a/doc/howto/howto_website/website-dependency +++ b/doc/howto/howto_website/website-dependency @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 5a5145642f3604f09c5685d37beaddc497d3c850 +# Parent 77db36690ddd8ad5065cab77837deec9da3df502 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py @@ -15,7 +15,7 @@ diff --git a/__openerp__.py b/__openerp__.py diff --git a/controllers.py b/controllers.py --- a/controllers.py +++ b/controllers.py -@@ -10,18 +10,12 @@ teaching_assistants = [ +@@ -10,17 +10,12 @@ teaching_assistants = [ ] class Home(main.Home): @@ -30,7 +30,6 @@ diff --git a/controllers.py b/controllers.py + 'tas': teaching_assistants, + }) -- # how in fuck do I get a db here? - return "" % { - 'tas': '\n'.join(tas) - } From 125d1586b08d5e5601602cbffe5eb5fea2b241d7 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2014 17:51:27 +0100 Subject: [PATCH 07/41] [ADD] models intro --- doc/howto/howto_website.rst | 128 +++++++++++++++++- doc/howto/howto_website/series | 6 + doc/howto/howto_website/ta-data | 37 +++++ doc/howto/howto_website/ta-html-biography | 11 ++ doc/howto/howto_website/ta-model | 68 ++++++++++ doc/howto/howto_website/ta-t-field | 14 ++ doc/howto/howto_website/ta-template-biography | 16 +++ doc/howto/howto_website/ta-view-fix | 38 ++++++ doc/howto/howto_website/website-layoutify | 12 +- 9 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 doc/howto/howto_website/ta-data create mode 100644 doc/howto/howto_website/ta-html-biography create mode 100644 doc/howto/howto_website/ta-model create mode 100644 doc/howto/howto_website/ta-t-field create mode 100644 doc/howto/howto_website/ta-template-biography create mode 100644 doc/howto/howto_website/ta-view-fix diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 23939bc8eee..e7052df67f1 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -308,9 +308,129 @@ structure: .. todo:: website template generator +If you try to add content to the TA pages using snippets, for instance +insert an :guilabel:`image-text` snippet to add a picture and a short +biography for a TA, you'll notice things don't work right: because +snippets are added in the template itself, they're content which is +the same across all pages using that template. + +Thus snippets are mostly for generic content, when a given template is +only used for a single page, or to add content in HTML fields. + +.. note:: + + When creating a new page (e.g. via :menuselection:`Content --> New + Page`), OpenERP will duplicate a "source" template, and create a + new template for each page. As a result, it's safe to use + dedicated-content snippets for "static" pages. + +Time, then, to create more specific content. + Storing data in OpenERP ======================= +The conceptual storage model of OpenERP is simple: there are storage +tables, represented by OpenERP models, and inside these tables are +records. The first step, then, is to define a model. + +We'll start by moving our teaching assistants in the database: + +.. patch:: + +We've also altered the index method slightly, to retrieve our teaching +assistants from the database instead of storing them in a global list +in the module\ [#taprofile]_. + +.. note:: :file:`ir.model.access.csv` is necessary to tell OpenERP that + any user can *see* the teaching assistants: by default, only + the administrator can see, edit, create or destroy objects. + Here, we only change the ``read`` permission to allow any + user to list and browse teaching assistants. + +.. todo:: command/shortcut + +Update the module, reload `your openerp`_… and the Teaching Assistants +list is empty since we haven't put any TA in the database. + +Let's add them in data files: + +.. patch:: + +Update the module again, reload `your openerp`_ and the TAs are +back. Click on a TA name, and you'll see an error message. Let's fix +the TA view now: + +.. todo:: if ta template was modified in previous section, it's marked + noupdate and updating the module will have no effect for no + known reason. That's really quite annoying. + +.. patch:: + +There are a few non-obvious things here, so let's go through them for +clarity: + +* OpenERP provides a has a special `converter pattern`_, which knows + how to retrieve OpenERP objects by identifier. Instead of an integer + or other similar basic value, ``ta`` thus gets a full-blown + ``academy.tas`` object, without having to retrieve it by hand (as is + done in ``index``). + +* However because the ``model()`` `converter pattern`_ takes an + identifier, we have to alter the creation of ``ta``'s URL to include + such an identifier, rather than an index in an array + +* Finally, ``website.render()`` wants a dict as its rendering context, + not an object, which is why we wrap our ``ta`` object into one. + +We're still where we started this section though: if we add snippets +to or edit the text of a TA's page, these editions will be visible +across all TA pages since they'll be stored in the shared +``academy.ta`` template. + +Not only that, but we can not even edit the TA's name, even though +it's not shared content. + +Let's fix that first, instead of using the basic "display this +content" template tag ``t-esc``, we'll use one aware of OpenERP +objects and their fields: + +.. patch:: + +Update the module, go into a TA page and activate the edition mode. If +you move your mouse over the TA's name, it is surrounded by a yellow +border, and you can edit its content. If you change the name of a TA +and save the page, the change is correctly stored in the TA's record, +the name is fixed when you go to the index page but other TAs remain +unaffected. + +For the issue of customizing our TA profiles, we can expand our model +with a "freeform" HTML field: + +.. patch:: + +Then, insert the new biographical content in the template using the +same object-aware template tag: + +.. patch:: + +.. todo:: updating the ``name`` field from the RTE altered the + template, which locked it... + +Update the module, browse to a TA's page and open the edition mode +(using the :guilabel:`Edit` button in the window's top-right). The +empty HTML field now displays a big placeholder image, if you drop +snippets in or write some content for one of the teaching assistants, +you will see that other TA profiles are unaffected. + +A more complex model +-------------------- + +Up to now, we've been working with displaying and manipulating +objects representing teaching assistants. It's a basic and +simple concept, but not one which allows for much further +diving into interesting tools of OpenERP. Thus, let's add a +list of course lectures. + .. calendar model .. demo data for events dates .. access & formatting @@ -325,9 +445,15 @@ Administration and ERP Integration .. improve generated views .. create list & form views for events +.. [#taprofile] the teaching assistants profile view ends up + broken for now, but don't worry we'll get + around to it + .. _bootstrap: http://getbootstrap.com -.. _converter patterns: http://werkzeug.pocoo.org/docs/routing/#rule-format +.. _converter pattern: +.. _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/series b/doc/howto/howto_website/series index c0d15ab67a6..e54bbbb05e1 100644 --- a/doc/howto/howto_website/series +++ b/doc/howto/howto_website/series @@ -7,3 +7,9 @@ url-pattern templates-basic website-dependency website-layoutify +ta-model +ta-data +ta-view-fix +ta-t-field +ta-html-biography +ta-template-biography diff --git a/doc/howto/howto_website/ta-data b/doc/howto/howto_website/ta-data new file mode 100644 index 00000000000..c38eae470ed --- /dev/null +++ b/doc/howto/howto_website/ta-data @@ -0,0 +1,37 @@ +# HG changeset patch +# Parent 94316d8049d7453cf70aff198b2d7ad1c04bf089 + +diff --git a/__openerp__.py b/__openerp__.py +--- a/__openerp__.py ++++ b/__openerp__.py +@@ -5,5 +5,6 @@ + 'data': [ + 'ir.model.access.csv', + 'views/templates.xml', ++ 'data/teaching_assistants.xml', + ] + } +diff --git a/data/teaching_assistants.xml b/data/teaching_assistants.xml +new file mode 100644 +--- /dev/null ++++ b/data/teaching_assistants.xml +@@ -0,0 +1,19 @@ ++ ++ ++ ++ Diana Padilla ++ ++ ++ Jody Carroll ++ ++ ++ Lester Vaughn ++ ++ ++ Paul Jimenez ++ ++ ++ Tanya Harris ++ ++ ++ diff --git a/doc/howto/howto_website/ta-html-biography b/doc/howto/howto_website/ta-html-biography new file mode 100644 index 00000000000..5d9dbc0ab09 --- /dev/null +++ b/doc/howto/howto_website/ta-html-biography @@ -0,0 +1,11 @@ +# HG changeset patch +# Parent e603b52f5a0484822964f6cefd7e5b389d44399b +diff --git a/models.py b/models.py +--- a/models.py ++++ b/models.py +@@ -7,4 +7,5 @@ class TeachingAssistants(orm.Model): + + _columns = { + 'name': fields.char(), ++ 'biography': fields.html(), + } diff --git a/doc/howto/howto_website/ta-model b/doc/howto/howto_website/ta-model new file mode 100644 index 00000000000..7b9917cb85a --- /dev/null +++ b/doc/howto/howto_website/ta-model @@ -0,0 +1,68 @@ +# HG changeset patch +# Parent 9735c655933b94f5e9017d0aac0b6e579f23adba + +diff --git a/__init__.py b/__init__.py +--- a/__init__.py ++++ b/__init__.py +@@ -1,1 +1,2 @@ + import controllers ++import models +diff --git a/__openerp__.py b/__openerp__.py +--- a/__openerp__.py ++++ b/__openerp__.py +@@ -3,6 +3,7 @@ + 'category': "Tools", + 'depends': ['website'], + 'data': [ ++ 'ir.model.access.csv', + 'views/templates.xml', + ] + } +diff --git a/controllers.py b/controllers.py +--- a/controllers.py ++++ b/controllers.py +@@ -1,19 +1,13 @@ + 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='public') + def index(self): ++ tas = http.request.registry['academy.tas'].search_read( ++ http.request.cr, http.request.uid, context=http.request.context) + return http.request.website.render('academy.index', { +- 'tas': teaching_assistants, ++ 'tas': tas, + }) + + @http.route('/tas//', auth='public', website=True) +diff --git a/ir.model.access.csv b/ir.model.access.csv +new file mode 100644 +--- /dev/null ++++ b/ir.model.access.csv +@@ -0,0 +1,2 @@ ++id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink ++access_academy_tas,access_academy_tas,model_academy_tas,,1,0,0,0 +diff --git a/models.py b/models.py +new file mode 100644 +--- /dev/null ++++ b/models.py +@@ -0,0 +1,10 @@ ++# -*- coding: utf-8 -*- ++ ++from openerp.osv import orm, fields ++ ++class TeachingAssistants(orm.Model): ++ _name = 'academy.tas' ++ ++ _columns = { ++ 'name': fields.char(), ++ } diff --git a/doc/howto/howto_website/ta-t-field b/doc/howto/howto_website/ta-t-field new file mode 100644 index 00000000000..706850a41ed --- /dev/null +++ b/doc/howto/howto_website/ta-t-field @@ -0,0 +1,14 @@ +# HG changeset patch +# Parent e00d1176e7ba0a515a45874d9f9e8703722810d1 +diff --git a/views/templates.xml b/views/templates.xml +--- a/views/templates.xml ++++ b/views/templates.xml +@@ -35,7 +35,7 @@ +
    +
    +
    +-

    ++

    +
    +
    +
    diff --git a/doc/howto/howto_website/ta-template-biography b/doc/howto/howto_website/ta-template-biography new file mode 100644 index 00000000000..9f596fae54b --- /dev/null +++ b/doc/howto/howto_website/ta-template-biography @@ -0,0 +1,16 @@ +# HG changeset patch +# Parent bba1cb179e03ab82504d12accfe456633806ba06 +diff --git a/views/templates.xml b/views/templates.xml +--- a/views/templates.xml ++++ b/views/templates.xml +@@ -35,7 +35,9 @@ +
    +
    +
    +-

    ++

    ++

    Biography

    ++
    +
    +
    +
    diff --git a/doc/howto/howto_website/ta-view-fix b/doc/howto/howto_website/ta-view-fix new file mode 100644 index 00000000000..88fcdef1787 --- /dev/null +++ b/doc/howto/howto_website/ta-view-fix @@ -0,0 +1,38 @@ +# HG changeset patch +# Parent d757ab6e2223e63f283b31815c8ff650ea42e2e7 +diff --git a/controllers.py b/controllers.py +--- a/controllers.py ++++ b/controllers.py +@@ -10,6 +10,8 @@ class Home(main.Home): + 'tas': tas, + }) + +- @http.route('/tas//', auth='public', website=True) +- def ta(self, id): +- return http.request.website.render('academy.ta', teaching_assistants[id]) ++ @http.route('/tas//', auth='public', website=True) ++ def ta(self, ta): ++ return http.request.website.render('academy.ta', { ++ 'ta': ta ++ }) +diff --git a/views/templates.xml b/views/templates.xml +--- a/views/templates.xml ++++ b/views/templates.xml +@@ -17,7 +17,7 @@ +

    Teaching Assistants

    +
      +
    • +- ++ + + +
    • +@@ -35,7 +35,7 @@ +
      +
      +
      +-

      ++

      +
      +
      +
      diff --git a/doc/howto/howto_website/website-layoutify b/doc/howto/howto_website/website-layoutify index f3bd6ba6142..27cfd6de74f 100644 --- a/doc/howto/howto_website/website-layoutify +++ b/doc/howto/howto_website/website-layoutify @@ -1,10 +1,10 @@ # HG changeset patch -# Parent c7be40a51aa39a1562ad0d8e3f75e56ca4ab47fc +# Parent 375b20994a7069eadfbd64c793328a07f7d9baf6 diff --git a/views/templates.xml b/views/templates.xml --- a/views/templates.xml +++ b/views/templates.xml -@@ -1,42 +1,42 @@ +@@ -1,42 +1,46 @@ From b2a751652289f31caa1f8880d1a9e47c7b495345 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 30 Jan 2014 10:50:43 +0100 Subject: [PATCH 08/41] [ADD] explain reason for new working model --- doc/howto/howto_website.rst | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index e7052df67f1..a3e938a0a52 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -341,11 +341,11 @@ We've also altered the index method slightly, to retrieve our teaching assistants from the database instead of storing them in a global list in the module\ [#taprofile]_. -.. note:: :file:`ir.model.access.csv` is necessary to tell OpenERP that - any user can *see* the teaching assistants: by default, only - the administrator can see, edit, create or destroy objects. - Here, we only change the ``read`` permission to allow any - user to list and browse teaching assistants. +.. note:: :file:`ir.model.access.csv` is necessary to tell OpenERP + that any user can *see* the teaching assistants: by default, + only the administrator can see, edit, create or destroy + objects. Here, we only change the ``read`` permission to + allow any user to list and browse teaching assistants. .. todo:: command/shortcut @@ -425,11 +425,16 @@ you will see that other TA profiles are unaffected. A more complex model -------------------- -Up to now, we've been working with displaying and manipulating -objects representing teaching assistants. It's a basic and -simple concept, but not one which allows for much further -diving into interesting tools of OpenERP. Thus, let's add a -list of course lectures. +Up to now, we've been working with displaying and manipulating objects +representing teaching assistants. It's a basic and simple concept, but not one +which allows for much further diving into interesting tools of OpenERP. + +We need an object fitting the theme yet allowing for richer interactions and +more interesting extensions. Course lectures seem to fit: they can be +displayed in various manners (e.g. as a list of lectures or as a calendar), +they can be moved around as necessary (cancelled/rescheduled), they can have +numerous pieces of data attached both intrinsic (lecture transcripts) and +extrinsic (attendance records, student discussions, etc…). .. calendar model .. demo data for events dates From 80f03b260455d42b9af5ab0e23e6b006dffef9b6 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 30 Jan 2014 10:53:41 +0100 Subject: [PATCH 09/41] [IMP] source formatting: fill-paragraph to 78 leaves a bit of room for diff mark & a small gutter in a 80c system --- doc/howto/howto_website.rst | 380 +++++++++++++++++------------------- 1 file changed, 183 insertions(+), 197 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index a3e938a0a52..025cc3a5c1a 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -9,18 +9,18 @@ Howto: build a website with OpenERP This guide assumes `basic knowledge of python `_. - This guide assumes :ref:`an OpenERP installed and ready for - development `. + This guide assumes :ref:`an OpenERP installed and ready for development + `. - For production deployment, see the dedicated guides - :ref:`using-gunicorn` and :ref:`using-mod-wsgi`. + For production deployment, see the dedicated guides :ref:`using-gunicorn` + and :ref:`using-mod-wsgi`. 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: +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? @@ -29,15 +29,15 @@ step is thus to create a module: * 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: +* 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: + interacting directly with your web browser will live. For starters, just + include the following in it: .. patch:: @@ -45,8 +45,8 @@ step is thus to create a module: .. patch:: - This makes :file:`controllers.py` "visible" to openerp (by running - the code it holds). + This makes :file:`controllers.py` "visible" to openerp (by running the code + it holds). .. todo:: @@ -56,15 +56,15 @@ step is thus to create a module: - 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. +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. +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: @@ -73,17 +73,17 @@ output: .. 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. + 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). +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 @@ -98,14 +98,15 @@ 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``: +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 +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 @@ -116,171 +117,164 @@ 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 ` templating system which we'll later see offers -some useful features. +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 +` 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:: -.. todo:: 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:: 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? -This simplifies the controller code by moving data formatting out of -it, and generally makes it simpler for designers to edit the markup. +This simplifies the controller code by moving data formatting out of it, and +generally makes it simpler for designers to edit the markup. -.. todo:: link to section about reusing/altering existing stuff, - template overriding +.. todo:: link to section about reusing/altering existing stuff, template + overriding OpenERP's Website support ========================= -OpenERP 8 is bundled with new modules dedicated specifically to -building websites (whether it be simply sets of pages or more complex -components such as blogs). +OpenERP 8 is bundled with new modules dedicated specifically to building +websites (whether it be simply sets of pages or more complex components such +as blogs). First, we'll install the ``website`` module: ``oe install website``. .. todo:: is it possible that the page has *not* been replaced? -If you navigate to `your openerp`_, your basic page has now been -replaced by the generic empty index page. Because you are not -logged-in yet, the page has no content and just basic placeholders in -the header and footer. Click on the :guilabel:`Sign In` link, fill in -your credentials (``admin``/``admin`` by default), click -:guilabel:`Log in`. +If you navigate to `your openerp`_, your basic page has now been replaced by +the generic empty index page. Because you are not logged-in yet, the page has +no content and just basic placeholders in the header and footer. Click on the +:guilabel:`Sign In` link, fill in your credentials (``admin``/``admin`` by +default), click :guilabel:`Log in`. -You're now in OpenERP "proper", the backend/administrative -interface. We'll deal with it in :ref:`a latter section -`, for how click on the -:menuselection:`Website` menu item, in the top-left of the browser -between :menuselection:`Messaging` and :menuselection:`Settings`. +You're now in OpenERP "proper", the backend/administrative interface. We'll +deal with it in :ref:`a latter section `, for +how click on the :menuselection:`Website` menu item, in the top-left of the +browser between :menuselection:`Messaging` and :menuselection:`Settings`. -You're back to your website, but are now an administrator and thus -have access to the advanced edition features of an OpenERP-build -website. Let's quickly run through them. +You're back to your website, but are now an administrator and thus have access +to the advanced edition features of an OpenERP-build website. Let's quickly +run through them. Mobile Preview -------------- .. todo:: insert menu bar, mobile preview icon outlined -Because the OpenERP website system is built with bootstrap_, it is -easy to build "responsive" websites reacting to the size of the screen -and making best use of the available space. +Because the OpenERP website system is built with bootstrap_, it is easy to +build "responsive" websites reacting to the size of the screen and making best +use of the available space. -The mobile preview does not give you the exact rendering of a -smartphone (if there's such a thing), but it goes some of the way and -lets you know if it's completely unusable without having to actually -switch to a smartphone and try to find out how to see your site with -it (especially during edition). +The mobile preview does not give you the exact rendering of a smartphone (if +there's such a thing), but it goes some of the way and lets you know if it's +completely unusable without having to actually switch to a smartphone and try +to find out how to see your site with it (especially during edition). .. todo:: screenshot of page in desktop v mobile preview layout Promote ------- -Lets you easily configure how your page should advertise its existence -to search engines: keywords matching the page's subject, nice titles -and descriptions for visitors finding the page via search engines. +Lets you easily configure how your page should advertise its existence to +search engines: keywords matching the page's subject, nice titles and +descriptions for visitors finding the page via search engines. .. todo:: screenshot promote Content ------- -The content menu provides "top level" operations: manipulation of the -main menu (creation of new links, submenus, etc...) and creation of -high-level objects. At the moment only pages (they're the top-level -object for the ``website`` module), but installing the recruitment -module will add an entry to quick-create a new job offer, and the -events module one for a new event. +The content menu provides "top level" operations: manipulation of the main +menu (creation of new links, submenus, etc...) and creation of high-level +objects. At the moment only pages (they're the top-level object for the +``website`` module), but installing the recruitment module will add an entry +to quick-create a new job offer, and the events module one for a new event. Customize --------- -The customize menu provides a number of loosely associated features, -broadly split in two sections: +The customize menu provides a number of loosely associated features, broadly +split in two sections: Templates configuration ``````````````````````` -Some templates provide alternative versions/structures. These -alternative version can be toggled from the template configuration -checkboxes. Two of these are bundled in ``website``, providing an -alternative blank footer to fill, and the other one replacing your -company's name by your company's logo in the navigation bar. +Some templates provide alternative versions/structures. These alternative +version can be toggled from the template configuration checkboxes. Two of +these are bundled in ``website``, providing an alternative blank footer to +fill, and the other one replacing your company's name by your company's logo +in the navigation bar. Theming ``````` -As previously mentioned, OpenERP's website module uses bootstrap_ for -much of its basic styles and layout. This, in turns, allows using -existing bootstrap themes to alter the color scheme of your website. +As previously mentioned, OpenERP's website module uses bootstrap_ for much of +its basic styles and layout. This, in turns, allows using existing bootstrap +themes to alter the color scheme of your website. -:menuselection:`Customize --> Change Theme` opens a picker to a few -bundled Bootstrap themes, and lets you change the look of your site -quickly and on-the-fly. +:menuselection:`Customize --> Change Theme` opens a picker to a few bundled +Bootstrap themes, and lets you change the look of your site quickly and +on-the-fly. .. todo:: creating or installing new boostrap themes? HTML Editor ``````````` -Opens a full-blown code editor on the current template, and lets you -easily edit templates in-place, either for a quick fix which is -simpler to perform in code yet from the page, or to try things out -before moving them to template files. +Opens a full-blown code editor on the current template, and lets you easily +edit templates in-place, either for a quick fix which is simpler to perform in +code yet from the page, or to try things out before moving them to template +files. Help ---- Lists available tutorials, step-by-step lessons in using the website. -``website`` only provides :menuselection:`Help --> Insert a banner` -which shows some basic features of the website (snippets, edition, -mobile preview) while guiding the user through. Other modules can -provide additional tutorials for their advanced features. +``website`` only provides :menuselection:`Help --> Insert a banner` which +shows some basic features of the website (snippets, edition, mobile preview) +while guiding the user through. Other modules can provide additional tutorials +for their advanced features. Edit ---- -Starts up the rich text editor, which lets you alter page text, add -links and images, change colors, etc… +Starts up the rich text editor, which lets you alter page text, add links and +images, change colors, etc… Snippets ```````` -:guilabel:`Insert Blocks` opens the snippets UI: pre-built layout -blocks which you can then fill with your own content (text, pictures, -…). Simply select a snippet and drag-and-drop it on your page. Guides -should appear when you start dragging a snippet, showing where the -snippet can be dropped. +:guilabel:`Insert Blocks` opens the snippets UI: pre-built layout blocks which +you can then fill with your own content (text, pictures, …). Simply select a +snippet and drag-and-drop it on your page. Guides should appear when you start +dragging a snippet, showing where the snippet can be dropped. Building your pages with OpenERP Website ======================================== -As we've seen, your index page has "disappeared" and been replaced by -the one provided by ``website``. The page is not lost, but because -``website`` was installed after the ``academy`` module, its index -page takes over routing (two index pages exist, and one is picked -over the other). +As we've seen, your index page has "disappeared" and been replaced by the one +provided by ``website``. The page is not lost, but because ``website`` was +installed after the ``academy`` module, its index page takes over routing (two +index pages exist, and one is picked over the other). -To fix the issue, we can simply add ``website`` as a dependency to -``academy`` (that is, tell OpenERP that ``academy`` needs ``website`` -to work right): +To fix the issue, we can simply add ``website`` as a dependency to ``academy`` +(that is, tell OpenERP that ``academy`` needs ``website`` to work right): .. needs -u all to update metadata .. patch:: .. todo:: website dispatch overrides blows up on auth=none (implicitly - inherits website's index -> ``website_enabled`` -> tries to - access ``request.registry['website']`` even though - ``request.registry is None`` because ``auth='none'``) + inherits website's index -> ``website_enabled`` -> tries to access + ``request.registry['website']`` even though ``request.registry is + None`` because ``auth='none'``) also template issues (see above) (enabled website to "fix") @@ -288,139 +282,132 @@ This will cause ``academy``'s index page to overwrite ``website``'s. Reload `your openerp`_. Your old index page is back. -However, none of the website edition tools are available. That is -because much of these tools are inserted and enabled by the website -layout template. Let's use that layout instead of our own page -structure: +However, none of the website edition tools are available. That is because much +of these tools are inserted and enabled by the website layout template. Let's +use that layout instead of our own page structure: .. patch:: -* ``website.layout`` is the main Website layout, it provides standard - headers and footers as well as integration with various - customization tools. +* ``website.layout`` is the main Website layout, it provides standard headers + and footers as well as integration with various customization tools. -* there's quite a bit of complex markup, used as hooks for various - features (e.g. snippets). Although technically not mandatory, some - things will not work if they're not there. +* there's quite a bit of complex markup, used as hooks for various features + (e.g. snippets). Although technically not mandatory, some things will not + work if they're not there. -* if you go in the HTML editor (:menuselection:`Customize --> HTML - Editor`), you can see and edit your template +* if you go in the HTML editor (:menuselection:`Customize --> HTML Editor`), + you can see and edit your template .. todo:: website template generator -If you try to add content to the TA pages using snippets, for instance -insert an :guilabel:`image-text` snippet to add a picture and a short -biography for a TA, you'll notice things don't work right: because -snippets are added in the template itself, they're content which is -the same across all pages using that template. +If you try to add content to the TA pages using snippets, for instance insert +an :guilabel:`image-text` snippet to add a picture and a short biography for a +TA, you'll notice things don't work right: because snippets are added in the +template itself, they're content which is the same across all pages using that +template. -Thus snippets are mostly for generic content, when a given template is -only used for a single page, or to add content in HTML fields. +Thus snippets are mostly for generic content, when a given template is only +used for a single page, or to add content in HTML fields. .. note:: - When creating a new page (e.g. via :menuselection:`Content --> New - Page`), OpenERP will duplicate a "source" template, and create a - new template for each page. As a result, it's safe to use - dedicated-content snippets for "static" pages. + When creating a new page (e.g. via :menuselection:`Content --> New Page`), + OpenERP will duplicate a "source" template, and create a new template for + each page. As a result, it's safe to use dedicated-content snippets for + "static" pages. Time, then, to create more specific content. Storing data in OpenERP ======================= -The conceptual storage model of OpenERP is simple: there are storage -tables, represented by OpenERP models, and inside these tables are -records. The first step, then, is to define a model. +The conceptual storage model of OpenERP is simple: there are storage tables, +represented by OpenERP models, and inside these tables are records. The first +step, then, is to define a model. We'll start by moving our teaching assistants in the database: .. patch:: We've also altered the index method slightly, to retrieve our teaching -assistants from the database instead of storing them in a global list -in the module\ [#taprofile]_. +assistants from the database instead of storing them in a global list in the +module\ [#taprofile]_. -.. note:: :file:`ir.model.access.csv` is necessary to tell OpenERP - that any user can *see* the teaching assistants: by default, - only the administrator can see, edit, create or destroy - objects. Here, we only change the ``read`` permission to - allow any user to list and browse teaching assistants. +.. note:: :file:`ir.model.access.csv` is necessary to tell OpenERP that any + user can *see* the teaching assistants: by default, only the + administrator can see, edit, create or destroy objects. Here, we + only change the ``read`` permission to allow any user to list and + browse teaching assistants. .. todo:: command/shortcut -Update the module, reload `your openerp`_… and the Teaching Assistants -list is empty since we haven't put any TA in the database. +Update the module, reload `your openerp`_… and the Teaching Assistants list is +empty since we haven't put any TA in the database. Let's add them in data files: .. patch:: -Update the module again, reload `your openerp`_ and the TAs are -back. Click on a TA name, and you'll see an error message. Let's fix -the TA view now: +Update the module again, reload `your openerp`_ and the TAs are back. Click on +a TA name, and you'll see an error message. Let's fix the TA view now: .. todo:: if ta template was modified in previous section, it's marked - noupdate and updating the module will have no effect for no - known reason. That's really quite annoying. + noupdate and updating the module will have no effect for no known + reason. That's really quite annoying. .. patch:: -There are a few non-obvious things here, so let's go through them for -clarity: +There are a few non-obvious things here, so let's go through them for clarity: -* OpenERP provides a has a special `converter pattern`_, which knows - how to retrieve OpenERP objects by identifier. Instead of an integer - or other similar basic value, ``ta`` thus gets a full-blown - ``academy.tas`` object, without having to retrieve it by hand (as is - done in ``index``). +* OpenERP provides a has a special `converter pattern`_, which knows how to + retrieve OpenERP objects by identifier. Instead of an integer or other + similar basic value, ``ta`` thus gets a full-blown ``academy.tas`` object, + without having to retrieve it by hand (as is done in ``index``). -* However because the ``model()`` `converter pattern`_ takes an - identifier, we have to alter the creation of ``ta``'s URL to include - such an identifier, rather than an index in an array +* However because the ``model()`` `converter pattern`_ takes an identifier, we + have to alter the creation of ``ta``'s URL to include such an identifier, + rather than an index in an array -* Finally, ``website.render()`` wants a dict as its rendering context, - not an object, which is why we wrap our ``ta`` object into one. +* Finally, ``website.render()`` wants a dict as its rendering context, not an + object, which is why we wrap our ``ta`` object into one. -We're still where we started this section though: if we add snippets -to or edit the text of a TA's page, these editions will be visible -across all TA pages since they'll be stored in the shared -``academy.ta`` template. +We're still where we started this section though: if we add snippets to or +edit the text of a TA's page, these editions will be visible across all TA +pages since they'll be stored in the shared ``academy.ta`` template. -Not only that, but we can not even edit the TA's name, even though -it's not shared content. +Not only that, but we can not even edit the TA's name, even though it's not +shared content. -Let's fix that first, instead of using the basic "display this -content" template tag ``t-esc``, we'll use one aware of OpenERP -objects and their fields: +Let's fix that first, instead of using the basic "display this content" +template tag ``t-esc``, we'll use one aware of OpenERP objects and their +fields: .. patch:: -Update the module, go into a TA page and activate the edition mode. If -you move your mouse over the TA's name, it is surrounded by a yellow -border, and you can edit its content. If you change the name of a TA -and save the page, the change is correctly stored in the TA's record, -the name is fixed when you go to the index page but other TAs remain -unaffected. +Update the module, go into a TA page and activate the edition mode. If you +move your mouse over the TA's name, it is surrounded by a yellow border, and +you can edit its content. If you change the name of a TA and save the page, +the change is correctly stored in the TA's record, the name is fixed when you +go to the index page but other TAs remain unaffected. -For the issue of customizing our TA profiles, we can expand our model -with a "freeform" HTML field: +For the issue of customizing our TA profiles, we can expand our model with a +"freeform" HTML field: .. patch:: -Then, insert the new biographical content in the template using the -same object-aware template tag: +Then, insert the new biographical content in the template using the same +object-aware template tag: .. patch:: -.. todo:: updating the ``name`` field from the RTE altered the - template, which locked it... +.. todo:: updating the ``name`` field from the RTE altered the template, which + locked it... -Update the module, browse to a TA's page and open the edition mode -(using the :guilabel:`Edit` button in the window's top-right). The -empty HTML field now displays a big placeholder image, if you drop -snippets in or write some content for one of the teaching assistants, -you will see that other TA profiles are unaffected. +Update the module, browse to a TA's page and open the edition mode (using the +:guilabel:`Edit` button in the window's top-right). The empty HTML field now +displays a big placeholder image, if you drop snippets in or write some +content for one of the teaching assistants, you will see that other TA +profiles are unaffected. A more complex model -------------------- @@ -450,9 +437,8 @@ Administration and ERP Integration .. improve generated views .. create list & form views for events -.. [#taprofile] the teaching assistants profile view ends up - broken for now, but don't worry we'll get - around to it +.. [#taprofile] the teaching assistants profile view ends up broken for now, + but don't worry we'll get around to it .. _bootstrap: http://getbootstrap.com From 8a7397806349530f7b0dd547e04eca38c8bb9819 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 30 Jan 2014 15:06:46 +0100 Subject: [PATCH 10/41] [FIX] use format_date for date fields --- openerp/addons/base/ir/ir_qweb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index bb422d5397c..9fceda9cc94 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -635,7 +635,7 @@ class DateConverter(osv.AbstractModel): strftime_pattern = lang.date_format pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale) - return babel.dates.format_datetime( + return babel.dates.format_date( value, format=pattern, locale=locale) From 6d25d63981872c8080293ec1e77d8410dc3eae75 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 30 Jan 2014 15:07:23 +0100 Subject: [PATCH 11/41] [ADD] lectures model, demonstrate date fields & options --- doc/howto/howto_website.rst | 28 ++++- doc/howto/howto_website/lectures-model-add | 115 +++++++++++++++++++++ doc/howto/howto_website/series | 1 + 3 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 doc/howto/howto_website/lectures-model-add diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 025cc3a5c1a..d9a84a30e42 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -423,8 +423,30 @@ they can be moved around as necessary (cancelled/rescheduled), they can have numerous pieces of data attached both intrinsic (lecture transcripts) and extrinsic (attendance records, student discussions, etc…). -.. calendar model -.. demo data for events dates +.. patch:: + +.. TODO:: ``-u`` did not work, not even ``-uall``, new data file does not get + installed + +Note a new feature: ``t-field`` tags can take options through +``t-field-options``. The options must be a JSON_ object. Available options +depend on the field's type and potentially the display widget (some types +of fields can be displayed in multiple manners). In this case, the same +``date`` field is displayed using custom date formats, one being the generic +``long`` (which depends on the current user's locale) and the other being +an explicit format for `the weekday in short form +`_. + +.. note:: in edition mode, formatted date and datetime fields revert to a + canonical representation in order to provide all of the field's + information. + +.. warning:: if you edit the course's dates, you will notice that the two + displays of the ``date`` field are unlinked, if one is edited + the second one will not change until the edition is saved. This + is a limitation of the current ``website`` but may be improved in + future releases. + .. access & formatting .. sending & storing comments (?) @@ -449,3 +471,5 @@ Administration and ERP Integration .. _templates: http://en.wikipedia.org/wiki/Web_template .. _your openerp: http://localhost:8069/ + +.. _JSON: http://www.json.org diff --git a/doc/howto/howto_website/lectures-model-add b/doc/howto/howto_website/lectures-model-add new file mode 100644 index 00000000000..dd53130721d --- /dev/null +++ b/doc/howto/howto_website/lectures-model-add @@ -0,0 +1,115 @@ +# HG changeset patch +# Parent 65912bc56408d6bf61b2023a79a48e06a22fe9e2 + +diff --git a/__openerp__.py b/__openerp__.py +--- a/__openerp__.py ++++ b/__openerp__.py +@@ -6,5 +6,6 @@ + 'ir.model.access.csv', + 'views/templates.xml', + 'data/teaching_assistants.xml', ++ 'data/lectures.xml', + ] + } +diff --git a/controllers.py b/controllers.py +--- a/controllers.py ++++ b/controllers.py +@@ -4,10 +4,15 @@ from openerp.addons.web.controllers impo + class Home(main.Home): + @http.route('/', auth='public') + def index(self): ++ cr, uid, context = http.request.cr, http.request.uid, http.request.context ++ Lectures = http.request.registry['academy.lectures'] + tas = http.request.registry['academy.tas'].search_read( + http.request.cr, http.request.uid, context=http.request.context) ++ lectures = Lectures.browse( ++ cr, uid, Lectures.search(cr, uid, [], context=context), context=context) + return http.request.website.render('academy.index', { + 'tas': tas, ++ 'lectures': lectures, + }) + + @http.route('/tas//', auth='public', website=True) +diff --git a/data/lectures.xml b/data/lectures.xml +new file mode 100644 +--- /dev/null ++++ b/data/lectures.xml +@@ -0,0 +1,24 @@ ++ ++ ++ ++ Lecture 1 ++ 2014-01-06 ++ ++ ++ Lecture 2 ++ 2014-01-08 ++ ++ ++ Lecture 3 ++ 2014-01-10 ++ ++ ++ Lecture 4 ++ 2014-01-13 ++ ++ ++ Lecture 5 ++ 2014-01-15 ++ ++ ++ +diff --git a/ir.model.access.csv b/ir.model.access.csv +--- a/ir.model.access.csv ++++ b/ir.model.access.csv +@@ -1,2 +1,3 @@ + id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink + access_academy_tas,access_academy_tas,model_academy_tas,,1,0,0,0 ++access_academy_lectures,access_academy_lectures,model_academy_lectures,,1,0,0,0 +diff --git a/models.py b/models.py +--- a/models.py ++++ b/models.py +@@ -9,3 +9,12 @@ class TeachingAssistants(orm.Model): + 'name': fields.char(), + 'biography': fields.html(), + } ++ ++class Lectures(orm.Model): ++ _name = 'academy.lectures' ++ _order = 'date ASC' ++ ++ _columns = { ++ 'name': fields.char(required=True), ++ 'date': fields.date(required=True), ++ } +diff --git a/views/templates.xml b/views/templates.xml +--- a/views/templates.xml ++++ b/views/templates.xml +@@ -22,6 +22,27 @@ + + +
    ++

    Course Calendar

    ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
    DateDayTopic
    ++ ++ ++ ++ ++ ++
    +
    +
    +
    diff --git a/doc/howto/howto_website/series b/doc/howto/howto_website/series index e54bbbb05e1..162e9df8bbe 100644 --- a/doc/howto/howto_website/series +++ b/doc/howto/howto_website/series @@ -13,3 +13,4 @@ ta-view-fix ta-t-field ta-html-biography ta-template-biography +lectures-model-add From 275c612dbbfcfcf04450ec54fdabb36059a6d0bd Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 31 Jan 2014 10:02:54 +0100 Subject: [PATCH 12/41] [IMP] move data to demo, action and menus --- doc/howto/howto_website.rst | 69 +++++++++++++++++-- doc/howto/howto_website/data-to-demo | 23 +++++++ .../howto_website/lectures-action-and-menus | 33 +++++++++ doc/howto/howto_website/series | 2 + 4 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 doc/howto/howto_website/data-to-demo create mode 100644 doc/howto/howto_website/lectures-action-and-menus diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index d9a84a30e42..cc1dba77995 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -137,6 +137,8 @@ generally makes it simpler for designers to edit the markup. .. todo:: link to section about reusing/altering existing stuff, template overriding +.. _howto-website-support: + OpenERP's Website support ========================= @@ -155,12 +157,12 @@ no content and just basic placeholders in the header and footer. Click on the default), click :guilabel:`Log in`. You're now in OpenERP "proper", the backend/administrative interface. We'll -deal with it in :ref:`a latter section `, for -how click on the :menuselection:`Website` menu item, in the top-left of the -browser between :menuselection:`Messaging` and :menuselection:`Settings`. +deal with it in :ref:`a latter section `. For +now, click on the :menuselection:`Website` menu item in the top-left of the +browser, between :menuselection:`Messaging` and :menuselection:`Settings`. You're back to your website, but are now an administrator and thus have access -to the advanced edition features of an OpenERP-build website. Let's quickly +to the advanced edition features of an OpenERP-built website. Let's quickly run through them. Mobile Preview @@ -447,7 +449,6 @@ an explicit format for `the weekday in short form is a limitation of the current ``website`` but may be improved in future releases. -.. access & formatting .. sending & storing comments (?) .. _howto-website-administration: @@ -455,6 +456,64 @@ an explicit format for `the weekday in short form Administration and ERP Integration ================================== +In practice, the data we've created so far using XML data files is usually +stored as "demo data", used for testing and demonstrations of modules, and the +actual user data is input via the OpenERP "backend", which we're going to try +out now. First let's move our data set to demo data: + +.. patch:: + +the difference is simply that new databases can be created either in "demo" +mode or in "no demo" mode. In the former case, the database will be preloaded +with any demo data configured in the installed module. + +.. todo:: need to create a new DB again? + +A brief and incomplete introduction to the OpenERP administration +----------------------------------------------------------------- + +You've already seen it for a very short time in :ref:`howto-website-support`, +you can go back to it using :menuselection:`Administrator --> Administration` +if you're already logged-in (which you should be), or go through +:menuselection:`Sign In` again if you are not. + +The conceptual structure of the OpenERP backend is simple: + +1. first are menus, menus are a tree (they can have sub-menus). To menus + without children is mapped… + +2. an action. Actions have various types, they can be links, reports (PDF), + code which the server should execute or window actions. Window actions + tell the client to display the OpenERP object according to certain views… + +3. a view has a type, the broad category to which it corresponds (tree, form, + graph, calendar, …) and its architecture which represents the way the + object is laid out inside the view. + +By default, when an OpenERP object is *defined* it is essentially invisible in +the interface. To make it visible, it needs to be available through an action, +which itself needs to be reachable somehow, usually a through a menu. + +Let us, then, create a menu and an action for our lectures: + +.. patch:: + +.. todo:: reinstall module? update? + +If you reload the backend, you should see a new menu :menuselection:`Academy` +at the top-left corner, before :menuselection:`Messaging`. In it is the +submenus we defined via ``menuitem``, and within (the first submenu is +selected by default) opens a list view of the lectures. To the right is a +series of 2 buttons, which lets you toggle between the "list" view (overview +of all records in the object) and the "form" view (view an manipulation of a +single record). The :guilabel:`Create` button above the list lets you create +new record, you can select records to delete them. + +There's one big issue to fix right now, the labeling of the column in the list +and the fields in the form view, which are all currently :guilabel:`unknown`: + +.. FIXME:: fix labels + .. create menu, action .. improve generated views .. create list & form views for events diff --git a/doc/howto/howto_website/data-to-demo b/doc/howto/howto_website/data-to-demo new file mode 100644 index 00000000000..4c0797f0543 --- /dev/null +++ b/doc/howto/howto_website/data-to-demo @@ -0,0 +1,23 @@ +# HG changeset patch +# Parent 2af29a429acda61e5e567997dad78a673e011796 +diff --git a/__openerp__.py b/__openerp__.py +--- a/__openerp__.py ++++ b/__openerp__.py +@@ -5,7 +5,9 @@ + 'data': [ + 'ir.model.access.csv', + 'views/templates.xml', +- 'data/teaching_assistants.xml', +- 'data/lectures.xml', ++ ], ++ 'demo': [ ++ 'demo/teaching_assistants.xml', ++ 'demo/lectures.xml', + ] + } +diff --git a/data/lectures.xml b/demo/lectures.xml +rename from data/lectures.xml +rename to demo/lectures.xml +diff --git a/data/teaching_assistants.xml b/demo/teaching_assistants.xml +rename from data/teaching_assistants.xml +rename to demo/teaching_assistants.xml diff --git a/doc/howto/howto_website/lectures-action-and-menus b/doc/howto/howto_website/lectures-action-and-menus new file mode 100644 index 00000000000..2f851491c9a --- /dev/null +++ b/doc/howto/howto_website/lectures-action-and-menus @@ -0,0 +1,33 @@ +# HG changeset patch +# Parent 419f2476f7485ffc81eced5233f323c3bea76100 +diff --git a/__openerp__.py b/__openerp__.py +--- a/__openerp__.py ++++ b/__openerp__.py +@@ -5,6 +5,7 @@ + 'data': [ + 'ir.model.access.csv', + 'views/templates.xml', ++ 'data/views.xml', + ], + 'demo': [ + 'demo/teaching_assistants.xml', +diff --git a/data/views.xml b/data/views.xml +new file mode 100644 +--- /dev/null ++++ b/data/views.xml +@@ -0,0 +1,15 @@ ++ ++ ++ ++ Academy lectures ++ academy.lectures ++ ++ ++ ++ ++ ++ ++ diff --git a/doc/howto/howto_website/series b/doc/howto/howto_website/series index 162e9df8bbe..e8b52f313a3 100644 --- a/doc/howto/howto_website/series +++ b/doc/howto/howto_website/series @@ -14,3 +14,5 @@ ta-t-field ta-html-biography ta-template-biography lectures-model-add +data-to-demo +lectures-action-and-menus From f41fde480d3780a31b744ec0653e044458c31661 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 5 Feb 2014 10:13:37 +0100 Subject: [PATCH 13/41] [FIX] rST warnings & errors --- doc/howto/howto_website.rst | 2 +- openerp/http.py | 115 +++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index cc1dba77995..0ca53e49610 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -512,7 +512,7 @@ new record, you can select records to delete them. There's one big issue to fix right now, the labeling of the column in the list and the fields in the form view, which are all currently :guilabel:`unknown`: -.. FIXME:: fix labels +.. FIXME fix labels .. create menu, action .. improve generated views diff --git a/openerp/http.py b/openerp/http.py index 72bb28ba92b..dcd20002a35 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -142,8 +142,8 @@ class WebRequest(object): initialization and setup of the request object (the dispatching itself has to be handled by the subclasses) - :param request: a wrapped werkzeug Request object - :type request: :class:`werkzeug.wrappers.BaseRequest` + :param httprequest: a wrapped werkzeug Request object + :type httprequest: :class:`werkzeug.wrappers.BaseRequest` .. attribute:: httprequest @@ -154,7 +154,7 @@ class WebRequest(object): .. deprecated:: 8.0 - Use ``self.session`` instead. + Use :attr:`session` instead. .. attribute:: params @@ -164,7 +164,7 @@ class WebRequest(object): .. attribute:: session_id - opaque identifier for the :class:`session.OpenERPSession` instance of + opaque identifier for the :class:`OpenERPSession` instance of the current request .. attribute:: session @@ -174,17 +174,18 @@ class WebRequest(object): .. attribute:: context - :class:`~collections.Mapping` of context values for the current request + :class:`~collections.Mapping` of context values for the current + request .. attribute:: db - ``str``, the name of the database linked to the current request. Can be ``None`` - if the current request uses the ``none`` authentication. + ``str``, the name of the database linked to the current request. Can + be ``None`` if the current request uses the ``none`` authentication. .. attribute:: uid - ``int``, the id of the user related to the current request. Can be ``None`` - if the current request uses the ``none`` authenticatoin. + ``int``, the id of the user related to the current request. Can be + ``None`` if the current request uses the ``none`` authentication. """ def __init__(self, httprequest): self.httprequest = httprequest @@ -214,24 +215,25 @@ class WebRequest(object): @property def registry(self): """ - The registry to the database linked to this request. Can be ``None`` if the current request uses the - ``none'' authentication. + The registry to the database linked to this request. Can be ``None`` + if the current request uses the ``none`` authentication. """ return openerp.modules.registry.RegistryManager.get(self.db) if self.db else None @property def db(self): """ - The registry to the database linked to this request. Can be ``None`` if the current request uses the - ``none'' authentication. + The registry to the database linked to this request. Can be ``None`` + if the current request uses the ``none`` authentication. """ return self.session.db if not self.disable_db else None @property def cr(self): """ - The cursor initialized for the current method call. If the current request uses the ``none`` authentication - trying to access this property will raise an exception. + The cursor initialized for the current method call. If the current + request uses the ``none`` authentication trying to access this + property will raise an exception. """ # some magic to lazy create the cr if not self._cr: @@ -305,22 +307,29 @@ class WebRequest(object): def route(route=None, **kw): """ - Decorator marking the decorated method as being a handler for requests. The method must be part of a subclass - of ``Controller``. + Decorator marking the decorated method as being a handler for + requests. The method must be part of a subclass of ``Controller``. - :param route: string or array. The route part that will determine which http requests will match the decorated - method. Can be a single string or an array of strings. See werkzeug's routing documentation for the format of - route expression ( http://werkzeug.pocoo.org/docs/routing/ ). + :param route: string or array. The route part that will determine which + http requests will match the decorated method. Can be a + single string or an array of strings. See werkzeug's routing + documentation for the format of route expression ( + http://werkzeug.pocoo.org/docs/routing/ ). :param type: The type of request, can be ``'http'`` or ``'json'``. :param auth: The type of authentication method, can on of the following: - * ``user``: The user must be authenticated and the current request will perform using the rights of the - user. - * ``admin``: The user may not be authenticated and the current request will perform using the admin user. - * ``none``: The method is always active, even if there is no database. Mainly used by the framework and - authentication modules. There request code will not have any facilities to access the database nor have any - configuration indicating the current database nor the current user. - :param methods: A sequence of http methods this route applies to. If not specified, all methods are allowed. + * ``user``: The user must be authenticated and the current request + will perform using the rights of the user. + * ``admin``: The user may not be authenticated and the current request + will perform using the admin user. + * ``none``: The method is always active, even if there is no + database. Mainly used by the framework and authentication + modules. There request code will not have any facilities to access + the database nor have any configuration indicating the current + database nor the current user. + + :param methods: A sequence of http methods this route applies to. If not + specified, all methods are allowed. :param cors: The Access-Control-Allow-Origin cors directive value. """ routing = kw.copy() @@ -424,7 +433,7 @@ class JsonRequest(WebRequest): response = { 'jsonrpc': '2.0', 'id': self.jsonrequest.get('id') - } + } if error is not None: response['error'] = error if result is not None: @@ -505,8 +514,7 @@ def to_jsonable(o): def jsonrequest(f): """ .. deprecated:: 8.0 - - Use the ``route()`` decorator instead. + Use the :func:`~openerp.http.route` decorator instead. """ base = f.__name__.lstrip('/') if f.__name__ == "index": @@ -584,7 +592,7 @@ def httprequest(f): """ .. deprecated:: 8.0 - Use the ``route()`` decorator instead. + Use the :func:`~openerp.http.route` decorator instead. """ base = f.__name__.lstrip('/') if f.__name__ == "index": @@ -701,7 +709,7 @@ class SessionExpiredException(Exception): class Service(object): """ .. deprecated:: 8.0 - Use ``dispatch_rpc()`` instead. + Use :func:`dispatch_rpc` instead. """ def __init__(self, session, service_name): self.session = session @@ -716,7 +724,7 @@ class Service(object): class Model(object): """ .. deprecated:: 8.0 - Use the resistry and cursor in ``openerp.http.request`` instead. + Use the registry and cursor in :data:`request` instead. """ def __init__(self, session, model): self.session = session @@ -769,10 +777,12 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def authenticate(self, db, login=None, password=None, uid=None): """ - Authenticate the current user with the given db, login and password. If successful, store - the authentication parameters in the current session and request. + Authenticate the current user with the given db, login and + password. If successful, store the authentication parameters in the + current session and request. - :param uid: If not None, that user id will be used instead the login to authenticate the user. + :param uid: If not None, that user id will be used instead the login + to authenticate the user. """ if uid is None: @@ -797,9 +807,9 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def check_security(self): """ - Chech the current authentication parameters to know if those are still valid. This method - should be called at each request. If the authentication fails, a ``SessionExpiredException`` - is raised. + Check the current authentication parameters to know if those are still + valid. This method should be called at each request. If the + authentication fails, a :exc:`SessionExpiredException` is raised. """ if not self.db or not self.uid: raise SessionExpiredException("Session expired") @@ -820,9 +830,8 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def get_context(self): """ - Re-initializes the current user's session context (based on - his preferences) by calling res.users.get_context() with the old - context. + Re-initializes the current user's session context (based on his + preferences) by calling res.users.get_context() with the old context. :returns: the new context """ @@ -855,8 +864,8 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): # Deprecated to be removed in 9 """ - Damn properties for retro-compatibility. All of that is deprecated, all - of that. + Damn properties for retro-compatibility. All of that is deprecated, + all of that. """ @property def _db(self): @@ -886,21 +895,21 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def send(self, service_name, method, *args): """ .. deprecated:: 8.0 - Use ``dispatch_rpc()`` instead. + Use :func:`dispatch_rpc` instead. """ return dispatch_rpc(service_name, method, args) def proxy(self, service): """ .. deprecated:: 8.0 - Use ``dispatch_rpc()`` instead. + Use :func:`dispatch_rpc` instead. """ return Service(self, service) def assert_valid(self, force=False): """ .. deprecated:: 8.0 - Use ``check_security()`` instead. + Use :meth:`check_security` instead. Ensures this session is valid (logged into the openerp server) """ @@ -914,7 +923,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def ensure_valid(self): """ .. deprecated:: 8.0 - Use ``check_security()`` instead. + Use :meth:`check_security` instead. """ if self.uid: try: @@ -925,7 +934,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def execute(self, model, func, *l, **d): """ .. deprecated:: 8.0 - Use the resistry and cursor in ``openerp.addons.web.http.request`` instead. + Use the registry and cursor in :data:`request` instead. """ model = self.model(model) r = getattr(model, func)(*l, **d) @@ -934,7 +943,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def exec_workflow(self, model, id, signal): """ .. deprecated:: 8.0 - Use the resistry and cursor in ``openerp.addons.web.http.request`` instead. + Use the registry and cursor in :data:`request` instead. """ self.assert_valid() r = self.proxy('object').exec_workflow(self.db, self.uid, self.password, model, signal, id) @@ -943,7 +952,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): def model(self, model): """ .. deprecated:: 8.0 - Use the resistry and cursor in ``openerp.addons.web.http.request`` instead. + Use the registry and cursor in :data:`request` instead. Get an RPC proxy for the object ``model``, bound to this session. @@ -1126,8 +1135,8 @@ class Root(object): if statics: _logger.info("HTTP Configuring static files") - app = werkzeug.wsgi.SharedDataMiddleware(self.dispatch, statics) - self.dispatch = DisableCacheMiddleware(app) + app = werkzeug.wsgi.SharedDataMiddleware(self.dispatch, statics) + self.dispatch = DisableCacheMiddleware(app) def setup_session(self, httprequest): # recover or create session From 68eb0983f68a41a1d389f565df65f94a544f43da Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 5 Feb 2014 15:54:50 +0100 Subject: [PATCH 14/41] [ADD] improved scaffolding, controllers scaffolding alter tutorial module to use scaffolded structure --- doc/howto/howto_website.rst | 32 +--- doc/howto/howto_website/basic-controller | 15 -- doc/howto/howto_website/basic-page | 19 +-- doc/howto/howto_website/data-to-demo | 12 +- .../howto_website/lectures-action-and-menus | 7 +- doc/howto/howto_website/lectures-model-add | 44 +++--- doc/howto/howto_website/manifest | 83 ++++++++++- doc/howto/howto_website/module-init | 8 - doc/howto/howto_website/series | 2 - doc/howto/howto_website/ta-controller | 20 +-- doc/howto/howto_website/ta-data | 11 +- doc/howto/howto_website/ta-html-biography | 11 +- doc/howto/howto_website/ta-model | 70 ++++----- doc/howto/howto_website/ta-view-fix | 18 +-- doc/howto/howto_website/templates-basic | 31 ++-- doc/howto/howto_website/url-pattern | 15 +- doc/howto/howto_website/website-dependency | 23 +-- openerpcommand/scaffold.py | 141 +++++++++++------- openerpcommand/templates/__init__.jinja2 | 4 + openerpcommand/templates/__openerp__.jinja2 | 24 +++ openerpcommand/templates/controllers.jinja2 | 9 ++ .../templates/ir.model.access.jinja2 | 6 + openerpcommand/templates/models.jinja2 | 9 ++ 23 files changed, 362 insertions(+), 252 deletions(-) delete mode 100644 doc/howto/howto_website/basic-controller delete mode 100644 doc/howto/howto_website/module-init create mode 100644 openerpcommand/templates/__init__.jinja2 create mode 100644 openerpcommand/templates/__openerp__.jinja2 create mode 100644 openerpcommand/templates/controllers.jinja2 create mode 100644 openerpcommand/templates/ir.model.access.jinja2 create mode 100644 openerpcommand/templates/models.jinja2 diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 0ca53e49610..7eccd24935f 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -22,31 +22,15 @@ 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? +.. code:: shell-session - * Create empty module (mandatory name, category) - * Create controller (parent class?) - * Create model (concrete/abstract? Inherit?) - * Add field? + > oe scaffold Academy -* 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:: + :hidden: - .. 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). +This builds a basic module for you, ignore anything in the ``models`` and +``security`` directories for now. .. todo:: @@ -66,8 +50,8 @@ 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: +Go to :file:`academy/controllers/my_controller.py` and change the string +returned by the ``index`` method to get a more page-ish output: .. patch:: diff --git a/doc/howto/howto_website/basic-controller b/doc/howto/howto_website/basic-controller deleted file mode 100644 index 4415d9516bc..00000000000 --- a/doc/howto/howto_website/basic-controller +++ /dev/null @@ -1,15 +0,0 @@ -# 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 index 5a60c346acf..9e6c9d9abc7 100644 --- a/doc/howto/howto_website/basic-page +++ b/doc/howto/howto_website/basic-page @@ -1,11 +1,11 @@ # HG changeset patch -# Parent b377930cec8f9445882bb3268f9f5fac71dd8c15 +# Parent a76a9a0e0668f4191bdc383a0d4b3173f44b39b1 -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): +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -6,4 +6,16 @@ from openerp.addons.web.controllers impo + class my_controller(main.Home): @http.route('/', auth='none') def index(self): - return "Hello, world!" @@ -18,12 +18,7 @@ diff --git a/controllers.py b/controllers.py + +

    Introduction to a thing

    +

    Course description

    -+

    -+ 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. -+

    ++

    Course introduction

    + + +""" diff --git a/doc/howto/howto_website/data-to-demo b/doc/howto/howto_website/data-to-demo index 4c0797f0543..2be34f484cf 100644 --- a/doc/howto/howto_website/data-to-demo +++ b/doc/howto/howto_website/data-to-demo @@ -1,11 +1,12 @@ # HG changeset patch -# Parent 2af29a429acda61e5e567997dad78a673e011796 +# Parent 8799d7578ebf7aa0d81f0dbafa959f8abd106dff + diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py +++ b/__openerp__.py -@@ -5,7 +5,9 @@ +@@ -19,8 +19,10 @@ 'data': [ - 'ir.model.access.csv', + 'security/ir.model.access.csv', 'views/templates.xml', - 'data/teaching_assistants.xml', - 'data/lectures.xml', @@ -13,8 +14,9 @@ diff --git a/__openerp__.py b/__openerp__.py + 'demo': [ + 'demo/teaching_assistants.xml', + 'demo/lectures.xml', - ] - } + ], + 'tests': [ + ], diff --git a/data/lectures.xml b/demo/lectures.xml rename from data/lectures.xml rename to demo/lectures.xml diff --git a/doc/howto/howto_website/lectures-action-and-menus b/doc/howto/howto_website/lectures-action-and-menus index 2f851491c9a..3ca5c055f39 100644 --- a/doc/howto/howto_website/lectures-action-and-menus +++ b/doc/howto/howto_website/lectures-action-and-menus @@ -1,11 +1,12 @@ # HG changeset patch -# Parent 419f2476f7485ffc81eced5233f323c3bea76100 +# Parent f8963c3ab009d422767aaaaa29f8ce08f84ac299 + diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py +++ b/__openerp__.py -@@ -5,6 +5,7 @@ +@@ -19,6 +19,7 @@ 'data': [ - 'ir.model.access.csv', + 'security/ir.model.access.csv', 'views/templates.xml', + 'data/views.xml', ], diff --git a/doc/howto/howto_website/lectures-model-add b/doc/howto/howto_website/lectures-model-add index dd53130721d..a467817faad 100644 --- a/doc/howto/howto_website/lectures-model-add +++ b/doc/howto/howto_website/lectures-model-add @@ -1,21 +1,22 @@ # HG changeset patch -# Parent 65912bc56408d6bf61b2023a79a48e06a22fe9e2 +# Parent 9042ace1e3e8175155d9dbed75657222a371cdb6 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py +++ b/__openerp__.py -@@ -6,5 +6,6 @@ - 'ir.model.access.csv', +@@ -20,6 +20,7 @@ + 'security/ir.model.access.csv', 'views/templates.xml', 'data/teaching_assistants.xml', + 'data/lectures.xml', - ] - } -diff --git a/controllers.py b/controllers.py ---- a/controllers.py -+++ b/controllers.py -@@ -4,10 +4,15 @@ from openerp.addons.web.controllers impo - class Home(main.Home): + ], + 'tests': [ + ], +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -6,10 +6,15 @@ from openerp.addons.web.controllers impo + class my_controller(main.Home): @http.route('/', auth='public') def index(self): + cr, uid, context = http.request.cr, http.request.uid, http.request.context @@ -59,17 +60,10 @@ new file mode 100644 + + + -diff --git a/ir.model.access.csv b/ir.model.access.csv ---- a/ir.model.access.csv -+++ b/ir.model.access.csv -@@ -1,2 +1,3 @@ - id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink - access_academy_tas,access_academy_tas,model_academy_tas,,1,0,0,0 -+access_academy_lectures,access_academy_lectures,model_academy_lectures,,1,0,0,0 -diff --git a/models.py b/models.py ---- a/models.py -+++ b/models.py -@@ -9,3 +9,12 @@ class TeachingAssistants(orm.Model): +diff --git a/models/my_model.py b/models/my_model.py +--- a/models/my_model.py ++++ b/models/my_model.py +@@ -8,3 +8,12 @@ class TeachingAssistants(orm.Model): 'name': fields.char(), 'biography': fields.html(), } @@ -82,6 +76,14 @@ diff --git a/models.py b/models.py + 'name': fields.char(required=True), + 'date': fields.date(required=True), + } +diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv +--- a/security/ir.model.access.csv ++++ b/security/ir.model.access.csv +@@ -1,2 +1,3 @@ + id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink + access_academy_tas,access_academy_tas,model_academy_tas,,1,0,0,0 ++access_academy_lectures,access_academy_lectures,model_academy_lectures,,1,0,0,0 +\ No newline at end of file diff --git a/views/templates.xml b/views/templates.xml --- a/views/templates.xml +++ b/views/templates.xml diff --git a/doc/howto/howto_website/manifest b/doc/howto/howto_website/manifest index 3cf359c9b30..3c81585b522 100644 --- a/doc/howto/howto_website/manifest +++ b/doc/howto/howto_website/manifest @@ -1,11 +1,90 @@ # HG changeset patch # Parent 0000000000000000000000000000000000000000 + +diff --git a/__init__.py b/__init__.py +new file mode 100644 +--- /dev/null ++++ b/__init__.py +@@ -0,0 +1,4 @@ ++# -*- coding: utf-8 -*- ++import controllers ++import models ++ diff --git a/__openerp__.py b/__openerp__.py new file mode 100644 --- /dev/null +++ b/__openerp__.py -@@ -0,0 +1,4 @@ +@@ -0,0 +1,22 @@ ++# -*- coding: utf-8 -*- +{ + 'name': "Academy", -+ 'category': "Tools", ++ # short description, used as subtitles on modules listings ++ 'summary': "", ++ # long description of module purpose ++ 'description': """ ++""", ++ # Who you are ++ 'author': "", ++ 'website': "", ++ ++ # categories can be used to filter modules in modules listing ++ 'category': 'Uncategorized', ++ 'version': '0.1', ++ ++ # any module necessary for this one to work correctly ++ 'depends': ['web'], ++ 'data': ['security/ir.model.access.csv'], ++ 'tests': [ ++ ], +} +diff --git a/controllers/__init__.py b/controllers/__init__.py +new file mode 100644 +--- /dev/null ++++ b/controllers/__init__.py +@@ -0,0 +1,3 @@ ++# -*- coding: utf-8 -*- ++import my_controller ++ +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +new file mode 100644 +--- /dev/null ++++ b/controllers/my_controller.py +@@ -0,0 +1,9 @@ ++# -*- coding: utf-8 -*- ++ ++from openerp import http ++from openerp.addons.web.controllers import main ++ ++class my_controller(main.Home): ++ @http.route('/', auth='none') ++ def index(self): ++ return "Hello, world!" +diff --git a/models/__init__.py b/models/__init__.py +new file mode 100644 +--- /dev/null ++++ b/models/__init__.py +@@ -0,0 +1,3 @@ ++# -*- coding: utf-8 -*- ++import my_model ++ +diff --git a/models/my_model.py b/models/my_model.py +new file mode 100644 +--- /dev/null ++++ b/models/my_model.py +@@ -0,0 +1,9 @@ ++# -*- coding: utf-8 -*- ++from openerp.osv import orm, fields ++ ++class my_model(orm.Model): ++ _name = "academy.my_model" ++ ++ _columns = { ++ 'name': fields.char(), ++ } +diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv +new file mode 100644 +--- /dev/null ++++ b/security/ir.model.access.csv +@@ -0,0 +1,2 @@ ++id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink ++access_academy_my_model,access_academy_my_model,model_academy_my_model,,1,0,0,0 diff --git a/doc/howto/howto_website/module-init b/doc/howto/howto_website/module-init deleted file mode 100644 index 4484236edc9..00000000000 --- a/doc/howto/howto_website/module-init +++ /dev/null @@ -1,8 +0,0 @@ -# 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 index e8b52f313a3..d34c6476bb7 100644 --- a/doc/howto/howto_website/series +++ b/doc/howto/howto_website/series @@ -1,6 +1,4 @@ manifest -basic-controller -module-init basic-page ta-controller url-pattern diff --git a/doc/howto/howto_website/ta-controller b/doc/howto/howto_website/ta-controller index 5b8d0b799d5..080111bb4d4 100644 --- a/doc/howto/howto_website/ta-controller +++ b/doc/howto/howto_website/ta-controller @@ -1,10 +1,10 @@ # HG changeset patch -# Parent 30a859b5dc378c0da751537b1342e8d22775ad44 +# Parent a615de71be483d88acca032ad5d35072c87999c0 -diff --git a/controllers.py b/controllers.py ---- a/controllers.py -+++ b/controllers.py -@@ -1,9 +1,22 @@ +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -3,9 +3,22 @@ from openerp import http from openerp.addons.web.controllers import main @@ -16,7 +16,7 @@ diff --git a/controllers.py b/controllers.py + {'name': "Tanya Harris"}, +] + - class Home(main.Home): + class my_controller(main.Home): @http.route('/', auth='none') def index(self): + tas = [ @@ -27,10 +27,10 @@ diff --git a/controllers.py b/controllers.py return """ -@@ -19,6 +32,26 @@ class Home(main.Home): - will focus on the discovery of things and the planning and - organization necessary to handle things. -

    +@@ -16,6 +29,26 @@ class my_controller(main.Home): +

    Introduction to a thing

    +

    Course description

    +

    Course introduction

    +

    Teaching Assistants

    +
      + %(tas)s diff --git a/doc/howto/howto_website/ta-data b/doc/howto/howto_website/ta-data index c38eae470ed..395b5a2b430 100644 --- a/doc/howto/howto_website/ta-data +++ b/doc/howto/howto_website/ta-data @@ -1,16 +1,17 @@ # HG changeset patch -# Parent 94316d8049d7453cf70aff198b2d7ad1c04bf089 +# Parent a35b5f4903087b1b31a4ecf33bfe655dc3ad5663 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py +++ b/__openerp__.py -@@ -5,5 +5,6 @@ +@@ -19,6 +19,7 @@ 'data': [ - 'ir.model.access.csv', + 'security/ir.model.access.csv', 'views/templates.xml', + 'data/teaching_assistants.xml', - ] - } + ], + 'tests': [ + ], diff --git a/data/teaching_assistants.xml b/data/teaching_assistants.xml new file mode 100644 --- /dev/null diff --git a/doc/howto/howto_website/ta-html-biography b/doc/howto/howto_website/ta-html-biography index 5d9dbc0ab09..23da32b1e4e 100644 --- a/doc/howto/howto_website/ta-html-biography +++ b/doc/howto/howto_website/ta-html-biography @@ -1,9 +1,10 @@ # HG changeset patch -# Parent e603b52f5a0484822964f6cefd7e5b389d44399b -diff --git a/models.py b/models.py ---- a/models.py -+++ b/models.py -@@ -7,4 +7,5 @@ class TeachingAssistants(orm.Model): +# Parent 8cbdbbeaf1d89c9a4e4d03e2392ddcc79a648206 + +diff --git a/models/my_model.py b/models/my_model.py +--- a/models/my_model.py ++++ b/models/my_model.py +@@ -6,4 +6,5 @@ class TeachingAssistants(orm.Model): _columns = { 'name': fields.char(), diff --git a/doc/howto/howto_website/ta-model b/doc/howto/howto_website/ta-model index 7b9917cb85a..83a74c83c51 100644 --- a/doc/howto/howto_website/ta-model +++ b/doc/howto/howto_website/ta-model @@ -1,27 +1,10 @@ # HG changeset patch -# Parent 9735c655933b94f5e9017d0aac0b6e579f23adba +# Parent b6ba23a3c284db481f14d9ea573e0baf8d3320e8 -diff --git a/__init__.py b/__init__.py ---- a/__init__.py -+++ b/__init__.py -@@ -1,1 +1,2 @@ - import controllers -+import models -diff --git a/__openerp__.py b/__openerp__.py ---- a/__openerp__.py -+++ b/__openerp__.py -@@ -3,6 +3,7 @@ - 'category': "Tools", - 'depends': ['website'], - 'data': [ -+ 'ir.model.access.csv', - 'views/templates.xml', - ] - } -diff --git a/controllers.py b/controllers.py ---- a/controllers.py -+++ b/controllers.py -@@ -1,19 +1,13 @@ +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -3,19 +3,13 @@ from openerp import http from openerp.addons.web.controllers import main @@ -33,7 +16,7 @@ diff --git a/controllers.py b/controllers.py - {'name': "Tanya Harris"}, -] - - class Home(main.Home): + class my_controller(main.Home): @http.route('/', auth='public') def index(self): + tas = http.request.registry['academy.tas'].search_read( @@ -44,25 +27,24 @@ diff --git a/controllers.py b/controllers.py }) @http.route('/tas//', auth='public', website=True) -diff --git a/ir.model.access.csv b/ir.model.access.csv -new file mode 100644 ---- /dev/null -+++ b/ir.model.access.csv -@@ -0,0 +1,2 @@ -+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -+access_academy_tas,access_academy_tas,model_academy_tas,,1,0,0,0 -diff --git a/models.py b/models.py -new file mode 100644 ---- /dev/null -+++ b/models.py -@@ -0,0 +1,10 @@ -+# -*- coding: utf-8 -*- -+ -+from openerp.osv import orm, fields -+ +diff --git a/models/my_model.py b/models/my_model.py +--- a/models/my_model.py ++++ b/models/my_model.py +@@ -1,8 +1,8 @@ + # -*- coding: utf-8 -*- + from openerp.osv import orm, fields + +-class my_model(orm.Model): +- _name = "academy.my_model" +class TeachingAssistants(orm.Model): -+ _name = 'academy.tas' -+ -+ _columns = { -+ 'name': fields.char(), -+ } ++ _name = "academy.tas" + + _columns = { + 'name': fields.char(), +diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv +--- a/security/ir.model.access.csv ++++ b/security/ir.model.access.csv +@@ -1,2 +1,2 @@ + id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +-access_academy_my_model,access_academy_my_model,model_academy_my_model,,1,0,0,0 ++access_academy_tas,access_academy_tas,model_academy_tas,,1,0,0,0 diff --git a/doc/howto/howto_website/ta-view-fix b/doc/howto/howto_website/ta-view-fix index 88fcdef1787..dac105dba9e 100644 --- a/doc/howto/howto_website/ta-view-fix +++ b/doc/howto/howto_website/ta-view-fix @@ -1,19 +1,19 @@ # HG changeset patch -# Parent d757ab6e2223e63f283b31815c8ff650ea42e2e7 -diff --git a/controllers.py b/controllers.py ---- a/controllers.py -+++ b/controllers.py -@@ -10,6 +10,8 @@ class Home(main.Home): +# Parent fa3e25d0315e54de4bd983ad8532044b5e2df233 + +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -12,6 +12,8 @@ class my_controller(main.Home): 'tas': tas, }) - @http.route('/tas//', auth='public', website=True) -- def ta(self, id): -- return http.request.website.render('academy.ta', teaching_assistants[id]) + @http.route('/tas//', auth='public', website=True) -+ def ta(self, ta): + def ta(self, id): +- return http.request.website.render('academy.ta', teaching_assistants[id]) + return http.request.website.render('academy.ta', { -+ 'ta': ta ++ 'ta': ta, + }) diff --git a/views/templates.xml b/views/templates.xml --- a/views/templates.xml diff --git a/doc/howto/howto_website/templates-basic b/doc/howto/howto_website/templates-basic index ebce6f468bd..b0e5d85c487 100644 --- a/doc/howto/howto_website/templates-basic +++ b/doc/howto/howto_website/templates-basic @@ -1,21 +1,25 @@ # HG changeset patch -# Parent 0e882bf90a845788e155b437baf2b42c98901216 +# Parent 170cc87a26983d34df5cd3bb27d3259722c586e5 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py +++ b/__openerp__.py -@@ -1,4 +1,7 @@ - { - 'name': "Academy", - 'category': "Tools", +@@ -16,7 +16,10 @@ + + # any module necessary for this one to work correctly + 'depends': ['web'], +- 'data': ['security/ir.model.access.csv'], + 'data': [ ++ 'security/ir.model.access.csv', + 'views/templates.xml', -+ ] ++ ], + 'tests': [ + ], } -diff --git a/controllers.py b/controllers.py ---- a/controllers.py -+++ b/controllers.py -@@ -17,41 +17,10 @@ class Home(main.Home): +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -19,36 +19,10 @@ class my_controller(main.Home): for i, ta in enumerate(teaching_assistants) ] @@ -28,12 +32,7 @@ diff --git a/controllers.py b/controllers.py - -

      Introduction to a thing

      -

      Course description

      --

      -- 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. --

      +-

      Course introduction

      -

      Teaching Assistants

      -
        - %(tas)s diff --git a/doc/howto/howto_website/url-pattern b/doc/howto/howto_website/url-pattern index 8f37b1bdcda..72be995a7b8 100644 --- a/doc/howto/howto_website/url-pattern +++ b/doc/howto/howto_website/url-pattern @@ -1,9 +1,10 @@ # 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): +# Parent 1d6a01fae0bb650ea0de8437b3983a29f66463ed + +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -15,7 +15,7 @@ class my_controller(main.Home): @http.route('/', auth='none') def index(self): tas = [ @@ -12,7 +13,7 @@ diff --git a/controllers.py b/controllers.py for i, ta in enumerate(teaching_assistants) ] -@@ -42,7 +42,7 @@ class Home(main.Home): +@@ -39,7 +39,7 @@ class my_controller(main.Home): 'tas': '\n'.join(tas) } @@ -21,7 +22,7 @@ diff --git a/controllers.py b/controllers.py def ta(self, id): return """ -@@ -54,4 +54,4 @@ class Home(main.Home): +@@ -51,4 +51,4 @@ class my_controller(main.Home):

        %(name)s

        diff --git a/doc/howto/howto_website/website-dependency b/doc/howto/howto_website/website-dependency index 51bc6a6c9df..6910aff199e 100644 --- a/doc/howto/howto_website/website-dependency +++ b/doc/howto/howto_website/website-dependency @@ -1,24 +1,25 @@ # HG changeset patch -# Parent 77db36690ddd8ad5065cab77837deec9da3df502 +# Parent 5426218c6da91a13911e64eeb18a0cc2e19083c7 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py +++ b/__openerp__.py -@@ -1,6 +1,7 @@ - { - 'name': "Academy", - 'category': "Tools", +@@ -15,7 +15,7 @@ + 'version': '0.1', + + # any module necessary for this one to work correctly +- 'depends': ['web'], + 'depends': ['website'], 'data': [ + 'security/ir.model.access.csv', 'views/templates.xml', - ] -diff --git a/controllers.py b/controllers.py ---- a/controllers.py -+++ b/controllers.py -@@ -10,17 +10,12 @@ teaching_assistants = [ +diff --git a/controllers/my_controller.py b/controllers/my_controller.py +--- a/controllers/my_controller.py ++++ b/controllers/my_controller.py +@@ -12,17 +12,12 @@ teaching_assistants = [ ] - class Home(main.Home): + class my_controller(main.Home): - @http.route('/', auth='none') + @http.route('/', auth='public') def index(self): diff --git a/openerpcommand/scaffold.py b/openerpcommand/scaffold.py index e590653c91b..845122dcb75 100644 --- a/openerpcommand/scaffold.py +++ b/openerpcommand/scaffold.py @@ -2,25 +2,46 @@ Generate an OpenERP module skeleton. """ +import functools +import keyword import os +import re import sys +import jinja2 + +# FIXME: add logging def run(args): + env = jinja2.Environment(loader=jinja2.PackageLoader( + 'openerpcommand', 'templates')) + env.filters['snake'] = snake assert args.module - module = args.module + args.dependency = 'web' if args.controller else 'base' - if os.path.exists(module): - print "The path `%s` already exists." - sys.exit(1) + module = functools.partial(os.path.join, snake(args.module)) - os.mkdir(module) - os.mkdir(os.path.join(module, 'models')) - with open(os.path.join(module, '__openerp__.py'), 'w') as h: - h.write(MANIFEST) - with open(os.path.join(module, '__init__.py'), 'w') as h: - h.write(INIT_PY) - with open(os.path.join(module, 'models', '__init__.py'), 'w') as h: - h.write(MODELS_PY % (module,)) + if os.path.exists(module()): + message = "The path `%s` already exists." % module() + die(message) + + dump(env, '__openerp__.jinja2', module('__openerp__.py'), config=args) + dump(env, '__init__.jinja2', module('__init__.py'), modules=[ + args.controller and 'controllers', + args.model and 'models' + ]) + dump(env, 'ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) + + if args.controller: + controller_module = snake(args.controller) + dump(env, '__init__.jinja2', module('controllers', '__init__.py'), modules=[controller_module]) + dump(env, 'controllers.jinja2', + module('controllers', '%s.py' % controller_module), + config=args) + + if args.model: + model_module = snake(args.model) + dump(env, '__init__.jinja2', module('models', '__init__.py'), modules=[model_module]) + dump(env, 'models.jinja2', module('models', '%s.py' % model_module), config=args) def add_parser(subparsers): parser = subparsers.add_parser('scaffold', @@ -28,50 +49,64 @@ def add_parser(subparsers): parser.add_argument('module', metavar='MODULE', help='the name of the generated module') - parser.set_defaults(run=run) + controller = parser.add_mutually_exclusive_group() + controller.add_argument('--controller', type=identifier, + help="The name of the controller to generate (default: %(default)s)") + controller.add_argument('--no-controller', dest='controller', + action='store_const', const=None, help="Do not generate a controller") -MANIFEST = """\ -# -*- coding: utf-8 -*- -{ - 'name': '', - 'version': '0.0', - 'category': '', - 'description': ''' - -''', - 'author': '', - 'maintainer': '', - 'website': 'http://', - # Add any module that are necessary for this module to correctly work in - # the `depends` list. - 'depends': ['base'], - 'data': [ - ], - 'test': [ - ], - # Set to False if you want to prevent the module to be known by OpenERP - # (and thus appearing in the list of modules). - 'installable': True, - # Set to True if you want the module to be automatically whenever all its - # dependencies are installed. - 'auto_install': False, -} -""" + model = parser.add_mutually_exclusive_group() + model.add_argument('--model', type=identifier, + help="The name of the model to generate (default: %(default)s)") + model.add_argument('--no-model', dest='model', + action='store_const', const=None, help="Do not generate a model") -INIT_PY = """\ -# -*- coding: utf-8 -*- -import models -""" + mod = parser.add_argument_group("Module information", + "these are added to the module metadata and displayed on e.g. " + "apps.openerp.com. For company-backed modules, the company " + "information should be used") + mod.add_argument('--name', dest='author_name', default="", + help="Name of the module author") + mod.add_argument('--website', dest='author_website', default="", + help="Website of the module author") + mod.add_argument('--category', default="Uncategorized", + help="Broad categories to which the module belongs, used for " + "filtering within OpenERP and on apps.openerp.com. " + "Defaults to %(default)s") + mod.add_argument('--summary', default="", + help="Short (1 phrase/line) summary of the module's purpose, used as " + "subtitle on modules listing or apps.openerp.com") -MODELS_PY = """\ -# -*- coding: utf-8 -*- -import openerp + parser.set_defaults(run=run, controller='my_controller', model='my_model') -# Define a new model. -class my_model(openerp.osv.osv.Model): +def snake(s): + """ snake cases ``s`` - _name = '%s.my_model' + :param str s: + :return: str + """ + # insert a space before each uppercase character preceded by a + # non-uppercase letter + s = re.sub(r'(?<=[^A-Z])\B([A-Z])', r' \1', s) + # lowercase everything, split on whitespace and join + return '_'.join(s.lower().split()) - _columns = { - } -""" +def dump(env, template, dest, **kwargs): + outdir = os.path.dirname(dest) + if not os.path.exists(outdir): + os.makedirs(outdir) + env.get_template(template).stream(**kwargs).dump(dest) + # add trailing newline which jinja removes + with open(dest, 'a') as f: + f.write('\n') + +def identifier(s): + if keyword.iskeyword(s): + die("%s is a Python keyword and can not be used as a name" % s) + if not re.match('[A-Za-z_][A-Za-z0-9_]*', s): + die("%s is not a valid Python identifier" % s) + return s + +def die(message, code=1): + print >>sys.stderr, message + sys.exit(code) diff --git a/openerpcommand/templates/__init__.jinja2 b/openerpcommand/templates/__init__.jinja2 new file mode 100644 index 00000000000..0124cdd2d93 --- /dev/null +++ b/openerpcommand/templates/__init__.jinja2 @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +{% for module in modules if module -%} +import {{ module }} +{% endfor %} diff --git a/openerpcommand/templates/__openerp__.jinja2 b/openerpcommand/templates/__openerp__.jinja2 new file mode 100644 index 00000000000..d37a6f33334 --- /dev/null +++ b/openerpcommand/templates/__openerp__.jinja2 @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +{ + 'name': "{{ config.module }}", + # short description, used as subtitles on modules listings + 'summary': "{{ config.summary }}", + # long description of module purpose + 'description': """ +""", + # Who you are + 'author': "{{ config.author_name }}", + 'website': "{{ config.author_website }}", + + # categories can be used to filter modules in modules listing + 'category': '{{ config.category }}', + 'version': '0.1', + + # any module necessary for this one to work correctly + 'depends': ['{{ config.dependency }}'], + 'data': [ + {{- "'security/ir.model.access.csv'" if config.model -}} + ], + 'tests': [ + ], +} diff --git a/openerpcommand/templates/controllers.jinja2 b/openerpcommand/templates/controllers.jinja2 new file mode 100644 index 00000000000..3cc47365d40 --- /dev/null +++ b/openerpcommand/templates/controllers.jinja2 @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +from openerp import http +from openerp.addons.web.controllers import main + +class {{ config.controller }}(main.Home): + @http.route('/', auth='none') + def index(self): + return "Hello, world!" diff --git a/openerpcommand/templates/ir.model.access.jinja2 b/openerpcommand/templates/ir.model.access.jinja2 new file mode 100644 index 00000000000..e5e2fb35fe7 --- /dev/null +++ b/openerpcommand/templates/ir.model.access.jinja2 @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +{% if config.model -%} +access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} +access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} +model_{{ config.module|snake }}_{{ config.model|snake }},,1,0,0,0 +{%- endif %} diff --git a/openerpcommand/templates/models.jinja2 b/openerpcommand/templates/models.jinja2 new file mode 100644 index 00000000000..878bf9be4f6 --- /dev/null +++ b/openerpcommand/templates/models.jinja2 @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +from openerp.osv import orm, fields + +class {{ config.model }}(orm.Model): + _name = "{{ config.module|snake }}.{{ config.model|snake }}" + + _columns = { + 'name': fields.char(), + } From 0ea465e8a34876a0fed25a120f49ada9c692aaa3 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 6 Feb 2014 11:25:13 +0100 Subject: [PATCH 15/41] [IMP] simplify howto wording, add modules directory (output) to scaffold --- doc/howto/howto_website.rst | 17 ++++++++--------- openerpcommand/scaffold.py | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 7eccd24935f..452d83d1aca 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -22,9 +22,11 @@ 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: -.. code:: shell-session +.. todo:: output directory probably shouldn't be ``.`` - > oe scaffold Academy +.. code-block:: console + + $ oe scaffold Academy . .. patch:: :hidden: @@ -44,10 +46,8 @@ 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 +Let's prettify things a bit: instead of returning just a bit of text, +we can return a page, and use a tool like bootstrap_ to get a nicer rendering than the default. Go to :file:`academy/controllers/my_controller.py` and change the string @@ -66,10 +66,9 @@ 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). +usefulness (you could do that with static files in the first place). -But you can also create controllers which use data provided in the access URL, +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. diff --git a/openerpcommand/scaffold.py b/openerpcommand/scaffold.py index 845122dcb75..4bbc7cdc503 100644 --- a/openerpcommand/scaffold.py +++ b/openerpcommand/scaffold.py @@ -15,10 +15,10 @@ def run(args): env = jinja2.Environment(loader=jinja2.PackageLoader( 'openerpcommand', 'templates')) env.filters['snake'] = snake - assert args.module args.dependency = 'web' if args.controller else 'base' - module = functools.partial(os.path.join, snake(args.module)) + module = functools.partial( + os.path.join, args.modules_dir, snake(args.module)) if os.path.exists(module()): message = "The path `%s` already exists." % module() @@ -48,6 +48,8 @@ def add_parser(subparsers): description='Generate an OpenERP module skeleton.') parser.add_argument('module', metavar='MODULE', help='the name of the generated module') + parser.add_argument('modules_dir', metavar='DIRECTORY', type=directory, + help="Modules directory in which the new module should be generated") controller = parser.add_mutually_exclusive_group() controller.add_argument('--controller', type=identifier, @@ -107,6 +109,14 @@ def identifier(s): die("%s is not a valid Python identifier" % s) return s +def directory(p): + expanded = os.path.abspath( + os.path.expanduser( + os.path.expandvars(p))) + if not os.path.isdir(expanded): + die("Directory %s does not seem to exist" % p) + return expanded + def die(message, code=1): print >>sys.stderr, message sys.exit(code) From 66d8934802d6d15ef5b5d2be6dd5e4644bf2dda5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 7 Feb 2014 11:03:02 +0100 Subject: [PATCH 16/41] [FIX] correctly handle get_inheriting_views_arch when uid=None --- openerp/addons/base/ir/ir_ui_view.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py index e898492a762..219cc991d2a 100644 --- a/openerp/addons/base/ir/ir_ui_view.py +++ b/openerp/addons/base/ir/ir_ui_view.py @@ -265,7 +265,8 @@ class view(osv.osv): :return: [(view_arch,view_id), ...] """ - user_groups = frozenset(self.pool.get('res.users').browse(cr, 1, uid, context).groups_id) + user = self.pool['res.users'].browse(cr, 1, uid, context=context) + user_groups = frozenset(user.groups_id or ()) check_view_ids = context and context.get('check_view_ids') or (0,) conditions = [['inherit_id', '=', view_id], ['model', '=', model]] From cfc7015355848629cdc7f7d9fde795c929eec093 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 7 Feb 2014 11:11:57 +0100 Subject: [PATCH 17/41] [FIX] templating section, some wording --- doc/howto/howto_website.rst | 57 +++++++++++++++------- doc/howto/howto_website/templates-basic | 22 ++++++--- doc/howto/howto_website/website-dependency | 13 +++-- doc/howto/howto_website/website-layoutify | 8 +-- 4 files changed, 68 insertions(+), 32 deletions(-) diff --git a/doc/howto/howto_website.rst b/doc/howto/howto_website.rst index 452d83d1aca..65a6ed18327 100644 --- a/doc/howto/howto_website.rst +++ b/doc/howto/howto_website.rst @@ -31,13 +31,29 @@ create a module: .. patch:: :hidden: -This builds a basic module for you, ignore anything in the ``models`` and -``security`` directories for now. +This builds a basic module for you: + +.. code-block:: text + + academy + ├── __init__.py + ├── __openerp__.py + ├── controllers + │   ├── __init__.py + │   └── my_controller.py + ├── models + │   ├── __init__.py + │   └── my_model.py + └── security + └── ir.model.access.csv + +Ignore anything in the ``models`` and ``security`` directories for now. .. todo:: * instructions for start & install * db handling + - if existing db, automatically selected - if no existing db, nodb -> login -> login of first db - dbfilter @@ -46,6 +62,8 @@ 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. +.. todo:: screenshot? + Let's prettify things a bit: instead of returning just a bit of text, we can return a page, and use a tool like bootstrap_ to get a nicer rendering than the default. @@ -57,21 +75,28 @@ returned by the ``index`` method to get a more page-ish output: .. 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. + this example requires internet access 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. + +.. todo:: screenshot 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). +usefulness (you could do that with static files). -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. +You can also create dynamic pages which use data provided in the URL, +for instance so a single controller generates multiple pages. Any +query parameter (``?name=value``) is passed as a string parameter to the +controller method. + +For instance, the index page can display a list of teaching assistants linking +to a page for each assistant through their index in a global array. Each +assistant's page will simply print their name by applying the index to the +array: .. patch:: @@ -89,16 +114,14 @@ This can be done by adding `converter patterns`_ to the URL in 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). +``404 Not Found`` instead of a 500 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. +So far we've output HTML by munging strings. 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 diff --git a/doc/howto/howto_website/templates-basic b/doc/howto/howto_website/templates-basic index b0e5d85c487..e3475046b2d 100644 --- a/doc/howto/howto_website/templates-basic +++ b/doc/howto/howto_website/templates-basic @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 170cc87a26983d34df5cd3bb27d3259722c586e5 +# Parent 0792d59a4a456e1ce70d8aa4cb1784632883d714 diff --git a/__openerp__.py b/__openerp__.py --- a/__openerp__.py @@ -19,7 +19,13 @@ diff --git a/__openerp__.py b/__openerp__.py diff --git a/controllers/my_controller.py b/controllers/my_controller.py --- a/controllers/my_controller.py +++ b/controllers/my_controller.py -@@ -19,36 +19,10 @@ class my_controller(main.Home): +@@ -14,41 +14,18 @@ teaching_assistants = [ + class my_controller(main.Home): + @http.route('/', auth='none') + def index(self): ++ cr, uid, context = http.request.cr, http.request.uid, http.request.context + tas = [ + '
      • %s
      • ' % (i, ta['name']) for i, ta in enumerate(teaching_assistants) ] @@ -42,9 +48,9 @@ diff --git a/controllers/my_controller.py b/controllers/my_controller.py -""" % { - 'tas': '\n'.join(tas) - } -+ return "" % { ++ return http.request.registry['ir.ui.view'].render(cr, uid, 'academy.index', { + 'tas': '\n'.join(tas) -+ } ++ }, context=context) @http.route('/tas//', auth='none') def ta(self, id): @@ -59,7 +65,9 @@ diff --git a/controllers/my_controller.py b/controllers/my_controller.py - - -""" % teaching_assistants[id] -+ return "" % teaching_assistants[id] ++ cr, uid, context = http.request.cr, http.request.uid, http.request.context ++ return http.request.registry['ir.ui.view'].render( ++ cr, uid, "academy.tas", teaching_assistants[id], context=context) diff --git a/views/templates.xml b/views/templates.xml new file mode 100644 --- /dev/null @@ -67,7 +75,7 @@ new file mode 100644 @@ -0,0 +1,39 @@ + + -+