Sadak
Sadak

Reputation: 911

Manage Multiple Params with GET Flask restful MongoEngine Clean Code

I'm creating an API with flask_restful, and I want to search for example with two parameters that will be passed by GET, tag and author.

with the code below I can do this. However, it's necessary that I should pass the two parameters. I want whatever the parameter the user passed still search for it,

Exempli gratia: if I passed tag=tech the response should have all the news with tag tech and with all authors if also I passed the author it should consider tag as all -i think u got it-

class ArticleAPI(Resource):
    def get(self):
        tag=request.args.get('tag','')
        auth=request.args.get('author','')

        news = News.objects.filter(topic=tag,author=auth).to_json()
        return Response(news, mimetype="application/json", status=200)

i know i can do it long just like this, but it looks ugly :`(

    if tag is not None and auth is not None :
            news = News.objects.filter(topic=tag,author=auth).to_json()
        elif tag is not None :
            news = News.objects.filter(topic=tag).to_json()
        elif auth is not  None:
            news = News.objects.filter(author=auth).to_json()

I'm using Flask_mongoengine

from flask_mongoengine import MongoEngine

db = MongoEngine()

def initialize_db(app):
    db.init_app(app)

Upvotes: 0

Views: 944

Answers (1)

Jon
Jon

Reputation: 1850

I think you are asking how to pass in keyword arguments into the .filter() method in a more concise way.

According to the mongoengine docs, .filter() is an alias for __call__(). It takes a Query object, or keyword arguments for the **query parameter. Your code is using the keywords style.

You could put the tag and auth variables into a dict, then unpack them using a double splat as keyword arguments.

Something like this:

fdict = dict()
if tag : fdict['tag'] = tag
if auth: fdict['auth'] = auth

news = News.objects.filter(**fdict).to_json()

Now you can add as many of these parameters as you want and it should be the same syntax.

You could just pass in all query params at once. This is the cleanest way I can think of:

news = News.objects.filter(**request.args).to_json()

That said, there is usually a security tradeoff for blindly taking user provided data and passing into a database. I don't know enough about how Mongo handles this to speak intelligently about what is best practice here. Plus, what you name on the UI side may not have the same name on the DB side.

This is also possible using a Query object, but I haven't done any MongoDB stuff in a long time and the syntax seems very specific, so I won't attempt here. :)

Upvotes: 1

Related Questions