Tastypie Urls and Filters - tastypie

I would like to use tastypie with some slightly different urls. I would like them to be like this:
/api/v1/city/London/make_default
/api/v1/city/Paris/make_default
/api/v1/city/Singapore/remove_city
Where the city itself can be any city in the city table in my db and the resource name is the method I want to perform. Each method has it's own resource. In tastypie the urls seem to give me some trouble with this. The prepend_urls that I have keep giving me a 301 redirect.
class CityResource(Resource):
class Meta
def make_default(self, request, city_name):
return super(ViewTemplateResource, self).get_object_list(request)\
.filter(name=city_name, client=request.user).update(default=True)
def prepend_urls(self):
return [
url(r"^city/(?P<city_id>[\w\d_.-]+)/(?P<resource_name>%s)/$" % self._meta.resource_name,
self.wrap_view('make_default')),
]

So to solve this I did it a bit differently:
first the wrap view was avoiding the normal pathway of tastypie instead of adding to it:
def dispatch_default(self, request, city_name, **kwargs):
self.queryset = City.objects.filter(name=city_name, client=user)
return self.dispatch('detail', request, **kwargs) # could use super here too instead of copying the normal code
def prepend_urls(self):
return [
url(r"^city/(.+)/(?P<resource_name>%s)$" % self._meta.resource_name,
self.wrap_view('dispatch_detail')),
]

Related

Graphene: How to add a function before query execute?

Is there a way to execute a function before all query?
When I add an annotation above Query class, It makes an error
AssertionError: Type <function Query at 0x104d1dd30> is not a valid ObjectType.
def my_func(f):
#wraps(f)
def my_func_wrap(*args, **kwargs):
//do something
return f(*args, **kwargs)
return my_func_wrap
#my_func
class Query(graphene.ObjectType):
node = relay.Node.Field()
users = graphene.List(lambda: UserSchema)
def resolve_users(self, info):
//do something
return User.query.all()
schema = graphene.Schema(query=Query)
If i add the annotation to every resolver, It works fine.
but I will add more than 20 resolvers and I don't think adding the annotation to every resolver is good idea.
Yes, you can. Just create a custom View class inheriting from GraphQLView and override dispatch method then use your own view class as graphql endpoint handler. Something like this:
class CustomGraphQLView(GraphQLView):
def dispatch(self, request, *args, **kwargs):
// do something
super(CustomGraphqlView, self).dispatch(request, *args, **kwargs)
If you want to manipulate the queryset itself, I suggest to use graphene-django-extras and override the list_resolver method on its query fields(DjangoFilterListField, DjangoFilterPaginateListField, ...) class and use your own custom class.
You can call super on override methods or copy the exact code from their source and edit them.

flask redirect from closure

def check_login(func):
"""Check if user is logged in."""
def decorator(*args, **kwargs):
if not login_session_test():
print ("Not logged in - redirect to /login")
flash ("Well that was wrong. Chicken winner. No more dinner.")
return redirect(url_for('login'))
print ("Logged in, do what needs to be done.")
return func(*args, **kwargs)
return decorator
#check_login
#app.route("/sacred/secret/stuff", methods=['GET'])
def funfunfun():
return "Super fun"
It never redirects to /login but gives some garbage like page.
Swapping the #/closure order yields:
AssertionError: View function mapping is overwriting an existing endpoint function: decorator
I am not yet fully pythonized.
Your decorator order is incorrect, and you are not copying across the function name to the wrapper function.
Use this order:
#app.route("/sacred/secret/stuff", methods=['GET'])
#check_login
def funfunfun():
return "Super fun"
Otherwise the undecorated function is registered for the view.
Use #functools.wraps() to have various pieces of metadata copied over from the original wrapped function to the wrapper that replaces it:
from functools import wraps
def check_login(func):
"""Check if user is logged in."""
#wraps(func)
def decorator(*args, **kwargs):
if not login_session_test():
print ("Not logged in - redirect to /login")
flash ("Well that was wrong. Chicken winner. No more dinner.")
return redirect(url_for('login'))
print ("Logged in, do what needs to be done.")
return func(*args, **kwargs)
return decorator
Routes need an endpoint name, and if you don't specify one explicitly, Flask uses the name of the function (from functionobj.__name__). But your decorator wrapper object has the name decorator, so if you use the decorator more than once Flask complains that it already has used that endpoint name.
#functools.wraps() copies across the __name__ attribute, so now your decorator wrapper is also called funfunfun, whereas another decorated route function gets to keep its name too.

