Optional URL parameter on Pyramid route - python

For example I want to use the same route to submit a form and to show the content of forms based on their id number.
I thought a rematched parameter:
config.add_route('poll', '/poll/{id}*')
was enough but it doesn't work. When the method POST finishes I want it to load the page showing the result but it throws a 404 error.

From http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#route-pattern-syntax:
config.add_route('poll', '/poll/{id:.*}')
Note that when generating a url via request.route_url('poll', id='5') the id parameter is required, you cannot leave it out. You can solve this with a pregenerator:
def pregen(request, elements, kw):
kw.setdefault('id', '')
return elements, kw
config.add_route('poll', '/poll/{id:.*}', pregenerator=pregen)
This will allow you to use request.route_url('poll') as well as request.route_url('poll', id='5').

Related

Django, how to send arguments to redirected view

My view function what should receive an argument:
def result(request, exercise_field = {"tro": "lolo"}):
return render(request, "lolapp/result.html", exercise_field)
"Exercise_field" is the variable that takes an argument.
Url for that function:
url(r'^result/', view = views.result, kwargs = {'lolo': 'roflo'}, name = 'result')
As you can see, i tried to pass my argument via "kwargs" keyword. So far - haven't worked out.
Shortcut that calls this View:
return redirect('result', kwargs={'lol': 'rofl'})
And finally the error message:
Reverse for 'result' with arguments '()' and keyword arguments '{'kwargs': {'lol': 'rofl'}}' not found. 1 pattern(s) tried: ['result/']
I need to send one argument to "results" view.
And this is typical "NoReverseMatch" error, but no solutions in internet worked for me.
What do i do wrong?
may be just typo:
kwargs={'lol': 'rofl'}
you should try:
kwargs={'lolo': 'rofl'}
return redirect('result', kwargs={'lol': 'rofl'})
should be for kwargs:
mydict = {'lol': 'rofl'}
return redirect('result',passdict=mydict)
or simply you can do with args:
mydict = {'lol': 'rofl'}
return redirect('result',mydict)
Your URL does not accept any arguments at all: the view kwargs are hard-coded. It is therefore impossible for any request - whether a redirect or just a normal request - to pass any kwargs other than the hard coded ones.
You have various options:
change the URL pattern so it does accept arguments;
add an extra pattern with the other kwargs hard coded;
pass the data in the session rather than the kwargs.
The solution to my problem is simple: i should've to use sessions.
Info about sessions: http://machinesaredigging.com/2013/10/29/how-does-a-web-session-work/
How to use sessions in Django: https://docs.djangoproject.com/en/1.6/topics/http/sessions/
Simply store it within request.session["my_data_key"], and i good to go.
request.session is simple python dictionary.

How to ensure URLs generated by Pyramid's route_url and route_path are valid?

Using URL Dispatch in Pyramid and pattern matching inside the route definition, I would like to ensure that URLs generated by route_path are valid and match the given route - what's the best way to do that?
This is my route definition - I want /numbers followed by a numeric string that's equivalent to 1 or greater...
config.add_route('numbers', 'numbers/{n:[1-9]\d*}/')
Then when I generate a route in a view for example, this is fine:
request.route_url('numbers', n=123)
It returns /numbers/123/ which is fine...
However, if I do...
request.route_url('numbers', n='chicken')
Pyramid returns /numbers/chicken/ which clearly doesn't match the pattern and will give a 404 when passed back to the app.
Is there a way that I can force Pyramid to check that the n matches the given pattern when it's generating the route? This would mean that I could be certain that route_url and route_path would give valid URLs that would work in the app.
You can use a pregenerator to add custom logic when generating urls. The regex patterns in the urls have only ever been used for matching purposes.
def check_n(request, elements, kw):
if not is_valid(kw['n']):
raise ValueError('invalid url parameter')
return elements, kw
config.add_route('numbers', 'numbers/{n:[1-9]\d*}/', pregenerator=check_n)
If you want to write something that validates the generated urls, it's not easy. The pregenerator doesn't know what route is being used and the route object matches paths, not kwargs. Your best bet is to wrap the route generation and validate the resulting url, instead of validating the kwargs themselves.
def validated_route_path(request, *args, **kwargs):
route_name = args[0]
path = request.route_path(*args, **kwargs)
route_intr = request.registry.introspector.get('routes', route_name)
route = route_intr['object']
if route.match(path) is None:
raise ValueError('invalid url generated')
return path
config.add_request_method(validated_route_path)
request.validated_route_path('numbers', n='chicken') # -> ValueError

