|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 | Next > |
|
|
Exposing the request object. RequestExposingDjangoGatewayHey all,
We're currently developing a small project which will use a Flash 8 frontend and a Django backend. Because we need to allow people to input some of their personal data in flash, which we then would like to reuse in a different flash we need access to the request object used by the AMF calls. To enable this, I wrote a quick subclass of the pyamf.gateway.DjangoGateway class which seems to do the trick. I'll just post the code here in case anyone else may find it useful (and also to have an extra set of eyeballs maybe checking it for bugs :)): import pyamf from pyamf import remoting, gateway class RequestExposingDjangoGateway(gateway.DjangoGateway): def __call__(self, request): if request.method == 'POST': response = HttpResponse() context = pyamf.get_context(pyamf.AMF0) amfrequest = remoting.decode(request.raw_post_data, context) amfresponse = remoting.Envelope(amfrequest.amfVersion, amfrequest.clientType ) processor = self.getProcessor(amfrequest) for name, message in amfrequest: amfresponse[name] = processor(message, request) stream = remoting.encode(amfresponse, context) response['Content-Type'] = remoting.CONTENT_TYPE response['Content-Length'] = str(len(stream)) response.write(stream.getvalue()) else: response = HttpResponseNotAllowed(['POST']) return response def processRequest(self, message, request): """ This is mainly a copy from the BaseGateway code. The only change is the call to getServiceRequest that now includes the request parameter. """ response = remoting.Message(None, None, None, None) service_request = self.getServiceRequest(message) #we have a valid service, now attempt authentication if not self._authenticate(service_request, message): # FIXME: what error to return here? response.status = remoting.STATUS_ERROR response.body = dict( code=' SERVER.AUTHENTICATION', level='Auth' ) return response try: response.body = service_request(request, *message.body) response.status = remoting.STATUS_OK except (SystemExit, KeyboardInterrupt): raise except: response.body = self.getErrorResponse(sys.exc_info()) response.status = remoting.STATUS_ERROR return response Initial tests indicate that this code works, as long as you remember that the first parameter to any function invoked by this gateway will be the request. I'm rather novice to Python, so any suggestions are welcome. One slight remark I have from going through a little bit of the source code is the seemingly inconsistent variable naming. There are a few functions, especially in the BaseGateway implementation that take a 'request' parameter, where the type of this parameter is actually different from request. I think legibility would be greatly enhanced if parameter names represent their types a bit better. |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGateway
Hey Bart,
On Wed, 2007-11-28 at 08:58 +0100, bart vandendriessche wrote: Hey all,Welcome! Thanks for putting something like this together, its great to know that the code we put together is starting to be exercised :) There is no such class gateway.DjangoGateway, perhaps you meant gateway.django.DjangoGateway? There has been an iteration in the gateway API, you may want to check that out. There is no _authenticate/getErrorResponse functions anymore, check the latest source for more info. Gateways are probably the most unstable in terms of API, but we are working as quick as possible to them nailed down. Yep, I would agree with that, ticket #102 _______________________________________________ PyAMF dev mailing list - dev@... http://lists.pyamf.org/mailman/listinfo/dev |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayHey Nick,
Yeah sorry, the copy pasting was done from a "work in progress" version of my class and the imports are wrong :) The comment is wrong as well, it's not the getServiceRequest call that receives the request now, but the call to service_request. I will check the updated code later, right now this works for us, and I'm trying to have as little moving parts as possible. Thanks for opening the ticket for me. Cheers, Bart
On Nov 28, 2007 11:14 AM, Nick Joyce <nick@...> wrote:
|
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayHelo,
On Nov 28, 2007 7:58 AM, bart vandendriessche <bart.vandendriessche@...> wrote: > We're currently developing a small project which will use a Flash 8 frontend > and a Django backend. Because we need to allow people to input some of their > personal data in flash, which we then would like to reuse in a different > flash we need access to the request object used by the AMF calls. Welcome to the party. > To enable this, I wrote a quick subclass of the pyamf.gateway.DjangoGateway > class which seems to do the trick. I'll just post the code here in case > anyone else may find it useful (and also to have an extra set of eyeballs > maybe checking it for bugs :)): Your code makes perfect sense in the Django context, sending the request as the first parameter is standard Django practice. Therefore, I'm thinking if we should provide this as an optional functionality of the DjangoGateway. Probably have it turned off by default, but keep a paramter to the constructor that when turned on, the gateway will prepend the request to all function calls. Nick, Thijs, thoughts on this? > I'm rather novice to Python, so any suggestions are welcome. One slight > remark I have from going through a little bit of the source code is the > seemingly inconsistent variable naming. There are a few functions, > especially in the BaseGateway implementation that take a 'request' > parameter, where the type of this parameter is actually different from > request. I think legibility would be greatly enhanced if parameter names > represent their types a bit better. When you talk about the "type of request", are you referring to the django.http.request object? BaseGateway (or most of pyamf for that matter) is not written with Django in mind, but rather as a general multi-purpose library. IMO there's no need to worry about naming collision with Django, since one can assume a "request" refers to an AMF remoting request. Your point stil stands though, meaningful variable and function names are always good as long as one doesn't get carried away [1] :) [1] http://worsethanfailure.com/Articles/Overruled-by-RemoveSpecialCharsExceptQuoteAmpersand.aspx cheers, Arnar |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayOn Wed, 2007-11-28 at 11:37 +0000, Arnar Birgisson wrote: If its Django standard practice, then for the Django gateway, we should include the request as the first request by default?Helo, On Nov 28, 2007 7:58 AM, bart vandendriessche <bart.vandendriessche@...> wrote: > We're currently developing a small project which will use a Flash 8 frontend > and a Django backend. Because we need to allow people to input some of their > personal data in flash, which we then would like to reuse in a different > flash we need access to the request object used by the AMF calls. Welcome to the party. > To enable this, I wrote a quick subclass of the pyamf.gateway.DjangoGateway > class which seems to do the trick. I'll just post the code here in case > anyone else may find it useful (and also to have an extra set of eyeballs > maybe checking it for bugs :)): Your code makes perfect sense in the Django context, sending the request as the first parameter is standard Django practice. Therefore, I'm thinking if we should provide this as an optional functionality of the DjangoGateway. Probably have it turned off by default, but keep a paramter to the constructor that when turned on, the gateway will prepend the request to all function calls. Nick, Thijs, thoughts on this? Humm, on second thoughts to keep the underlying service code as portable as possible (over gateways), we should include a constructor param to turn this on. Ticket #103. > I'm rather novice to Python, so any suggestions are welcome. One slight > remark I have from going through a little bit of the source code is the > seemingly inconsistent variable naming. There are a few functions, > especially in the BaseGateway implementation that take a 'request' > parameter, where the type of this parameter is actually different from > request. I think legibility would be greatly enhanced if parameter names > represent their types a bit better. When you talk about the "type of request", are you referring to the django.http.request object? BaseGateway (or most of pyamf for that matter) is not written with Django in mind, but rather as a general multi-purpose library. IMO there's no need to worry about naming collision with Django, since one can assume a "request" refers to an AMF remoting request. Your point stil stands though, meaningful variable and function names are always good as long as one doesn't get carried away [1] :) [1] http://worsethanfailure.com/Articles/Overruled-by-RemoveSpecialCharsExceptQuoteAmpersand.aspx cheers, Arnar _______________________________________________ PyAMF dev mailing list - dev@... http://lists.pyamf.org/mailman/listinfo/dev |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayHey there,
On Nov 28, 2007 11:49 AM, Nick Joyce <nick@...> wrote: > If its Django standard practice, then for the Django gateway, we should > include the request as the first request by default? > > Humm, on second thoughts to keep the underlying service code as portable as > possible (over gateways), we should include a constructor param to turn this > on. Yes, definitely. Arnar |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayRight, here comes a bit of personal opinion:
It does fit Django pretty well to provide the request object as the first parameter since this mimics the way Django views work. However, I do believe this is something that users of other frameworks (or users who don't use any framework) might find useful as well. We have previously developed a application using amf and java, where we had a need to access the request object, and it required a bit of a hack there as well. So it might be interesting, if you are planning to provide this functionality through a constructor param, to provide it in the BaseGateway implementation. Arnar: when I say type of request, I mean the type(request) :) It was slightly confusing to be reading code where the variable's name is 'Request' but the type(variable) is 'Message' or 'Envelope'. If you check the ticket that Nick created, I think that perfectly illustrates my point. Cheers, Bart On Nov 28, 2007 12:56 PM, Arnar Birgisson <arnarbi@...> wrote: Hey there, |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGateway
If someone put together a service that adds two numbers together (too simplistic I know, but good for illustration), they would write something like this:
def sum(a, b): return a + b To have to write something like: def sum(request, a, b): return a + b Is ugly, and we need to be able to come up with something better. Also, does the request refer to the AMF request that was made or the underlying protocol (HTTP or RTMP)? I have been toying with the idea of adding a function variable at execution that holds the context of the request, including the AMF request and (in this case the HTTP request). So in this case: def sum(a, b): http_request = sum.context.http_request I'm not 100% on the implementation of this, but you get the idea. I admit, it's an ugly hack and if there is another way, without polluting the argument space of the defining function, let me know about it :) Thoughts? On Wed, 2007-11-28 at 13:29 +0100, bart vandendriessche wrote: Right, here comes a bit of personal opinion: On Nov 28, 2007 12:56 PM, Arnar Birgisson <arnarbi@...> wrote:
Yes, definitely.
|
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayOn Nov 28, 2007 12:29 PM, bart vandendriessche
<bart.vandendriessche@...> wrote: > It does fit Django pretty well to provide the request object as the first > parameter since this mimics the way Django views work. However, I do believe > this is something that users of other frameworks (or users who don't use any > framework) might find useful as well. We have previously developed a > application using amf and java, where we had a need to access the request > object, and it required a bit of a hack there as well. So it might be > interesting, if you are planning to provide this functionality through a > constructor param, to provide it in the BaseGateway implementation. I disagree. Most frameworks have a different notion of what a request objects is, and in some contexts there not even a request object per se. CherryPy for example uses thread-locals for request specific data and does not pass a request object as parameters. The notion of a request object being one of the parameters is completely arbitrary and an implementation detail of the underlying framework. Also, AMF remoting is not only used in the context of HTTP, there is also RTMP and possibly others in the future, where a "request object" doesn't even have a well defined meaning. cheers, Arnar |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayArnar and Nick, you both raise very good points. My reasoning on this is a bit shortsighted probably.
I do see your concerns about not wanting to pollute the argument space, and the fact that AMF is not solely used in an HTTP context / not all applications share the request notion. I don't see any obvious way in which both these concerns can be satisfied. I'll do some more digging into python and AMF when time permits, and will share any insights I might get. Cheers, Bart On Nov 28, 2007 1:56 PM, Arnar Birgisson <arnarbi@...> wrote: On Nov 28, 2007 12:29 PM, bart vandendriessche |
|
|
|
Re: Exposing the request object. RequestExposingDjangoGatewayOn Nov 28, 2007 1:22 PM, bart vandendriessche
<bart.vandendriessche@...> wrote: > I do see your concerns about not wanting to pollute the argument space, and > the fact that AMF is not solely used in an HTTP context / not all > applications share the request notion. I don't see any obvious way in which > both these concerns can be satisfied. I think having it configurable per implementation specific gateways (such as DjangoGateway) should take care of it fairly cleanly. > I'll do some more digging into python and AMF when time permits, and will > share any insights I might get. Thanks, we value any input. Arnar |
|
|
|
to BartHi Bart,
Since you are trying some Django-PyAMF stuff, I have a question. Have you already tried to return some objects (members etc.) from Django to Flash? I did but got errors. Bye, Rob |
|
|
|
Re: to BartHey Rob,
Yes we're returning some simple custom objects to flash at the moment. Keep in mind though that we're not doing anything complex at all. We haven't run into any problems just yet. Cheers, Bart On Nov 28, 2007 5:33 PM, Robert Slotboom <rob.slotboom@...> wrote: Hi Bart, |
|
|
|
Re: to BartHi Bart,
How did you return the objects without errors then? Here is what I did. ### urls.py ### from django.conf.urls.defaults import * urlpatterns = patterns('flashboard.customers.gateway', url(r'^gateway/', 'gateway', name="show_gateway"), ) ### gateway.pt ### from django_apps.pyamf.gateway.django import DjangoGateway import amf_views gateway = DjangoGateway({'customerData': amf_views}) ### amf_views.py ### from flashboard.customers.models import CustomerInfo, Category def echo(data): return data def getCategories(): return Category.objects.all().values() def getCategoriesAsStr(): ret_str = '' for c in Category.objects.all(): ret_str += " | %s" % c.Name return ret_str def getCustomers(customer_id): return CustomerInfo.objects.filter(CategoryID__exact=customer_id).values() ### result ### Calling service method getCategories from within Flash makes the server crash. Calling getCategoriesAsStr works fine. Maybe you have a clue? Bye, --Rob |
|
|
|
Re: to BartWell, I wouldn't really know, but have you checked what happens when you return a single Category or CustomerInfo object ?
Right now it seems like you're trying to serialize a ValuesQuerySet object which contains a bunch of dict's. I haven't looked at the source for the ValuesQuerySet object, but maybe something blows up trying to serialize that ? If you manage to send a single Category object to flash, I would try to convert the ValuesQuerySet into a tuple or a plain list and send that. On Nov 29, 2007 8:51 AM, Robert Slotboom <
rob.slotboom@...> wrote: Hi Bart, |
|
|
|
Django returns an object!!Hi Nick, Arnar, Bart,
Today I updated the pyamf source an changed my testcode a bit: ### customers/amf_views.py ### def getCustomer(ID): return CustomerInfo.objects.get(ID__exact=ID) ### flashboard.fla ### [snip...] var myService:Service = new Service("http://192.168.1.50:8000/customers/ gateway/",null,"customerData", null, null); trace( "no response from server yet." ); var param = "Hello World!"; var pc1:PendingCall = myService.echo(this.param); pc1.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); var pc2:PendingCall = myService.getCustomer(6); pc2.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); ### Flash traces ### no response from server yet. [object Object] Hello World! Seems like some progress } : o ) Robert Slotboom |
|
|
|
Re: Django returns an object!!Hi Robert,
Ok, then the problem seems with returning list results. >From your earlier attemts, try explicitly evaluating the queries to lists with def getCategories(): return list(Category.objects.all()) as Bart suggested. Arnar On Nov 29, 2007 3:52 PM, Robert Slotboom <rob.slotboom@...> wrote: > Hi Nick, Arnar, Bart, > > Today I updated the pyamf source an changed my testcode a bit: > > ### customers/amf_views.py ### > > def getCustomer(ID): > return CustomerInfo.objects.get(ID__exact=ID) > > > ### flashboard.fla ### > > [snip...] > var myService:Service = new > Service("http://192.168.1.50:8000/customers/ > gateway/",null,"customerData", null, null); > trace( "no response from server yet." ); > > var param = "Hello World!"; > var pc1:PendingCall = myService.echo(this.param); > pc1.responder = new RelayResponder(this, "getData_Result", > "getData_Fault"); > > var pc2:PendingCall = myService.getCustomer(6); > pc2.responder = new RelayResponder(this, "getData_Result", > "getData_Fault"); > > ### Flash traces ### > > no response from server yet. > [object Object] > Hello World! > > Seems like some progress } : o ) > > > Robert Slotboom > > _______________________________________________ > PyAMF dev mailing list - dev@... > http://lists.pyamf.org/mailman/listinfo/dev > > |
|
|
|
Re: Django returns an object!!Thanks for the update Robert because I think you found a bug..
I don't see why that "Hello World!" trace is not shown first. I opened ticket #105 Cheers, Thijs |
|
|
|
Re: Django returns an object!!Hi Thijs,
> Thanks for the update Robert because I think you found a bug.. > >> no response from server yet. >> [object Object] >> Hello World! >> > > I don't see why that "Hello World!" trace is not shown first. I opened > ticket #105 Sorry, I should have told you earlier. Another strange behaviour: urlpatterns += patterns('flashboard.customers.gateway', (r'^gateway/', 'gateway'), ) After updating to the latest version of PyAMF I get a Django template errors when entering admin. TemplateSyntaxError at /admin/ 'adminapplist' is not a valid tag library: Could not load template library from django.templatetags.adminapplist, cannot import name template Request Method: GET Request URL: http://192.168.1.50:8000/admin/ Exception Type: TemplateSyntaxError Exception Value: 'adminapplist' is not a valid tag library: Could not load template library from django.templatetags.adminapplist, cannot import name template Exception Location: /usr/local/lib/python2.5/site-packages/django/template/defaulttags.py in load, line 859 Python Executable: /usr/local/bin/python Python Version: 2.5.1 Cheers, --Rob |
|
|
|
Re: Django updateHi all,
An update if the current results trying to get the flash customer app sample running using Django and PyAMF. ### models.py ### class Category(models.Model): ID_CHOICES = ( ('B', 'Billable'), ('N', 'Nonbillable'), ('P', 'Prospect'), ) ID = models.CharField(maxlength=1, primary_key=True, choices=ID_CHOICES) Name = models.CharField(maxlength=50) Description = models.CharField(maxlength=50) class CustomerInfo(models.Model): ID = models.AutoField(primary_key=True) CategoryID = models.ForeignKey(Category) Name = models.CharField(max_length=50) Active = models.BooleanField() Logo = models.CharField(maxlength=50) Details = models.CharField(maxlength=255) TotalSales = models.DecimalField(max_digits=8, decimal_places=2) ### urls.py ### from django.conf.urls.defaults import * urlpatterns = patterns('flashboard.customers.views', url(r'^$', 'list', name="show_customer_list"), url(r'^(?P<customer_id>\d+)/$', 'details', name="show_customer_details"), ) urlpatterns += patterns('flashboard.customers.gateway', (r'^gateway/', 'gateway'), ) ### gateway.py ### from django_apps.pyamf.gateway.django import DjangoGateway import amf_views gateway = DjangoGateway({'customerData': amf_views}) ### amf_views.py ### from flashboard.customers.models import CustomerInfo, Category def echo(data): return data def getCategories(): return list(Category.objects.all()) def getCategory(ID): return Category.objects.get(ID__exact=ID) def getCustomers(CategoryID): return list(CustomerInfo.objects.filter(CategoryID__exact=CategoryID)) def getCustomer(ID): return CustomerInfo.objects.get(ID__exact=ID) ### Flash MX 2004 AS 2 ### import mx.remoting.Service; // import Service class import mx.rpc.FaultEvent; // import FaultEvent class import mx.remoting.PendingCall // import PendingCall class import mx.rpc.ResultEvent // import ResultEvent class import mx.rpc.RelayResponder // import RelayResponder class mx.remoting.debug.NetDebug.initialize(); var myService:Service = new Service("http://192.168.1.50:8000/customers/ gateway/",null,"customerData", null, null); trace( "no response from server yet." ); // This var holds the data we want to pass to the remote service. var param = "Hello World!"; var pc1:PendingCall = myService.echo(this.param); pc1.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); // This var is a customer we want to get var Customer_ID = 6; var pc2:PendingCall = myService.getCustomer(Customer_ID); pc2.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); // This var is a category we want to get var Category_ID = "B"; var pc3:PendingCall = myService.getCategory(Category_ID); pc3.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); // This var is a customer category we want to get var Category_ID = "B"; var pc4:PendingCall = myService.getCustomers(Category_ID); pc4.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); // Get all categories var pc5:PendingCall = myService.getCategories(); pc5.responder = new RelayResponder(this, "getData_Result", "getData_Fault"); function getData_Result( re:ResultEvent ):Void { // receive result trace( re.result ); } function getData_Fault( fe:FaultEvent ):Void { trace( "There was a problem: " ); for (var prop:String in fe.fault){ trace(prop + " - " + fe.fault[prop]); } } ### Ze trace ### no response from server yet. [object Object],[object Object],[object Object] [object Object],[object Object] [object Object] [object Object] Hello World! hth, Rob |
| < Prev | 1 - 2 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |