1

I am writing API for token-based authentication in django usign django rest framework. I have implemented it using default User model. But I need to add some more details in the User model. After searching, I found AbstractBaseUser, BaseUserMAnager. I have implemented it too and written Serializer for it but getting errors. There are too many different methods available online, now I am confused which one is the right way.

models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class MyUserManager(BaseUserManager):
    def create_user(self, email, password):
        if not email:
            raise ValueError('Enter email')

        user = self.model(
            email=email.normalize_email(email)
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        user = self.create_user(email, password=password)
        user.save(using=self._db)
        return user


class MyUser(AbstractBaseUser):

    email = models.EmailField(verbose_name='email address', max_length=255, unique=True, db_index=True)
    created = models.DateTimeField(auto_now_add=True)
    is_active = models.BooleanField(default=True)

    USERNAME_FIELD = 'email'

    objects = MyUserManager()

    def get_short_name(self):
        return self.email

    def get_full_name(self):
        return self.email

    def __unicode__(self):
        return self.email

serializers.py

from rest_framework import serializers
from bsa.models import MyUser
from django.contrib.auth import get_user_model


class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(style={'input_type': 'password'})

class Meta:
    model = get_user_model()
    fields = ['email', 'password']

    def create(self, email, password):
        user = MyUser(email, password)
        user.set_password(password)
        user.save()
        return user

views.py

from bsa.serializers import UserSerializer
from rest_framework.decorators import APIView
from rest_framework.response import Response

class Test(APIView):

    def post(self, request):
        serializer = UserSerializer( data=request.data)
        if serializer.is_valid():
            #getting error here
            serializer.save()
            return Response({'detail': "POST Response"})
        return Response({'detail': "Response"})

settings.py

"""
Django settings for BSA2 project.

Generated by 'django-admin startproject' using Django 1.9.6.

For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '1$x0gj(bx+ispf=f_a6-!syksl6qkier=6!@qh=m!w575!c!n+'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

AUTH_USER_MODEL = 'bsa.MyUser'

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bsa',
    'rest_framework',
]

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'BSA2.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'BSA2.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

errors

Traceback (most recent call last):
  File "/root/envTut/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/root/envTut/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "/root/envTut/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "/root/PycharmProjects/BSA2/bsa/views.py", line 20, in post
    serializer.save()
  File "/root/envTut/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 191, in save
    self.instance = self.create(validated_data)
TypeError: create() takes exactly 3 arguments (2 given)

if I remove self from create method in 'serializers.py' error changes to

Traceback (most recent call last):
  File "/root/envTut/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/root/envTut/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
    response = self.handle_exception(exc)
  File "/root/envTut/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
    response = handler(request, *args, **kwargs)
  File "/root/PycharmProjects/BSA2/bsa/views.py", line 20, in post
    serializer.save()
  File "/root/envTut/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 191, in save
    self.instance = self.create(validated_data)
  File "/root/PycharmProjects/BSA2/bsa/serializers.py", line 16, in create
    user.save()
  File "/root/envTut/local/lib/python2.7/site-packages/django/contrib/auth/base_user.py", line 74, in save
    super(AbstractBaseUser, self).save(*args, **kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/base.py", line 708, in save
    force_update=force_update, update_fields=update_fields)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/base.py", line 736, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/base.py", line 801, in _save_table
    forced_update)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/base.py", line 831, in _do_update
    filtered = base_qs.filter(pk=pk_val)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/query.py", line 790, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/query.py", line 808, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1243, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1269, in _add_q
    allow_joins=allow_joins, split_subq=split_subq,
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1203, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1099, in build_lookup
    return final_lookup(lhs, rhs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/lookups.py", line 19, in __init__
    self.rhs = self.get_prep_lookup()
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/lookups.py", line 57, in get_prep_lookup
    return self.lhs.output_field.get_prep_lookup(self.lookup_name, self.rhs)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 744, in get_prep_lookup
    return self.get_prep_value(value)
  File "/root/envTut/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 976, in get_prep_value
    return int(value)
TypeError: int() argument must be a string or a number, not 'UserSerializer'

I have written most of the code using django and drf documentation (some blogs too). Error is in serializer.save()

1 Answer 1

1

The first error that I see is that def create(self, email, password) should be receiving the arguments self and validated_data. For example:

def create(self, validated_data):
    """Create a new model instance"""
    return MyUser.objects.create(**validated_data)

Ideally, your serializer would contain all the fields need to create this user instance.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.