Eve framework: modify query_string - python

I'm writing API using Python EVE framework.
In my on_post_GET hook I want to extend request.query_string with some additional condition for some reason.
This request.query_string looks like a raw encoded string and it's not useful to add some new condition into existing.
My string looks like:
embedded=%7B%22some_key%22%3A1%2C%22another_key%22%3A1%2C%22one_more_key%22%3A1%2C%22and_more_key%22%3A1%2C%22and_more%22%3A1%2C%22some_specific_key%22%3A1%2C%22the_last_key%22%3A1%7D&where=%7B%22some_statement%22%3A%22in%28%5B%5C%22value1%5C%22%2C%5C%22value2%5C%22%5D%29%22%7D&max_results=10&page=1&sort=%5B%28%22date%22%2C0%29%5D
So, I want to add one additional condition into WHERE statement. I may parse it somehow, but there are a few things:
1) I may have another conditions and hardcoding related to condition looks terrible for me.
2) I hope, there is some better way to extend it somehow.
Thoughts?

You should be able to make your filter by handling the lookup inside a pre_GET event hook, as in this example from pyeve's documentation:
def pre_GET(resource, request, lookup):
# only return documents that have a 'username' field.
lookup["username"] = {'$exists': True}
app = Eve()
app.on_pre_GET += pre_GET
app.run()

Related

Is it OK to send the whole POST as a JSON object?

I am using GAE with python, and I am using many forms. Usually, my code looks something like this:
class Handler(BaseHandler):
#...
def post(self):
name = self.request.get("name")
last_name = self.request.get("last_name")
# More variables...
n = self.request.get("n")
#Do something with the variables, validations, etc.
#Add them to a dictionary
data = dict(name=name, last_name=last_name, n=n)
info = testdb.Test(**data)
info.put()
I have noticed lately that it gets too long when there are many inputs in the form (variables), so I thought maybe I could send a stringified JSON object (which can be treated as a python dictionary using json.loads). Right now it looks like this:
class Handler(BaseHandler):
#...
def post(self):
data = validate_dict(json.loads(self.request.body))
#Use a variable like this: data['last_name']
test = testdb.Test(**data)
test.put()
Which is a lot shorter. I am inclined to do things this way (and stop using self.request.get("something")), but I am worried I may be missing some disadvantage of doing this apart from the client needing javascript for it to even work. Is it OK to do this or is there something I should consider before rearranging my code?
There is absolutely nothing wrong with your short JSON-focused code variant (few web apps today bother supporting clients w/o Javascript anyway:-).
You'll just need to adapt the client-side code preparing that POST, from being just a traditional HTML form, to a JS-richer approach, of course. But, I'm pretty sure you're aware of that -- just spelling it out!-)
BTW, there is nothing here that's App Engine - specific: the same considerations would apply no matter how you chose to deploy your server.

Idiomatic/fast Django ORM check for existence on mysql/postgres

If I want to check for the existence and if possible retrieve an object, which of the following methods is faster? More idiomatic? And why? If not either of the two examples I list, how else would one go about doing this?
if Object.objects.get(**kwargs).exists():
my_object = Object.objects.get(**kwargs)
my_object = Object.objects.filter(**kwargs)
if my_object:
my_object = my_object[0]
If relevant, I care about mysql and postgres for this.
Why not do this in a try/except block to avoid the multiple queries / query then an if?
try:
obj = Object.objects.get(**kwargs)
except Object.DoesNotExist:
pass
Just add your else logic under the except.
django provides a pretty good overview of exists
Using your first example it will do the query two times, according to the documentation:
if some_queryset has not yet been evaluated, but you
know that it will be at some point, then using some_queryset.exists()
will do more overall work (one query for the existence check plus an
extra one to later retrieve the results) than simply using
bool(some_queryset), which retrieves the results and then checks if
any were returned.
So if you're going to be using the object, after checking for existance, the docs suggest just using it and forcing evaluation 1 time using
if my_object:
pass

