I'm really new to Python and GAE. I'm setting up a basic CRUD app for some test data and am trying to get some routing for the admin pages going. I'd like to use the same page for creating and editing an object. So basically I want:
/admin/edit/<id>
where <id> is optional and /admin/edit will route to the same page. I tried adding <id:\w*> to the route which then allowed me to hit the page without supplying an id, but then when I supplied the id, I received a 404. Then I tried <id:\w+> and got a 404 with and without an id. I'm not having much luck.
Can anyone help me with what regex I need for this?
You can set up a regex to parse IDs out of the URL. Here's a really premitive example using webapp2:
app = webapp2.WSGIApplication([('/', MainPage),
('/property/(.*)', PropertyHandler)],
debug=True)
And you setup your request handler to accept the additional parameter:
class PropertyHandler(webapp2.RequestHandler):
def get(self, propertyId):
For a real-world implementation, you'd want to be a bit more specific on the regex and add validation to the handler incase you get garbage or no ID.
Related
I have a RESTful API like /do/some/<action:.*> so my app with get <action> and run it.
My question is, if I use RedirectRoute and strict_slash=True, will my app keep getting <action> as argument or will it start getting <action>/ (notice the / at the end)?
EDIT: I'm using webapp2
A RedirectRoute will issue a HTTP redirect telling the browser to go to the new URL, then the browser will make a new request at that URL.
How this is implemented is that two routes are created - your original route, and one for redirecting.
So, in your case, a route with /do/some/<action:.*>/ would be created that redirects to /do/some/<action.*>.
However, I think your route actually will be checked first (not positive, sorry), so it would just always fire. I would modify it to not match slashes, if that's okay. Luckily, that's the default behaviour if you omit the regex, so just /do/some/<action:> should work!
I am pretty new to google app engine and python. After successfully uploading an application, I am stuck with a basic question.
app = webapp2.WSGIApplication([
('/.*',IndexHandler)
], debug=True)
This is the code block which is generally used to map the request with the class that handles it. However there is a section in app.yaml which allows specifying handler for individual url.
My question is what is the correct architecture of a python application on google app engine. What if my application has several hundreds of classes for handling different request ?, do I have to specify all of them here in this code ?
I have googled but could not find a satisfactory answer. Link to a good tutorial or documentation would be a great help.
Basically, you define the app to be used in app.yaml. For example, if you've got multiple apps, you can specify here which to use.
Yes, you have to specify all the allowed URLs here (in main.py). Otherwise the request will get 404. However, you can use regular expressions to make certain type of addresses to match the given handler.
Check out the tutorial: https://developers.google.com/appengine/docs/python/gettingstartedpython27/usingwebapp
Documentation for URI routing: http://webapp-improved.appspot.com/guide/routing.html?highlight=url
You can do like this.
In app.yaml
- url: /service/.*
script: service.app
- url: .*
script: main.app
In service.py
url_map = [
('.*/user.*', 'service.UserHandler'),
('.*/data/show/', 'appname.service.DataShowHandler'),
('.*/data.*', 'appname.service.DataHandler'),
]
app = webapp2.WSGIApplication(url_map)
When you tried to access http://your-appid.com/service/user, appengine will excecute GET function of UserHandler Class in service.py which is located in the Root Folder.
When you tried to access http://your-appid.com/service/data/show, appengine will excecute GET function of DataShowHandler Class in service.py which is located in the Root/appname Folder.
I have two anwers :
1) You can use webapp2 routing to handle the requests and uri routing. This is very powerfull. You can use url templates and / or write your own custom dispatcher.
2) For a lot of requests you can use a single URL and use a session / state to find out how to continue after a post. This means : you do not have to use a request handler for every request.
app.yaml can be used for setting such as secure and login options, though I personally don't use them.
I use main.py to map all urls to the right handlers.
I am trying to add some simple tenancy support to an app, creating an Account model which has a string 'tenant' to be read from the request url and identify the tenant in the system:
tenant.example.com/* -> www.example.com/tenant/* (rewritten by apache)
I wrote a simple middleware to capture this /tenant/ from request.path and add a request.account object to be worked with.
My problem is my url mapping.
I tried this:
url(r'^(?P<tenant_id>[\w\-]+)/', include('project.urls_tenant')),
and defined some simple urls inside urls_tenant.py:
url(r'^app1/', include('project.app1.urls')),
url(r'^app2/', include('project.app2.urls')),
When I try to access any page, I get an error message:
generic_view_method() got an unexpected keyword argument 'tenant_id'
because it doesn't (and really shouldn't) expect tenant_id as a parameter.
If I hardcode tenant_id in the urls.py file as /test_tenant/ everything works fine.
What am I doing wrong and how to fix it, so the request and the response gets processed normally?
Thank you guys pretty much. I used this as reference: optimal architecture for multitenant application on django
You are capturing the named parameter tenant_id in the url pattern when you apparently don't need to. Try removing the parentheses to avoid performing the capture:
url(r'^[\w\-]+/', include('project.urls_tenant')),
This page is a generally useful read:
https://docs.djangoproject.com/en/dev/topics/http/urls/#how-django-processes-a-request
If I understand your setup correctly you have defined:
url(r'^(?P<tenant_id>[\w\-]+)/', include('project.urls_tenant')),
In our main urls.py file and the other lines in your urls_tenant.py file ?
Taking it from there wouldn't any request that matches ^(?P[\w-]+)/ be passed
through urls_tenant.py file ? The two lines you have defined there would only be able to match /app1 or /app2.
But I'm just guessing I'm not fully understanding your setup ?
I think it would be better if you would map the tenant url to a specific view instead of including a different urls.py file
(I didn't even know this was possible).
url(r'^(?P<tenant_id>[\w\-]+)/', TenantView.as_view(), name="tenant-view"),
Something like the above looks more django to me.
I am building a web app with google app engine with python as well as HTML and CSS and I have a bunch of pages (around 15) that I want to make that will all somewhat different though will have a similar purpose. Is there any way to only have a few handlers that can create a bunch of pages or do I need a different class in python for every page?
I know this question is somewhat vague without context for the pages but really any information about how to create multiple pages without coding entirely new handlers and HTML for them would be a huge help.
No you don't need a different class for each page.
You can redirect every request to a singe script with app.yaml
handlers:
- url: /.*
script: dispatcher.app
Then, from dispatcher.py you can redirect every request to a single RequestHandler and program all your logic there, like serving a different jinja2 template for different URLs dinamically.
The URL Mappings documentation explains how to redirect multiples URLs to one RequestHandler. For example:
class BrowseHandler(webapp.RequestHandler):
def get(self, category, product_id):
# Display product with given ID in the given category.
# Map URLs like /browse/(category)/(product_id) to BrowseHandler.
application = webapp.WSGIApplication([(r'/browse/(.*)/(.*)', BrowseHandler)
],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
It will really depend on what framework you are using (if at all), but what you are looking for is templating systems. Here is a good list of frameworks and templating systems.
It really depends on what you're trying to do, but if you're using webapp or webapp2, you can use one handler. Check the Request parameter's url field to find out which page the user is requesting.
I just started with Google App Engine using python and I was following a tutorial and writing my own little app to get familiar the webapp framework. Now I just noticed the tutorial does the following self.redirect('/'). So that got me wondering: is there a way to redirect to a handler instead of a hardcoded path? Thought that might be better so that you can change your urls without breaking your app.
One alternative would be to have a map of symbolic names to URLs, that way you could redirect to the mapped URL - you could then update your URLs with impunity.
Or if you'd rather just execute the code from another handler, I don't know why you couldn't just make a method call - worst case, you could extract a common method from the two handlers and call that.
This isn't a limitation of App Engine so much as the webapp framework. webapp is intended to be a lightweight framework, providing just the essentials.
If you want fancier redirect behavior, try Django.
The accepted answer made me built my own little router before I realized that in webapp2 you can name your routes and then redirect using that name as described in webapp2 Uri routing
app = webapp2.WSGIApplication(
routes=[webapp2.Route('/', handler='RootController', name='root')])
and then redirect to them in the RequestHandler
self.redirect_to('root')
if your path contains placeholders you can supply the values for the placeholders and the webapp2.Router will build the correct uri for you. Again take a look at webapp2 Uri routing for more detailed information.