I have a Tastypie resource for a model extended from django.contribut.auth's User model (just a few extra fields). Here's the resource code:
class CustomerResource(ModelResource):
locations = fields.ToManyField('device.resources.LocationResource',
'location_set', null=True)
current_location = fields.ToOneField('device.resources.LocationResource',
'current_location', null=True)
default_location = fields.ToOneField('device.resources.LocationResource',
'default_location', null=True)
class Meta:
queryset = Customer.objects.all()
resource_name = 'customers'
validation = CleanedDataFormValidation(form_class=RegistrationForm)
list_allowed_methods = ['get', 'post']
detail_allowed_methods = ['get', 'put', 'patch', 'delete']
authorization = Authorization()
excludes =['is_superuser', 'is_active', 'is_staff', 'password', 'last_login',]
filtering = {
'location': ('exact'),
}
def obj_create(self, bundle, **kwargs):
bundle.data['username'] = bundle.data['email']
return super(CustomerResource, self).obj_create(bundle, **kwargs)
I want to be able to make a POST to the API with some JSON gathered from a form (it can't just be form data because I need to do some processing) to create the user. Here is my Django code that posts up to the API:
payload = {}
payload['email'] = request.POST['username']
payload['username'] = request.POST['username']
payload['password1'] = request.POST['password1']
payload['password2'] = request.POST['password2']
payload = json.dumps(payload)
customer = requests.post(self.base_url + '/v1/customers/', data=payload, headers=headers)
This posts a customer fine -- it exists in the API's database. However, its password for some reason is not registered. The password attribute is blank, whereas if I create a user locally in the API's database, the password appears as an encrypted hash. The has_usable_password field is set to false. The same thing happens if I try payload['password'] = request.POST['password1']
. Any suggestions?
My Customer model:
class Customer(AbstractUser):
current_location = models.ForeignKey('device.Location',
null=True, blank=True, related_name='customers_present')
default_location = models.ForeignKey('device.Location',
null=True, blank=True, related_name='default_customers')
def __unicode__(self):
return u'{0}'.format(self.username)
Your Customer
model has inherited a custom UserManager
manager attribute named objects
. It allows you to easily create Customer
instances and takes care of the password encryption.
You have to override the obj_create
method in your CustomerResource
:
class CustomerResource(ModelResource):
locations = fields.ToManyField('device.resources.LocationResource',
'location_set', null=True)
current_location = fields.ToOneField('device.resources.LocationResource',
'current_location', null=True)
default_location = fields.ToOneField('device.resources.LocationResource',
'default_location', null=True)
class Meta:
queryset = Customer.objects.all()
resource_name = 'customers'
validation = CleanedDataFormValidation(form_class=RegistrationForm)
list_allowed_methods = ['get', 'post']
detail_allowed_methods = ['get', 'put', 'patch', 'delete']
authorization = Authorization()
excludes =['is_superuser', 'is_active', 'is_staff', 'password', 'last_login',]
filtering = {
'location': ('exact'),
}
def obj_create(self, bundle, **kwargs):
bundle.obj = self._meta.object_class.objects.create_user(
username=kwargs['username'],
email=kwargs['email'],
password=kwargs['password1'],
)
return bundle