webapp2: regex in routing

I have such a problem: I want one method of the class to handle different URIs (for URI "/solution/add" and "solution/edit"). So I wrote such routing:
app = webapp2.WSGIApplication([webapp2.Route(r'/solutions/(add|edit)', handler='solution.SolutionPage:add_edit_solution'), ], debug=True)
And webapp2 gives 404 error. Could you please suggest the solution of this problem?
Ofcourse I can write different routes for every URI, but it's not so interesting.)
As the webapp2 docs indicate, you have to put the regex in angle brackets, with a colon separating name and expression. The name is optional, but
everything outside of <> is not interpreted as a regular expression to be matched
So something like this: '/blog/<:\d{4}>/<:\d{2}>' Or in your case, this:
webapp2.Route(r'/solutions/<:(add|edit)>',
handler='solution.SolutionPage:add_edit_solution')
If I can add something.
For my own purpose, I've try to create a handler which perform a little bit similar operation, but the point is that I've used self.request.host or self.request.route instead of arguments.
Doing this, and parsing the result with a switch case or if/elif/else loop, allow me to create a class named URIHandler which is use to route any kind of request to the correct ressources (even 404/500/yyy error pages) dynamicly whithout having to rewrite or add route for each new ressources.
So I'll be interested in comparing the two method to bench them a little bit.

SQLAlchemy - loading user by username

Just diving into pylons here, and am trying to get my head around the basics of SQLALchemy. I have figured out how to load a record by id:
user_q = session.query(model.User)
user = user_q.get(user_id)
But how do I query by a specific field (i.e. username)? I assume there is a quick way to do it with the model rather than hand-building the query. I think it has something with the add_column() function on the query object, but I can't quite figure out how to use it. I've been trying stuff like this, but obviously it doesn't work:
user_q = meta.Session.query(model.User).add_column('username'=user_name)
user = user_q.get()
I believe you want something like this:
user = meta.Session.query(model.User).filter_by(name=user_name).first()
Which is short for this:
user = meta.Session.query(model.User).filter(model.User.name=user_name).first()
Here's more documentation
If you change first() into one() it will raise an exception if there isn't a user (if you want to assert one exists).
I highly suggest reading through both Object Relational Tutorial as well as the and the SQL Expression Language Tutorial.

Duplicate an AppEngine Query object to create variations of a filter without affecting the base query

In my AppEngine project I have a need to use a certain filter as a base then apply various different extra filters to the end, retrieving the different result sets separately. e.g.:
base_query = MyModel.all().filter('mainfilter', 123)
Then I need to use the results of various sub queries separately:
subquery1 = basequery.filter('subfilter1', 'xyz')
#Do something with subquery1 results here
subquery2 = basequery.filter('subfilter2', 'abc')
#Do something with subquery2 results here
Unfortunately 'filter()' affects the state of the basequery Query instance, rather than just returning a modified version. Is there any way to duplicate the Query object and use it as a base? Is there perhaps a standard Python way of duping an object that could be used?
The extra filters are actually applied by the results of different forms dynamically within a wizard, and they use the 'running total' of the query in their branch to assess whether to ask further questions.
Obviously I could pass around a rudimentary stack of filter criteria, but I'd rather use the Query itself if possible, as it adds simplicity and elegance to the solution.
There's no officially approved (Eg, not likely to break) way to do this. Simply creating the query afresh from the parameters when you need it is your best option.
As Nick has said, you better create the query again, but you can still avoid repeating yourself. A good way to do that would be like this:
#inside a request handler
def create_base_query():
return MyModel.all().filter('mainfilter', 123)
subquery1 = create_base_query().filter('subfilter1', 'xyz')
#Do something with subquery1 results here
subquery2 = create_base_query().filter('subfilter2', 'abc')
#Do something with subquery2 results here

Categories

Resources