So this question has been asked before, but not answered in great detail.
I want to override the default Pylons error page to make a nicer, custom one. I've got as far as overwriting the controller in error.py, as follows:
def document(self):
"""Render the error document"""
resp = request.environ.get('pylons.original_response')
content = literal(resp.body) or cgi.escape(request.GET.get('message', ''))
custom_error_template = literal("""\
# some brief HTML here
""")
page = custom_error_template % \
dict(prefix=request.environ.get('SCRIPT_NAME', ''),
code=cgi.escape(request.GET.get('code', str(resp.status_int))),
message=content)
return page
This works OK. What I'd like to do now is use a template in the templates directory, so that the 404 page can inherit my usual layout template, CSS etc.
(I know this is a bad idea for 500 errors - I'll check in error.py that the code is 404 before I use the template rather than a literal.)
So, here's the question. How do I define custom_error_template to point at my template, rather than at a literal?
You should be able to use render method (import it from yourapp.lib.base, and use return render('/path/to/error/template').
Just create your view and use add_notfound_view configuration method to configure it.
See: http://docs.pylonsproject.org/docs/pyramid/en/latest/api/config.html?highlight=document%20error#pyramid.config.Configurator.add_notfound_view
Related
I have two different urls:
1) /campaigns/, which lists available campaigns and 2)campaigns/add/ where there is a form to fill the details of a campaign to be created.
My django urls.py file looks like:
url(r'^campaigns/', views.campaigns, name='agency-campaigns'),
url(r'^campaigns/add/$', views.add_campaign, name='agency-add-campaign')
The problem is that whenever I browse the /campaigns/ url, it shows the correct template. But when I browse the /campaigns/add/ url, it still shows the /campaigns/ url template.
What can be wrong with this subdirectory?
Any ideas?
Thanks in advance!
That's because you don't have the end of string match ($) at the end of the regular expression:
url(r'^campaigns/$', views.campaigns, name='agency-campaigns'),
# HERE^
Or, you can also put the "agency-add-campaign" pattern before the "agency-campaigns":
url(r'^campaigns/add/$', views.add_campaign, name='agency-add-campaign'),
url(r'^campaigns/', views.campaigns, name='agency-campaigns')
How do I make web.py fetch a page when I click on a link?
I have this in my template:
<a href='add.html'>Home</a>
When I click on 'Home', I get 'not found'.
In my application, I have '/add' mapped to the 'Add' class which returns 'Boom!' using the template add.html.
urls = ('/', 'Index',
'/add','Add')
class Add(object):
def GET(self):
return render.add('Boom!')
I feel when I request for /add.html, the Add class will handle the request and return 'Boom!'
Why do I keep getting 'not found'?
The origin of a page URI ending in .html lilke /add.html is that in static hosting environments those were traditionally really single text files with html-content and the file ending for such a file is .html
But your system is dynamic and creates web pages on the fly. It does not necessarily need the pages ending in .html. Although you can mimic the traditional behaviour if you desire.
But in a modern and dynamic system it is often preferred that there is no ending on the single "pages" at all.
So you could, as Ignacio also suggests, just get rid of the .html and request the /add page, which is a valid and sufficient unique identifier for that resource.
If you like to keep the .html ending. you have to add it also in the route.
urls = (
'/', 'Index',
'/add.html','Add',
)
You can also have multiple routes pointing to the same resource, so that both /add and /add.html are valid and showing the same content, but content duplication has other drawbacks:
urls = (
'/', 'Index',
'/add','Add',
'/add.html','Add',
)
I recommend getting rid of the .html. This means you stick with the code from your question and create links to the page like this:
add something
Either change the route to be "/add.html" or change the link to be "add".
The following browser view should return the content of the front page of the first Plone Site in it's context. However, I can not seem to obtain an object which is able to render html content.
from Products.Five import BrowserView
from zope.component import getMultiAdapter
class RenderFirst (BrowserView):
def __call__ (self):
def findPlones (context):
plones = context.objectValues("Plone Site")
folders = context.objectValues("Folder")
folders = set(folders).difference(set(plones))
for folder in folders:
plones += findPlones(folder)
return plones
plones = findPlones(context)
if len(plones):
default_page = plones[0].getDefaultPage()
content = plones[0].unrestrictedTraverse (default_page)
view = getMultiAdapter ((content, self.request))
return view()
else:
return "no plone"
The previous code when run tells me that the object view is not callable.
plones[0] is a Plone Site object and when called produces a KeyError for folder_listing
if I call the content object I get an AttributeError for document_view
There are lots of combinations here, of calling different adapters of different objects. Haven't yet found the right object which can render the page. Anyone know how to do this?
When I try this in a pdb a simple plones[0]() works fine.
Take a look at http://pypi.python.org/pypi/plone.subrequest.
So, I'm trying to make a simple call using jQuery .getJSON to my local web server using python/django to serve up its requests. The address being used is:
http://localhost:8000/api/0.1/tonight-mobile.json?callback=jsonp1290277462296
I'm trying to write a simple web view that can access this url and return a JSON packet as the result (worried about actual element values/layout later).
Here's my simple attempt at just alerting/returning the data:
$.getJSON("http://localhost:8000/api/0.1/tonight-mobile.json&callback=?",
function(json){
alert(json);
<!--$.each(json.items, function(i,item){
});-->
});
I am able to access this URL directly, either at http://localhost:8000/api/0.1/tonight-mobile.json or http://localhost:8000/api/0.1/tonight-mobile.json&callback=jsonp1290277462296 and get back a valid JSON packet... So I'm assuming it's in my noob javascript:)
My views.py function that is generating this response looks as follows:
def tonight_mobile(request):
callback = request.GET.get('callback=?', '')
def with_rank(rank, place):
return (rank > 0)
place_data = dict(
Places = [make_mobile_place_dict(request, p) for p in Place.objects.all()]
)
xml_bytes = json.dumps(place_data)
xml_bytes = callback + '(' + xml_bytes + ');'
return HttpResponse(xml_bytes, mimetype="application/json")
With corresponding urls.py configuration:
(r'^tonight-mobile.json','iphone_api.views.tonight_mobile'),
I am still somewhat confused on how to use callbacks, so maybe that is where my issue lies. Note I am able to call directly a 'blah.json' file that is giving me a response, but not through a wired URL. Could someone assist me with some direction?
First, callback = request.GET.get('callback=?', '') won't get you the value of callback.
callback = request.GET.get( 'callback', None )
Works much better.
To debug this kind of thing. You might want to include print statements in your Django view function so you can see what's going on. For example: print repr(request.GET) is a helpful thing to put in a view function so that you can see the GET dictionary.
I am trying to have a custom URL which looks like this:
example.com/site/yahoo.com
which would hit this script like this=
example.com/details?domain=yahoo.com
can this be done using app.yaml?
the basic idea is to call "details" with the input "yahoo.com"
You can't really rewrite the URLs per se, but you can use regular expression groups to perform a similar kind of thing.
In your app.yaml file, try something like:
handlers:
- url: /site/(.+)
script: site.py
And in your site.py:
SiteHandler(webapp.RequestHandler):
def get(self, site):
# the site parameter will be what was passed in the URL!
pass
def main():
application = webapp.WSGIApplication([('/site/(.+)', SiteHandler)], debug=True)
util.run_wsgi_app(application)
What happens is, whatever you have after /site/ in the request URL will be passed to SiteHandler's get() method in the site parameter. From there you can do whatever it is you wanted to do at /details?domain=yahoo.com, or simply redirect to that URL.