Pyramid route matching and query parameters

I have a Pyramid web service, and code samples are as follows:
View declaration:
#view_config(route_name="services/Prices/GetByTicker/")
def GET(request):
ticker = request.GET('ticker')
startDate = request.GET('startDate')
endDate = request.GET('endDate')
period = request.GET('period')
Routing:
config.add_route('services/Prices/GetByTicker/', 'services/Prices/GetByTicker/{ticker}/{startDate}/{endDate}/{period}')
Now I know this is all screwed up but I don't know what the convention is for Pyramid. At the moment this works inasmuch as the request gets routed to the view successfully, but then I get a "Dictionary object not callable" exception.
The URL looks horrible:
#root/services/Prices/GetByTicker/ticker=APPL/startDate=19981212/endDate=20121231/period=d
Ideally I would like to be able to use a URL something like:
#root/services/Prices/GetByTicker/?ticker=APPL&startDate=19981212&endDate=20121231&period=d
Any Pyramid bods out there willing to take five minutes to explain what I'm doing wrong?
from you sample code, i think you use the URL Dispatch
so it should be like this
config.add_route('services/Prices/GetByTicker/', 'services/Prices/GetByTicker/')
then the URL like:
#root/services/Prices/GetByTicker/?ticker=APPL&startDate=19981212&endDate=20121231&period=d
will match it
--edit--
you don't have to use a name like "services/Prices/GetByTicker" for route_name,and you can get the GET params use request.params['key']
View declaration:
#view_config(route_name="services_Prices_GetByTicker")
def services_Prices_GetByTicker(request):
ticker = request.params['ticker']
startDate = request.params['startDate']
endDate = request.params['endDate']
period = request.params['period']
Routing:
config.add_route('services_Prices_GetByTicker', 'services/Prices/GetByTicker/')
The query string is turned into the request.GET dictionary. You are using parenthesis to call the dictionary instead of accessing items via the brackets. For a url such as
#root/services/Prices/GetByTicker/?ticker=APPL&startDate=19981212&endDate=20121231&period=d
request.GET['ticker'] # -> 'APPL' or an exception if not available
request.GET.get('ticker') # -> 'APPL' or None if not available
request.GET.get('ticker', 'foo') # -> 'APPL' or 'foo' if not available
request.GET.getall('ticker') # -> ['APPL'] or [] if not available
The last option is useful if you expect ticker to be supplied multiple times.
request.params is a combination of request.GET and request.POST where the latter is a dictionary representing the request's body in a form upload.
Anyway, the answer is that request.GET('ticker') syntactically is not one of the options I mentioned, stop doing it. :-)

Unable to view item in browser based on its key in Python GAE

I'm using python GAE with webapp.
I have a form for a user to create a object in the database, something like:
class SpamRecord(db.Model):
author = db.ReferenceProperty(Author, required=True)
text = db.StringProperty()
After it's created, the user is redirected to a page whose URL contains that object's key... using code such as:
spam = SpamRecord(author=author, text=text)
spam.put()
new_spam_key = spam.key()
self.redirect("/view_spam/%s" % new_spam_key)
And this mostly works, with me being able to view items at:
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQYy8oJDA
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQY_boJDA
However, there's an occasional key that won't work. Here are 2 recent examples of pages that won't load and return HTTP 404 not found errors:
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQY-5MJDA
sitename.com/view_spam/ag1waWNreXByZXNlbnRzchQLEgxBbm5vdW5jZW1lbnQY-boJDA
My html-mappings.py contains the following mapping:
(r"/view_spam/(\w+)", ViewSpamPage)
And the ViewSpamPage looks something like:
class ViewSpamPage(webapp.RequestHandler):
def get(self, spam_id):
self.response.out.write("Got here")
Can anyone offer any insight as to why this is occurring and how it may be prevented?
Thanks very much!
In regular expressions, \w doesn't match hyphens. (It will match underscores.) For that second pair of keys, this'll result in only passing part of the key to your handler.
In your URL pattern, try r"/view_spam/(.*)" instead.

jQuery getJSON Output using Python/Django

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.

Categories