attomos
attomos

Reputation: 1202

How to write the django-piston handler to create and return ApiKey?

I'm currently working on the project that use Android for client and Django for web server. I decided to use piston-django to create REST API authentication and I've follow this instruction: What is the right way to write a django-piston client? and write my own handler (api/handlers.py) to create and return ApiKey like this:

class ApiKeyhandler(Basehandler):
    model = ApiKey
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
    fields = ('user', 'keys')

    def create(self, request):
        attrs = self.flatten_dict(request.POST)

        if self.exists(**attrs):
            return rc.DUPLICATE_ENTRY
        else:
            apikey = ApiKey(user=request.user)
            apikey.save()

            return apikey

and in urls.py I use HttpBasicAuthentication for this handler:

 auth = HttpBasicAuthentication(realm="Authentication API")
 apikey = Resource(handler=ApiKeyHandler, authentication=auth)

but when I test it with http://hurl.it

This is the response from GET

This is the response from POST method

Can anyone tell me how to write the complete code for this question or any suggestion on this problem?

Upvotes: 1

Views: 1128

Answers (1)

attomos
attomos

Reputation: 1202

Since nobody answer this question, I figured it out myself and some help from my friend. I have to edit ApiKeyHandler to

class ApiKeyHandler(BaseHandler):
    model = ApiKey
    allowed_methods = ('GET', 'POST')
    fileds = ('user', 'key')

    def read(self, request):
        # Return the API key for request.user
        values_query_set = request.user.keys.values('key')
        api_key = list(values_query_set)[0]['key']
        return HttpResponse(api_key)

    def create(self, request):
        #Create a new API Key.

        # Check if API key already exists
        if request.user.keys.count() > 0:
            values_query_set = request.user.keys.values('key')
            api_key = list(values_query_set)[0]['key']
            return HttpResponse(api_key)
        else:
            # Create API key
            api_key = ApiKey(user=request.user)
            api_key.save()
        return HttpResponse(api_key)

According to django-piston doc methodreadis called on GET and methodcreateis called on POST. Thus, when client want to create new API key; client need to request HTTP POST to create API key forrequest.userif the API key is not already exists.

Finally in models.py I need to edit the ApiKey model to

class ApiKey(models.Model):
    user = models.ForeignKey(User, related_name='keys', unique=True)
    key = models.CharField(max_length=KEY_SIZE, null=True, blank=True)

    def save(self, *args, **kwargs):
        self.key = User.objects.make_random_password(length=KEY_SIZE)

        while ApiKey.objects.filter(key__exact=self.key).count():
            self.key = User.objects.make_random_password(length=KEY_SIZE)

        super(ApiKey, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.key

We need to call the "real" save() method

super(ApiKey, self).save(*args, **kwargs)

and APIKeyAuthenticatin is work now.

Last but not least, when authenticating user, client need to request the HTTP request with HEADER ('Authorization', api_key).api_key must match with therequest.user.

Upvotes: 2

Related Questions