restful - ¿Cómo crear o registrar un usuario utilizando la API django-tastypie mediante programación?
proper way to consume data from restful api in django (3)
Mi código a continuación funciona, crea el objeto Usuario y lo guarda pero no guarda la contraseña:
class CreateUserResource(ModelResource):
class Meta:
allowed_methods = [''post'']
object_class = User
authentication = Authentication()
authorization = Authorization()
include_resource_uri = False
fields = [''username'']
def obj_create(self, bundle, request=None, **kwargs):
try:
bundle = super(CreateUserResource, self).obj_create(bundle, request, **kwargs)
except IntegrityError:
raise BadRequest(''That username already exists'')
return bundle
Si agrego ''contraseña'' a los campos Meta, entonces guarda la contraseña sin procesar pero no la hash. ¿Qué estoy haciendo mal?
Así que esto es lo que funcionó para mí:
def obj_create(self, bundle, request=None, **kwargs):
username, password = bundle.data[''username''], bundle.data[''password'']
try:
bundle.obj = User.objects.create_user(username, '''', password)
except IntegrityError:
raise BadRequest(''That username already exists'')
return bundle
Al crear un usuario, necesita utilizar el método set_password user.set_password(bundle.data.get(''password''))
o usar un método create_user del objeto User.
user = User.objects.create_user(bundle.data.get(''username''), bundle.data.get(''email''), bundle.data.get(''password''))
Así que algo como esto funcionaría para ti:
def obj_create(self, bundle, request=None, **kwargs):
try:
bundle = super(CreateUserResource, self).obj_create(bundle, request, **kwargs)
bundle.obj.set_password(bundle.data.get(''password''))
bundle.obj.save()
except IntegrityError:
raise BadRequest(''That username already exists'')
return bundle
Estaba en la misma situación y encontré ambas soluciones útiles, pero no completas. En ambos, pude crear usuarios con un nombre de usuario vacío. No quería tener tales fugas, así que aquí está lo que hice.
Primero, creé un formulario de validación:
from django import forms
from django.forms import ModelForm
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
self.fields[''username''].error_messages = {''required'': "Please enter username"}
self.fields[''username''].max_length = 30
self.fields[''password''].error_messages = {''required'': ''Please enter password''}
self.fields[''password''].max_length = 30
self.fields[''email''].required = False
def clean_username(self):
username = self.cleaned_data[''username'']
if len(username) < 4:
raise forms.ValidationError("Username has to be longer than 4 characters")
return username
def clean_password(self):
password = self.cleaned_data[''password'']
if len(password) < 5:
raise forms.ValidationError("Password has to be longer than 5 characters")
return password
class Meta:
model = User
fields = (''username'', ''email'', ''password'')
Luego, dentro del UserResource
validation = FormValidation(form_class=UserForm)
def obj_create(self, bundle, request=None, **kwargs):
bundle = super(UserResource, self).obj_create(bundle, request, **kwargs)
bundle.obj.set_password(bundle.data.get(''password''))
bundle.obj.save()
return bundle
Espero que mi solución pueda ayudar a otros desarrolladores. ¡Feliz codificación!
Estaba intentando usar un código similar con django-tastypie == 0.9.12 y me metí en errores relacionados con el queryset faltante y la cantidad de argumentos para obj_create. Usando el siguiente código funcionó para mí:
from django.contrib.auth.models import User
from django.db import IntegrityError
from tastypie.resources import ModelResource
from tastypie.authorization import Authorization
from tastypie.authentication import Authentication
from tastypie import fields
from tastypie.exceptions import BadRequest
class UserSignUpResource(ModelResource):
class Meta:
object_class = User
resource_name = ''register''
fields = [''username'', ''first_name'', ''last_name'', ''email'']
allowed_methods = [''post'']
include_resource_uri = False
authentication = Authentication()
authorization = Authorization()
queryset = User.objects.all()
def obj_create(self, bundle, request=None, **kwargs):
try:
bundle = super(UserSignUpResource, self).obj_create(bundle)
bundle.obj.set_password(bundle.data.get(''password''))
bundle.obj.save()
except IntegrityError:
raise BadRequest(''Username already exists'')
return bundle
Algún código de prueba sería:
from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
from tastypie.test import ResourceTestCase
class UserSignUpResourceTest(ResourceTestCase):
def test_post_list(self):
post_arguments = {
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"username": "test-user",
"password": "idiotic-pwd"
}
# Check how many are there
self.assertEqual(User.objects.count(), 0)
self.assertHttpCreated(self.api_client.post(''/api/register/'',
format=''json'', data=post_arguments))
# Check how many are there. Should be one more
self.assertEqual(User.objects.count(), 1)
# Check attributes got saved correctly
user = User.objects.get(username=''test-user'')
for atr in post_arguments:
if atr == ''password'':
check_password(post_arguments[atr], getattr(user, atr))
else:
self.assertEqual(post_arguments[atr], getattr(user, atr))