Reputation: 2061
I'm trying to use DRF to allow users to create a new user account via my API. I have a few requirements that might be different than the norm
So far I came up with this, but I am getting an error message saying "Column 'user_id' cannot be null"
View
@api_view(['POST'])
@permission_classes((AllowAny,))
def register_user(request):
serialized = UserSerializer(data=request.DATA)
if serialized.is_valid():
user = User.objects.create_user(
email = serialized.init_data['email'],
username = serialized.init_data['username'],
password = serialized.init_data['password'],
first_name = serialized.init_data['first_name'],
last_name = serialized.init_data['last_name']
)
phone_number = request.DATA["phone_number"]
#save phone_number to profile model here
return Response(serialized.data['token'], status=status.HTTP_201_CREATED)
else:
return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)
Serializer
class UserSerializer(serializers.ModelSerializer):
token = serializers.SerializerMethodField('get_token')
class Meta:
model = User
fields = ('password', 'username', 'first_name', 'last_name', 'email', 'token', 'phone_number')
def get_token(self, obj):
token = Token.objects.create(user=obj)
return token.key
My questions are
Stacktrace
Django Version: 1.6.8
Python Version: 2.7.5
Installed Applications:
('django.contrib.sites',
'django.contrib.admin',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'my_app',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
'debug_toolbar',
'rest_framework',
'rest_framework.authtoken',
'django_extensions')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware')
Traceback:
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
112. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
57. return view_func(*args, **kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/views/generic/base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
403. response = self.handle_exception(exc)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
400. response = handler(request, *args, **kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/decorators.py" in handler
50. return func(*args, **kwargs)
File "/home/vagrant/projects/my_project/my/my_app/api/views.py" in register_user
60. return Response(serialized.data['token'], status=status.HTTP_201_CREATED)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/serializers.py" in data
572. self._data = self.to_native(obj)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/serializers.py" in to_native
351. value = field.field_to_native(obj, field_name)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/fields.py" in field_to_native
1041. value = getattr(self.parent, self.method_name)(obj)
File "/home/vagrant/projects/my_project/my/my_app/api/serializers.py" in get_token
19. token = Token.objects.create(user=obj)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/manager.py" in create
157. return self.get_queryset().create(**kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/query.py" in create
322. obj.save(force_insert=True, using=self.db)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/rest_framework/authtoken/models.py" in save
33. return super(Token, self).save(*args, **kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/base.py" in save
545. force_update=force_update, update_fields=update_fields)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/base.py" in save_base
573. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/base.py" in _save_table
654. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/base.py" in _do_insert
687. using=using, raw=raw)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/manager.py" in _insert
232. return insert_query(self.model, objs, fields, **kwargs)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/query.py" in insert_query
1514. return query.get_compiler(using=using).execute_sql(return_id)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
903. cursor.execute(sql, params)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/debug_toolbar/panels/sql/tracking.py" in execute
174. return self._record(self.cursor.execute, sql, params)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/debug_toolbar/panels/sql/tracking.py" in _record
104. return method(sql, params)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/backends/util.py" in execute
69. return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/backends/util.py" in execute
53. return self.cursor.execute(sql, params)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/backends/mysql/base.py" in execute
129. six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
File "/home/vagrant/envs/my/lib/python2.7/site-packages/django/db/backends/mysql/base.py" in execute
124. return self.cursor.execute(query, args)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/MySQLdb/cursors.py" in execute
205. self.errorhandler(self, exc, value)
File "/home/vagrant/envs/my/lib/python2.7/site-packages/MySQLdb/connections.py" in defaulterrorhandler
36. raise errorclass, errorvalue
Exception Type: IntegrityError at /api/user/register/
Exception Value: (1048, "Column 'user_id' cannot be null")
Upvotes: 3
Views: 2772
Reputation: 41699
I would recommend using class-based views with Django REST Framework. They give you a lot of extra power that is missing from function-based views, and they are more supported. While this is less important for this case, this is also a very basic situation that avoids most of what Django REST Framework brings to the table.
Do i need separate validation on the phone number, first_name, last_name, email to make sure they are required or is that handled by the model?
When you call serializer.is_valid
, it should check to make sure that any fields that are specified as required on the model are included. Try it out, and if it isn't happening make sure that you don't have empty=False
specified on any of the fields. If you aren't in the position to fix that, you can override the field on the serializer and set required=True
there.
Is this the correct way to handle the POST of the phone number?
The serializer can create the user automatically by just calling serializer.save()
. If you have custom logic in the create_user
manager that you need to use, then you probably can't use save
.
Is this secure ? If not, what can I do to make it more secure?
Django will help you out a lot here, so your code currently looks pretty well. One thing you may want to consider is that the init_data
from the serializer is the same as that from request.DATA
. You should probably access the validated data from serializer.object
(like serializer.object.username
instead, as any validators may have modified your data to make it more friendly to the Django ORM.
Upvotes: 2