0

I'm using a Cookiecutter Pyramid web development framework. This has three linked files:

utils.py - defines the random cache string to add to an url

views.py - passes utils functions to chameleon template

layout.pt - chameleon template calling static css urls etc.

In layout.pt pre-cache-busting there is a link that says:

<link href="${request.static_url('pycharm_app:static/theme.css')}" rel="stylesheet">

I'm trying to edit this link to call the build_cache_id function as so:

 <link href="/static/theme.css?cacheId=${build_cache_id('/static/theme.css')}" rel="stylesheet">

but get error:

NameError: build_cache_id

 - Expression: "build_cache_id('/static/theme.css')"
 - Filename:   ... s/first_business_website/pycharm_app/templates/layout.pt
 - Location:   (line 17: col 43)
 - Source:     ... ss?cacheId=${build_cache_id('/static/theme.css')}" rel="styl ...
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - Expression: "load: layout.pt"
 - Filename:   ... rst_business_website/pycharm_app/templates/mytemplate.pt
 - Location:   (line 1: col 22)
 - Source:     <div metal:use-macro="load: layout.pt">
                                     ^^^^^^^^^^^^^^^
 - Arguments:  view: <function my_view at 0x109eff8b0>
               renderer_name: ../templates/mytemplate.pt
               renderer_info: <RendererHelper - at 0x109f3f040>
               context: <DefaultRootFactory None at 0x109d3faf0>
               request: <Request - at 0x109d3fa90>
               req: <Request - at 0x109d3fa90>
               get_csrf_token: <partial - at 0x109f32db0>
               project: pycharm_app
               target_language: <NoneType - at 0x10817de60>
               repeat: {...} (0)
               macroname: load: layout.pt
thunt
  • 89
  • 1
  • 11
  • 1
    The template engine doesn't seem to know about the `build_cache_id` function. Where is it defined? How do you pass it to the template engine? What about this: https://docs.pylonsproject.org/projects/pyramid/en/1.10-branch/narr/assets.html#cache-busting ? – sinoroc Nov 13 '19 at 08:44
  • Thanks for the link. I'm following along with a tutorial so would like to stick as close as possible to the intended method before considering alternatives (with only a basic understanding). I have a utils.py file that defines build_cache_id (using hashlib md5.hexidigest()). utils is then imported to views.py which has `@view_config(route_name='layout', renderer='templates/layout.pt') def layout(_): return extend_model({'project': 'pycharm_app'})` where `def extend_model(model_dict): model_dict['build_cache_id'] = pycharm_app.utils.build_cache_id return model_dict` – thunt Nov 13 '19 at 09:39
  • Edit your question to add details if possible. It would be preferable. Do you have a link to the tutorial? – sinoroc Nov 13 '19 at 09:40
  • Thanks for your patience Sinorac. I think there is a pay wall in front of the tutorial, but if not, it's at: https://training.talkpython.fm/player/course/python-for-entrepreneurs-build-and-launch-your-online-business/lecture/50707. I've updated the original question with screenshots of the 3 files. – thunt Nov 13 '19 at 11:02
  • Copy paste of the content of files would have been much more helpful than the screenshots. – sinoroc Nov 13 '19 at 11:21

2 Answers2

0

