I'm trying to implement a Tastypie Resource that allows GET & POST operations following a per user-permission policy, the model is pretty simple (similar to the Note model in Tastypie documentation) and the resource itself is also pretty simple, I just have an extra override_urls method to implement search with Haystack.
My main problem now is that although running the project locally seems to be working fine, requests are fast and everything. Once I deployed the project (On Linode, using Nginx, Gunicorn, Runit), I discovered that POST requests are too slow, taking about a 1.1 min to come back with a 201 status. GET requests on the other hand are working well and as expected.
I ran a Python Hotshot profiler on the request and it's showing that the entire POST request is taking 0.127 CPU seconds. I'm not really sure what's happening here.
I should mention that I'm using ApiKeyAuthentication and DjangoAuthorization for my Tastypie resource.
Here's a screenshot from Chrome Inspector for the request: http://d.pr/i/CvCS
It would be great if anyone can direct me into the correct direction to look for an answer for this problem.
Thanks!
Edit:
Some code:
Models & Resource:
class Note(models.Model):timestamp = models.DateTimeField('Timestamp')user = models.ForeignKey(User)page_title = models.CharField("Page Title", max_length=200)url = models.URLField('URL', verify_exists=False)summary = models.TextField("Summary")notes = models.TextField("Notes", null=True, blank=True)def __unicode__(self):return self.page_titledef get_absolute_url(self):return self.urlclass NoteResource(ModelResource):user = fields.ForeignKey(UserResource, 'user')class Meta:queryset = Note.objects.all()resource_name = 'note'list_allowed_methods = ['get', 'post']detail_allowed_methods = ['get']always_return_data = Trueauthentication = ApiKeyAuthentication()authorization = DjangoAuthorization()# authentication = Authentication() #allows all access# authorization = Authorization() #allows all accessordering = ['-timestamp']def override_urls(self):return [url(r"^(?P<resource_name>%s)/search%s$" % (self._meta.resource_name, trailing_slash()),self.wrap_view('get_search'), name="api_get_search"),]def obj_create(self, bundle, request=None, **kwargs):return super(NoteResource, self).obj_create(bundle,request,user=request.user)def apply_authorization_limits(self, request, object_list):return object_list.filter(user=request.user)def get_search(self, request, **kwargs):self.method_check(request, allowed=['get'])self.is_authenticated(request)sqs = SearchQuerySet().models(Note).filter(user=request.user).auto_query(request.GET.get('q', ''))paginator = Paginator(sqs, 100)try:page = paginator.page(int(request.GET.get('page', 1)))except InvalidPage:raise Http404("Sorry, no results on that page.")objects = []for result in page.object_list:bundle = self.build_bundle(obj=result.object, request=request)bundle.data['score'] = result.scorebundle = self.full_dehydrate(bundle)objects.append(bundle)object_list = {'objects': objects,}self.log_throttled_access(request)return self.create_response(request, object_list)
Gunicorn Conf:
bind = "0.0.0.0:1330"
workers = 1
Nginx Conf (included in the main nginx.conf):
server {listen 80;server_name domain.com example.com;access_log /path/to/home/then/project/access.log;error_log /path/to/home/then/project/error.log;location / {proxy_pass http://127.0.0.1:1330;}location /static/ {autoindex on;root /path/to/home/then/project/;}
}