To answer my own question (although there might be a simpler and better way that I'm just not aware of, but here's what I ended up doing for now)...
I created a custom routing converter (the method for doing this is described here), and registered it in my app so I could use it in my view_results()
route. I added this to my utils.py
that I have in the same directory as my app's init:
from werkzeug.routing import BaseConverter
class DictionaryConverter(BaseConverter):
"""Convert python dictionary to URL query string and back."""
def to_python(self, value):
d = {}
for item in value.split('&'):
k, v = item.split('=')
if k != 'csrf_token':
d[k] = v
return d
def to_url(self, values):
pairs = []
for k in values:
#don't expose the csrf token in the query string
if k != 'csrf_token':
pairs.append('{}={}'.format(k, values[k]))
return '&'.join(BaseConverter.to_url(self, value=pair) for pair in pairs)
Then in my app __init__.py
I made sure to register the custom converter after initializing the app, but before loading the blueprint that uses it (my main
blueprint):
app = Flask(__name__)
# ...
from .utils import DictionaryConverter
app.url_map.converters['dict'] = DictionaryConverter
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
My search view sends the data from request.form
(which is where the data goes for POSTs) along to the results view. I have it using code=303
to remove ambiguity and make certain the request is sent as a GET, but this is might not be a big deal here.
@main.route('/search/', methods=['GET', 'POST'])
def search():
form = SearchForm()
if form.validate_on_submit():
return redirect(url_for('.view_results', data=request.form), code=303)
return render_template('search.html', form=form)
Finally, my results view uses the new converter, and then I can access the data as per usual (as you can see, I'm still not really doing anything with it yet, but now I should be able to start):
@main.route('/search/results?<dict:data>')
def view_results(data):
for i in data:
print(i, data[i])
return "placeholder"
This seems to work but I still feel like I'm just missing something obvious from Flask that wouldn't require creating a custom converter...