I write grid filters and some functionality is not implemented yet, so I want to redirect people to default grid when they try to use the unimplemented features. In my controller I have access to a request object. Can I update its parameters and use my request object, to redirect the user?
I tried to update request.params directly but it's a read-only object. Tried to use httpfound but it doesn't accept params.
try:
self._parse_filters(filters)
except NotImplementedError:
url = self.request.route_
self.reset_filters = True
self.error = 'Not Implemented Functionality. Default filters loaded'
self._parse_filters(self.default_filters)
You need to build a new URL (possibly based on the parameters in your current request) and use HTTPFound to generate a redirect. To generate the query part of your new url you can use _query parameter of request.route_url method or simply use urllib.urlencode.
new_url = request.route_url(
'not_implemented_view',
blah='boo',
_query={'sort':'asc'} # you can give it request.GET if you want all the same url parameters
)
return HttpFound(new_url)
Related
I want my application to be able to detect the user's language to serve the corresponding page to them. My idea was to use #before.request to read the Accepted-Languages header, match it against the app's supported languages, and set a cookie if needed, but it seems that the last step is not achievable.
Here is the code for that:
#app.before_request
def before_request_callback():
if request.cookies.get('lang'):
pass
else:
lang = request.accept_languages.best_match(supported_languages)
print(lang)
#I would like to set the cookie here
I thought about setting the cookie in the response object directly in the decorator (resp.set_cookie()) and thus reformatted all the returns in my app to look like this
#app.route("/")
def hello():
resp = make_response(render_template('index.html'))
return resp
to maybe be able to fetch the cookie and attach it to this response, but since the response is created afterwards in the endpoitn function, i have no idea how to do that either.
I also thought about creating the response directly in the decorator, but since i need the return condition, i don't know if thats possible
I think you're trying to use a cookie when you don't need to. As you noted, you can only set cookies on the response. You send the browser cookies in the response and then it re-sends them to you in any subsequent request. But it's already sending you the Accept-Language. So there's no point in setting a cookie on the request. It's already arrived, and already contains what you need.
Instead of getting hung up on setting cookies, just consult the request at the point that you're generating the response to ensure that the served content is in the appropriate language.
from flask import request
#app.route("/")
def hello():
lang = request.accept_languages.best_match(supported_languages)
return render_template(f'{lang}/index.html')
I'm trying to write API client for Jira with Python requests lib according reference:
https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/
Request to be generated:
http://localhost:8080/rest/api/2/search?jql=assignee=charlie&startAt=2&maxResults=2
As I know, parameters to GET request should be passed as dictionary like:
params = {'assignee':'charlie', 'startAt':'2'}
But all main parameters are nested in jql parameter, so I assume there is should be a nested dict like:
params = {'jql': {'assignee': 'charlie'}}
But that's doesn't work - as a result I've got request to
/rest/api/2/search?jql=assignee
As expect /rest/api/2/search?jql=assignee=charlie
using
r = requests.get(url, params=params)
How to manage such request?
UPD:
To be more clear, I'd like to wrap request in a method with kwargs, like:
search_query(assignee='charlie', startAt=1, etc...)
And then generate a query using this params, but maybe there are any other ideas.
You are missing couple of key parameters, mainly if you are pushing data via requests, the data go into the data argument. Also the moment you push JSON data, you need to set the headers correctly as well. The last thing is authentication. Have you tried to post it in this manner?
import json
requests.post(url=url, headers={"Content-Type": "application/json"},
auth=('username', 'password'), # your username and password
data=json.dumps(params)
)
Also by the JIRA documentation you've provided (https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/) if you want to push query as data, the url you want is /rest/api/2/search.
I am using requests-oauthlib to authenticate with the ETrade API. It requires the authorization URL to have the following format:
https://us.etrade.com/e/t/etws/authorize?key={oauth_consumer_key}&token={oauth_token}
However, when I call authorization_url(), it uses oauth_token instead of token for that parameter. Currently I am using format() to format the URL myself, but now I have both token and oauth_token parameters. This works, but is completely inelegant. Is there some way to modify the behavior of authorization_url() to allow the URL format I require?
For completeness, here is my code:
oauth_session = requests_oauthlib.OAuth1Session(config.oauth_consumer_key, config.consumer_secret, callback_uri='oob')
def get_request_token():
path = 'oauth/request_token'
url = base_url + path
return oauth_session.fetch_request_token(url)
def get_authorization_url(request_token):
url_format = 'https://us.etrade.com/e/t/etws/authorize?key={oauth_consumer_key}&token={oauth_token}'
url = url_format.format(oauth_consumer_key=config.oauth_consumer_key, oauth_token=request_token['oauth_token'])
return oauth_session.authorization_url(url)
request_token = get_request_token()
print(get_authorization_url(request_token))
The authorization_url() function is a convenience function which calls a generic function to add query parameters to a url (OAuthLib's common.add_params_to_uri() which in turn uses urlparse.urlunparse()). There is no way to get authorization_url() to leave out the oauth_token parameter.
The returned type is a str (in Python 3), so as long as you are certain that the url and tokens will only contain valid characters, you can obtain the same result by using a plain string format call as you have done in your function.
However if the additional oauth_token parameter causes no problems, I would suggest using the authorization_url() function for the extra safety provided.
Additionally, it is then unnecessary to do the extra str.format() call in your function - the authorization_url() takes kwargs which can be used to specify those parameters:
def get_authorization_url(request_token):
url = 'https://us.etrade.com/e/t/etws/authorize'
return oauth_session.authorization_url(url,
key=config.oauth_consumer_key,
token=request_token['oauth_token'])
Is it possible to send data while to redirecting to another view?
For example:-
def social_user():
//do something here
return redirect('name of the view',{'variable':'value'})
or any other alternative to exchange data between a function and view function.
There are two ways to send data to the resulting destination, but first you should understand how redirects work.
When the server redirects, it just sets the Location header telling the browser which page to fetch next.
Location: /foo.html
Since the body is completely ignored even if present, you must somehow pass data via the HTTP headers.
1) Query Parameters
The easiest way is to use query (GET) parameters which you can then read from the destination page:
Location: /foo.html?username=bob
The downside is that the user can easily see and modify this value.
2) Cookies
The session, which is determined by cookies, is another place to store temporary data. But this has several downsides:
It is not tied to any request, so you all consequent request will have access to the data until you delete it.
It doesn't work if the user has disabled cookies. On the other hand query parameters always work.
If you choose the first option, you may need to write some of your own code since Django doesn't seem to offer a convenient method to do this (someone correct me if I'm wrong). Here's a sample function that wraps the functionality:
def redirect_with_query(path, query=None, *args, **kwargs):
if query is None:
query = {}
url = resolve_url(path, *args, **kwargs)
if len(query):
q_dict = QueryDict(mutable=True)
q_dict.update(query)
url += '?' + q_dict.urlencode()
return HttpResponseRedirect(url)
First Solution::
If you have access to the request variable in social_user, you can simply make use of sessions. Sessions are the best way to transfer data between 2 views.
def social_user(request):
request.session['variable'] = 'value'
return redirect('name of the view')
Then inside your view, you can access this variable using request.session.get('variable')
Second Solution::
In case you can't set session variables, send them as query parameters.
def social_user():
//do something here
return redirect("your_view/?variable=value")
Build a "mock django request" manually and call the view directly
Use query parameters
Use render() and pass the variable via context:
def social_user(request)
// do something here
return render(request, template_name='template.html', context={'variable': 'value'})
In Flask I have url rules with variables. For example:
my_blueprint.add_url_rule('/<user_token>/bills/',view_func=BillsView.as_view('bills'))
This is going to pass the user_token variable to the BillsView's get and post methods.
I am trying to intercept that user_token variable in the before_request of my blueprint.
Here is my blueprint before_request:
def before_req():
...
...
my_blueprint.before_request(before_req)
The closest I have come is to use request.url_rule. But that does not give me the content of the variable. Just the rule that matches.
Register a URL processor using #app.url_value_preprocessor, which takes the endpoint and values matched from the URL. The values dict can be modified, such as popping a value that won't be used as a view function argument, and instead storing it in the g namespace.
from flask import g
#app.url_value_preprocessor
def store_user_token(endpoint, values):
g.user_token = values.pop('user_token', None)
The docs include a detailed example of using this for extracting an internationalization language code from the URL.
Apart from the URL preprocessors as described above, another approach to get args passed to the URL explicitly will be to use this.
#app.before_request
def get_request_args():
"Provides all request args"
request_args = {**request.view_args, **request.args} if request.view_args else {**request.args}
print('All Request args ',request_args)
More info in the documentation of request.args and request.view_args