Last active
January 16, 2020 01:24
-
-
Save theskumar/7022218 to your computer and use it in GitHub Desktop.
User Management in django 1.5 and tastypie
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from tastypie.exceptions import TastypieError | |
from tastypie.http import HttpBadRequest | |
class CustomBadRequest(TastypieError): | |
""" | |
This exception is used to interrupt the flow of processing to immediately | |
return a custom HttpResponse. | |
Required after upgrading to django-tastypie==0.9.14 | |
""" | |
def __init__(self, code="", message=""): | |
self._response = { | |
"error": {"code": code or "not_provided", | |
"message": message or "No error message was provided."}} | |
@property | |
def response(self): | |
return HttpBadRequest( | |
json.dumps(self._response), | |
content_type='application/json') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tastpie userfrom django.contrib.auth.models import AbstractUser | |
from django.db import models | |
from django.utils.translation import ugettext as _ | |
class User(AbstractUser): | |
phone_number = models.CharField(_("Phone number"), max_length=20, blank=True) | |
@property | |
def name(self): | |
return self.get_full_name() | |
def __unicode__(self): | |
return self.username | |
class Meta: | |
verbose_name = _('User') | |
verbose_name_plural = _('Users') | |
#============================================================================== | |
# SIGNALS | |
#============================================================================== | |
def signals_import(): | |
""" A note on signals. | |
The signals need to be imported early on so that they get registered | |
by the application. Putting the signals here makes sure of this since | |
the models package gets imported on the application startup. | |
Important note: added it as a function in case someone does a ctrl+shift+O | |
in eclipse, the import will not be moved to the top of this file. | |
""" | |
from tastypie.models import create_api_key | |
models.signals.post_save.connect(create_api_key, sender=User) | |
signals_import() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.contrib.auth.hashers import make_password | |
from tastypie import fields | |
from tastypie.authentication import (Authentication, BasicAuthentication, | |
MultiAuthentication, ApiKeyAuthentication) | |
from tastypie.authorization import Authorization | |
from tastypie.cache import NoCache | |
from tastypie.resources import ModelResource | |
from .models import User | |
from .exceptions import CustomBadRequest | |
class UserResource(ModelResource): | |
"""Get and update user profile.""" | |
class Meta: | |
# Disable caching of objects returned from GET | |
cache = NoCache() | |
# For authentication, allow both basic and api key so that the key | |
# can be grabbed, if needed. | |
authentication = MultiAuthentication(BasicAuthentication(), | |
ApiKeyAuthentication() ) | |
authorization = Authorization() | |
detail_allowed_methods = ['get', 'patch', 'put'] | |
list_allowed_methods = ['patch', 'put'] | |
always_return_data = True | |
queryset = User.objects.all().select_related("api_key") | |
fields = ['email', 'first_name', 'last_name', 'phone_number', 'username'] | |
resource_name = 'profile' | |
def dehydrate(self, bundle): | |
bundle.data['key'] = bundle.obj.api_key.key | |
return bundle | |
def authorized_read_list(self, object_list, bundle): | |
# Return the profile of user making api reqeust. | |
return object_list.filter(id=bundle.request.user.id).select_related() | |
class SignupResource(ModelResource): | |
"""Endpoint to create a new account for a user.""" | |
class Meta: | |
queryset = User.objects.all() | |
detail_allowed_methods = ['post'] | |
list_allowed_methods = [] | |
always_return_data = True | |
authentication = Authentication() | |
authorization = Authorization() | |
resource_name = 'signup' | |
fields = ['email', 'first_name', 'last_name', 'phone_number', 'username'] | |
def dehydrate(self, bundle): | |
bundle.data['key'] = bundle.obj.api_key.key | |
del bundle.data['password'] | |
return bundle | |
def obj_create(self, bundle, **kwargs): | |
REQUIRED_USER_FIELDS = ("username", "email", "first_name", "last_name", "raw_password") | |
for field in REQUIRED_USER_FIELDS: | |
if field not in bundle.data: | |
raise CustomBadRequest( | |
code="missing_key", | |
message="Must provide {missing_key} when creating a user." | |
.format(missing_key=field)) | |
try: | |
username = bundle.data["username"] | |
if User.objects.filter(username=username): | |
raise CustomBadRequest( | |
code="duplicate_exception", | |
message="That username is already taken.") | |
except KeyError as missing_key: | |
raise CustomBadRequest( | |
code="missing_key", | |
message="Must provide {missing_key} when creating a user." | |
.format(missing_key=missing_key)) | |
except User.DoesNotExist: | |
pass | |
raw_password = bundle.data.pop('raw_password') | |
bundle.data["password"] = make_password(raw_password) | |
return super(SignupResource, self).obj_create(bundle, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
can u share about the blog post?