Spray routing: How to respond with different content-types?

In spray I would like to respond with different content-types, depending on the given Accept header. I've seen a couple of suggestions in the question by rompetroll, but I would like to hear if there are any canonical way of doing it (i. e. simple or already implemented).
In essence what I imagine should happen is something like:
path("somepath") {
get {
// Find whatever we would like to return (lazily)
...
// Marshall resource and complete depending on the `Accept` header
...
}
}
Thanks in advance.
See the tests in this commit.
I copied it here for reference:
case class Data(name: String, age: Int)
object Data {
import spray.json.DefaultJsonProtocol._
import spray.httpx.SprayJsonSupport._
// don't make those `implicit` or you will "ambiguous implicit" errors when compiling
val jsonMarshaller: Marshaller[Data] = jsonFormat2(Data.apply)
val xmlMarshaller: Marshaller[Data] =
Marshaller.delegate[Data, xml.NodeSeq](MediaTypes.`text/xml`) { (data: Data) ⇒
<data><name>{ data.name }</name><age>{ data.age }</age></data>
}
implicit val dataMarshaller: ToResponseMarshaller[Data] =
ToResponseMarshaller.oneOf(MediaTypes.`application/json`, MediaTypes.`text/xml`) (jsonMarshaller, xmlMarshaller)
}
You then using complete should suffice in your route, content-type negotiation is automatically taken care of:
get {
complete(Data("Ida", 83))
}
Spray is actually looking into the Accept header value and validates against it. So if route is returning application/json or text/plain and client accepts image/jpeg than spray will return 406 Not Acceptable. If client will request application/json ortext/plain from this route than he will receive repsonse with matching Content-Type.
The main trick here is to use correct marshallers for return objects.
You can read more about marshalling here.
Also you can override MediaType with respondWithMediaType directive, but I think it is better to use correct marshallers.

How to send an array of a complex object with GroovyWS

I'm about to call a webservice created in C#, that takes a parameter
KmlSystemVariable[] sysVariables
How can I pass a parameter like that using GroovyWS? It doesn't need to have any values, could be an empty array.
Looks like the full class name is Consorte.Pulse.Data.KmlSystemVariable
I enabled logging as described in GroovyWS and complex requests to get the namespace for KmlSystemVariable, and it looks like I can create a KmlSystemVariable with:
proxy.create("org.datacontract.schemas._2004._07.consorte_pulse.KmlSystemVariable")
But how do I create an array of KmlSystemVariable?
It should be enough to just wrap your proxied objects into a Groovy list and use it as the parameter. GroovyWS will do the transformation from List to SOAP array for you behind the scenes.
Example:
def ksv1 = proxy.create("org.datacontract.schemas._2004._07.consorte_pulse.KmlSystemVariable")
def ksv2 = ...
def ksv3 = ...
def list = [ksv1, ksv2, ksv3]
proxy.<some ws method>(list)

Really confused about snippets

I have a problem with my lift view. The thing is, I am making an expensive remote rest-api call twice - where I should really need to do it only once.
But I can't figure out how to solve this.
Basically I have an HTML template like this, that needs to display the list of users and their count:
//UserSearchResults.html
Num users: <span class="lift:UserSearchResults.userCount"></span>
User list:
<ul>
<lift:UserSearchResults.userList>
<li><user:userName/></li>
</lift:UserSearchResults.userList>
</ul>
And then I have an actual snippet that goes and retrieves the list of users from the rest-api server. However, note that it actually does this TWICE - once to count the number of users, and once to render the list.
//UserSearchResults.scala
/** Get list of users from api */
def users: List[User] = {
val url = "http://server/rest-api/user-search";
val result = io.Source.fromURL(url).mkString
//... parse users into List[User] and return it
return entries
}
/** Render user count */
def userCount =
"* *" #> users.length //<-- ONE call
def userList(in: NodeSeq): NodeSeq = {
users.flatMap(user => Helpers.bind("user", in, //<--SECOND call
"userName" -> user.user_name))
}
Is there a better place to put the api call? Is there like a "constructor" for the snippet, that I can use cache the user list, and to share it across all the functions in the class?
Any help is appreciated.
If UserSearchResults is a class (as opposed to an object), then there will be a per-request instance of that class. As such, all you have to do is change your def users to a lazy val users and you should be good to go.
If your snippet extends StatefulSnippet, you can just save the list in an instance variable. Another option would be to put the list into a RequestVar. Then it could also be accessed from other snippets.