The Arguments part of the error output clearly shows that build_cache_id is not passed to the template engine. On the other hand, the project variable is.

 - Arguments:  view: <function my_view at 0x109eff8b0>
               renderer_name: ../templates/mytemplate.pt
               renderer_info: <RendererHelper - at 0x109f3f040>
               context: <DefaultRootFactory None at 0x109d3faf0>
               request: <Request - at 0x109d3fa90>
               req: <Request - at 0x109d3fa90>
               get_csrf_token: <partial - at 0x109f32db0>
               project: pycharm_app
               target_language: <NoneType - at 0x10817de60>
               repeat: {...} (0)
               macroname: load: layout.pt```

Looks like the extend_model function is not correctly called, even though the code looks correct to me. Was the application correctly reloaded? Maybe add simple print calls in these functions as a quick and dirty debug and make sure that the correct code is running.

sinoroc
  • 18,409
  • 2
  • 39
  • 70
  • I'm at my wits end... I added print calls to `views.py` and it behaved as expected returning a dictionary `{'project': 'pycharm_app', 'build_cache_id': 'e6a2fee2b455c8a1946d0d1a52c9b112'}`. I tested `layout.pt` with `` to check it could process functions (it could). It seems `layout.pt` can't see other files. Adding `print 'test ${build_cache_id('/static/theme.css')}'` to `layout.pt` returned the same error. What did you mean by "was the application correctly reloaded?" – thunt Nov 13 '19 at 19:10
  • Yes, confusing... What I meant is something like `$ pserve --reload config.ini` or restart the server after each code modification, but I guess you already did this, otherwise you wouldn't see the `print` output. Is there anything interesting in the output of `proutes config.ini` and/or `prequest config.ini /`, etc.? – sinoroc Nov 13 '19 at 20:34
  • Assuming config = development and running those commands. I get: a 4x4 grid for the 1st command. For the 2nd I get a lot of text. Starts with: `Uncaught NameError at http://localhost/ traceback url: http://localhost/_debug_toolbar/34343432303738383936/exception`. `line 13, in _error_handler response = request.invoke_exception_view(exc_info)`. `line 779, in invoke_exception_view raise HTTPNotFound pyramid.httpexceptions.HTTPNotFound: The resource could not be found.` etc. the github is https://github.com/tyronehunt/first_business_website if that helps? – thunt Nov 13 '19 at 21:15
  • The output of `proutes` is important! I cloned your repository and things seem obviously wrong to me on that level. I couldn't find a route named `layout` so that would explain to me why the `layout` view is never called. – sinoroc Nov 13 '19 at 21:47
  • I see... I attempted to start this whole project again elsewhere, but this time using PyCharm's Pyramid plug-in. Asides from the fact this seems to force me down jinja2 (when the tutorial is in chameleon), this also doesn't seem to initiate any `routes.py` file. The tutorial didn't mention `routes.py` in the process either (theirs just worked). Is this going to be more difficult to resolve than a line or two in `routes.py` then? – thunt Nov 13 '19 at 22:13
  • I guess it's relatively easy to fix, but it will most likely get you out of the tracks planned by the tutorial. I could assume the tutorial is correct, and you might have missed a step at some point. Or I could assume there is an issue in the tutorial, but I don't have access to it and I can't guess what it is trying to teach and it what order. If the paid tutorial comes with support, then contact them. Otherwise I'd recommend the official, free and public Pyramid "narrative documentation" which is very good and covers these aspects. Maybe review the views/routes chapters to get back on track. – sinoroc Nov 13 '19 at 22:24
  • Thanks @sinorac. I suspect I didn't pay enough attention to the tutorial covering the theory of folder structure, but I'm equally sure that it doesn't cover why this issue happened, or how to fix it. Nor is there support available at present (I mailed them). – thunt Nov 14 '19 at 13:31
  • From my point of view the first thing you should fix, is the fact that you have both a _views_ module `pycharm_app/views.py` and package `pycharm_app/views/`. Which one should stay, I don't know, it is probably written in the tutorial. – sinoroc Nov 14 '19 at 15:25
0

Fixed this! with a lot of help from @sinoroc.

The problem is that using PyCharm to initiate a pyramid web project sets up files and folder structure in a different way to cookiecutter via terminal. It is not immediately possible to copy across "missing" files from the cookiecutter framework to the PyCharm framework without ensuring you fix the plumbing. - typing proutes development.ini in terminal will list routes. In my instance there were routes for pyramid_debugtoolbar with no url. Deleting pyramid_debugtoolbar from development.ini fixed this issue. - All routes need to be specified in __init__.py file. Copy pasting new template files in to the folder structure does not mean they will automatically appear here. - All routes need to be passed to @view_config in views.py. E.g.

@view_config(route_name='index',renderer='templates/index.pt')
def index(_):
return extend_model({'project':'designable_web'})

Again, these routes will not automatically be set up when pasting in new file names from another folder structure.

  • Check which template language is installed in setup.py (e.g. chameleon, jinja2). At present PyCharm has a bug that defaults to jinja2 EVEN IF YOU SELECTED CHAMELEON ON SET UP. Template files will not work unless the correct corresponding language is specified here.

  • Check folder depth. The cookiecutter framework had a separate views folder with views file inside, whereas PyCharm had the views.py file sitting underneath the top "app level" folder. Again proutes development.ini will specify which is correct.

thunt
  • 89
  • 1
  • 11