How to build a dynamic url using get parameters in Flask [duplicate] - python

This question already has answers here:
Get a variable from the URL in a Flask route
(2 answers)
Closed 1 year ago.
i am using this code to get filter value from template by GET method:
#app.route('/', methods=['GET'])
def filters():
if request.args.get('country') is None:
results = Table.query.all()
return render_template('index.html', results=results)
else:
country = request.args.get('country')
industry = request.args.get('industry')
results = Table.query.filter(Table.country == country, Table.industry == industry).all()
return render_template('index.html', results=results, country=country, industry=industry)
as a result, I get a url like this:
http://127.0.0.1:5000/?country=USA&industry=REIT
how can I get with GET or POST url requests of this kind:
http://127.0.0.1:5000/USA/REIT

It looks like the feature you are looking for is called "Variable (Routing) Rules". From the Flask documentation:
You can add variable sections to a URL by marking sections with <variable_name>. Your function then receives the <variable_name> as a keyword argument. Optionally, you can use a converter to specify the type of the argument like <converter:variable_name>.
#app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
or in your case:
#app.route('/<country>/<industry>')
def show_post(country, industry):
results = Table.query.filter(Table.country == country, Table.industry == industry).all()
return render_template('index.html', results=results, country=country, industry=industry)

Related

Type error when trying to fetch data Python Django

I am trying to get data from the database based on request with id u_id and x_id but I am not getting any data instead getting an error TypeError: display_data() missing 2 required positional arguments: 'u_id' and 'x_id' can you help?
code
def display_data(request, u_id, x_id):
if request.method == 'POST':
widget['data'] = Widget.objects.get(u_id = u_id, x_id = x_id)
return widget
urls.py
url(r'^display_data/$', views.display_data, name="display_data"),
You need to get them from the POST data instead.
def display_data(request):
if request.method == 'POST':
u_id = request.POST.get('u_id')
x_id = request.POST.get('x_id')
widget['data'] = Widget.objects.get(u_id=u_id, x_id=x_id)
return widget
Also, you might want to use a form for validation.
If you want to get u_id and x_id as arguments like you are trying, you need to add them to the url.
url(r'^display_data/<int:u_id>/<int:x_id>', views.display_data, name="display_data"),
Edit:
Use filter instead of get if you are getting multiple objects
widget['data'] = Widget.objects.filter(u_id=u_id, x_id=x_id)

Using an HTML form with Python Flask search a MongoDB collection

I 'ld like for a user to drop a random search in a search form for a book title and find get results if the book is in the db. Below is part of the code block.
I 'm having some issues searching for a single document in my mongodb using a search field and search strings. Below is the code. I'm trying to get the search result via the find_book route.
The code above with the /find_book/<book_id> returns errors.
Below is a part of my code in the app.py file and the search form.
I get the following errors.
werkzeug.routing.BuildError
werkzeug.routing.BuildError: Could not build url for endpoint 'find_book'. Did you forget to specify values ['book_title']?
Traceback (most recent call last)
# create an instance of py_mongo with app as argument
mongo = PyMongo(app)
#app.route('/')
def home():
return render_template('home.html')
# define the various menu options
#app.route('/get_books')
def get_books():
return render_template('books.html', books=mongo.db.books.find())
# Add a book
#app.route('/add_book')
def add_book():
return render_template('add_book.html',
faculties=mongo.db.faculties.find())
# Add submit button for Books
#app.route('/insert_book', methods=['POST'])
def insert_book():
book = mongo.db.books
book.insert_one(request.form.to_dict())
return redirect(url_for('get_books'))
# wire the edit button
#app.route('/edit_book/<book_id>')
# description task, name, due date, is urgent fields will be
# pre-populated based on the information returned in the task.
def edit_book(book_id):
a_book = mongo.db.books.find_one({"_id": ObjectId(book_id)})
# category names will be prepolulated based on the collection
# # of categories returned in the categories cursor
all_faculties = mongo.db.faculties.find()
return render_template('edit_book.html',
book=a_book, faculties=all_faculties)
#app.route('/update_book/<book_id>', methods=['POST'])
def update_book(book_id):
# access the database collection
book = mongo.db.books
# call the update function, specify an id
book.update({'_id': ObjectId(book_id)},
{
'faculty_name': request.form.get('faculty_name'),
'subject_name': request.form.get('subject_name'),
'book_title': request.form.get('book_title'),
'book_author': request.form.get('book_author'),
'book_description': request.form.get('task_description'),
'lender_name': request.form.get('lender_name'),
'due_date': request.form.get('due_date'),
'is_available': request.form.get('is_urgent')
})
return redirect(url_for('get_books'))
# specify the form fields to match the keys on the task collection
# delete a book
#app.route('/delete_book/<book_id>')
def delete_book(book_id):
mongo.db.books.remove({'_id': ObjectId(book_id)})
return redirect(url_for('get_books'))
# find a book by text search
#app.route('/find_book/<book_title>', methods=['GET'])
def find_book(book_title):
book_title = mongo.db.books
book_title.find_one(
{
'book_title': request.form.get('book_title'),
})
return render_template('find.html', book_title=book_title)
# categories function
#app.route('/get_faculties')
def get_faculties():
return render_template('faculties.html',
faculties=mongo.db.faculties.find())
if __name__ == '__main__':
app.run(host=os.environ.get('IP'),
port=int(os.environ.get('PORT')),
debug=True)
<form action="{{ url_for('find_book') }}" method="GET">
<input type="text" placeholder="Book Title" id="book_title" name="book_title" >
<button type="submit"><i class="fa fa-search">Search</i></button>
</form>
Your find_book route is expecting an argument book_title
But you are not passing that in {{ url_for('find_book') }}
You could just change this route to #app.route('/find_book') and get the value from request.form or if you are using this route in another place of your application you could use the approach from this question and use this way:
#app.route('/find_book/', defaults={'book_title': None})
#app.route('/find_book/<book_title>')
def find_book(book_title):
books = mongo.db.books
if book_title is None:
book_title = request.form.get('book_title')
book = books.find_one({
'book_title': book_title
})
return render_template('find.html', book=book)
I could not run this snippet of code now, so let me know if dont work.

django-rest-framework : list parameters in URL

I am pretty new to django and django-rest-framework, but I am trying to pass lists into url parameters to then filter my models by them.
Lets say the client application is sending a request that looks something like this...
url: "api.com/?something=string,string2,string3&?subthings=sub,sub2,sub3&?year=2014,2015,2016/"
I want to pass in those parameters "things", "subthings", and "years" with their values.
Where the url looks something like this?
NOTE: Trick is that it won't be always an array of length 3 for each parameter.
Can someone point me in the right direction for how my url regex should be handing the lists and also retrieving the query lists in my views.
Thanks!
To show how I did this thanks to the document links above.
Note: I used pipes as my url delimiter and not commas -> '|'.
in my urls.py
url(r'^$', SomethingAPIView.as_view(), name='something'),
in my views.py
class SomethingAPIView(ListAPIView):
# whatever serializer class
def get_queryset(self):
query_params = self.request.query_params
somethings = query_params.get('something', None)
subthings = query_params.get('subthing', None)
years = query_params.get('year', None)
# create an empty list for parameters to be filters by
somethingParams = []
subthingsParams = []
yearParams = []
# create the list based on the query parameters
if somethings is not None:
for something in somethings.split('|'):
countryParams.append(int(something))
if subthings is not None:
for subthing in subthings.split('|'):
subthingsParams.append(int(subthing))
if years is not None:
for year in years.split('|'):
yearParams.append(int(year))
if somethings and subthings and years is not None:
queryset_list = Model.objects.all()
queryset_list = queryset_list.filter(something_id__in=countryParams)
queryset_list = queryset_list.filter(subthing_id__in=subthingsParams)
queryset_list = queryset_list.filter(year__in=yearParams)
return queryset_list
I do need to check for an empty result if they are not valid. But here is starting point for people looking to pass in multiple values in query parameters.
A valid url here would be /?something=1|2|3&subthing=4|5|6&year=2015|2016.
Checkout this doc http://www.django-rest-framework.org/api-guide/filtering/
Query params are normally not validated by url regex

Remove objects from query if None or Null

I am trying to build a query that takes form data and removes any None or " " submissions but I'm not sure how to approach the logic. Here is the code;
#app.route('/filterassets', methods=['GET', 'POST'])
def searchassets():
form = FilterAssetsForm()
results = None
if request.method == "POST":
if form.validate_on_submit():
try:
horsepower = form.horsepower_search.data
voltage = form.voltage_search.data
rpm = form.rpm_search.data
results = Motor.query.filter_by(horsepower=horsepower, voltage=voltage, rpm=rpm).all()
except Exception as e:
flash(e)
db.session.rollback()
return render_template('filterassets.html', form=form, results=results)
return render_template('filterassets.html', form=form)
Because it's the backend of a page that lets users filter, rather than explicitly search, some form data is empty. This is causing the query to search for results where one or more forms == None.
Example: User enters 100 in the horsepower form and leaves RPM and Voltage blank. The query returns no results even though there are rows with 100 horsepower because it is looking for rows where Horsepower == 100 and RPM and Voltage == None.
I've tried using filter(None, object) with no success, and think the solution may be somewhere in using kwargs.
I know I need to pass all the form data to something that will remove None or Null entries, then pass it onto the final Motor.query.filter_by argument, I just don't know how.
You can create a dict with the filter data:
filter_data = {'horsepower': horsepower, 'voltage': voltage, 'rpm': rpm}
Then create another dict with only the keys which values exist:
filter_data = {key: value for (key, value) in filter_data.items()
if value}
And finally use this dict as kwargs to your query:
results = Motor.query.filter_by(**filter_data).all()

How to obtain a single resource through its ID from a URL?

I have an URL such as: http://example.com/page/page_id
I want to know how to get the page_id part from url in the route. I am hoping I could devise some method such as:
#route('/page/page_id')
def page(page_id):
pageid = page_id
It's pretty straightforward - pass the path parameter in between angle brackets, but be sure to pass that name to your method.
#app.route('/page/<page_id>')
def page(page_id):
pageid = page_id
# You might want to return some sort of response...
You should use the following syntax:
#app.route('/page/<int:page_id>')
def page(page_id):
# Do something with page_id
pass
You can specify the ID as integer :
#app.route('/page/<int:page_id>')
def page(page_id):
# Replace with your custom code or render_template method
return f"<h1>{page_id}</h1>"
or if you are using alpha_num ID:
#app.route('/page/<username>')
def page(username):
# Replace with your custom code or render_template method
return f"<h1>Welcome back {username}!</h1>"
It's also possible to not specify any argument in the function and still access to URL parameters :
# for given URL such as domain.com/page?id=123
#app.route('/page')
def page():
page_id = request.args.get("id") # 123
# Replace with your custom code or render_template method
return f"<h1>{page_id}</h1>"
However this specific case is mostly used when you have FORM with one or multiple parameters (example: you have a query :
domain.com/page?cars_category=audi&year=2015&color=red
#app.route('/page')
def page():
category = request.args.get("cars_category") # audi
year = request.args.get("year") # 2015
color = request.args.get("color") # red
# Replace with your custom code or render_template method
pass
Good luck! :)

Categories