title: User creation with unique constraint in Django Rest framework
body: <p>I researched about it in Google, and have tried in lot of ways but still not able to get it right. Here are the requirements:</p>
  
  <ol>
  <li>A one to one field for extending User model, so this has been achieved and the new model is called Customer.</li>
  <li>Now, with new user 201 response is returned BUT not all the data is serialized, only date_of_birth is coming in json format, I want even the User to be in that json response.</li>
  <li>If I try to add a user with a username which already exists it plays up really bad. I am trying with Try and Except but it really doesnt work. I want a response of 409 conflict to be sent if the username already exists.
  Here is UserSerializer.py:</li>
  </ol>
  
  <p>-</p>
  
  <pre><code>from django.contrib.auth.models import User
  from rest_framework import serializers
  
  
  class UserSerializer(serializers.HyperlinkedModelSerializer):
      new_username = serializers.SerializerMethodField()
  
      class Meta:
          model = User
          fields = ('url', 'pk', 'username', 'email', 'is_staff', 'new_username')
          extra_kwargs = {
              'username': {'validators': []},
          }
  
      def get_new_username(self, obj):
          return obj.username
  </code></pre>
  
  <p>Here is Customer model:</p>
  
  <pre><code>from django.db import models
  from django.contrib.auth.models import User
  
  
  class Customer(models.Model):
      user = models.OneToOneField(User, related_name="customer", on_delete=models.CASCADE)
      date_of_birth = models.DateField(max_length=8)
  
      def __unicode__(self):
          return u'%s' % self.user.username
  </code></pre>
  
  <p>Here is CustomerSerializer class:</p>
  
  <pre><code>from django.contrib.auth.models import User
  from django.contrib.auth import get_user_model
  
  from rest_framework import serializers, status
  from rest_framework.response import Response
  
  from customers.models import Customer
  from api.serializers import UserSerializer
  
  
  class CustomerSerializer(serializers.HyperlinkedModelSerializer):
      user = UserSerializer()
      class Meta:
          model = Customer
          fields = ('url', 'date_of_birth', 'user')
  
      def create(self, validated_data):
          print "coming inside serializer create"
          user_data = validated_data.pop("user")
          print user_data
          try:
              userinstance = User.objects.get_or_create(**user_data)[0]
              print "user..."
              print userinstance
              print validated_data
              customer = Customer.objects.create(user=userinstance, **validated_data)
              print customer.user
              return customer
          except Exception as exception:
              print exception
              # print "customer --&gt; %s " % customer
              return customer
  
      def update(self, instance, validated_data):
          print "coming inside update"
          user_data = validated_data.pop("user")
          username = user_data.pop('username')
          user = get_user_model().objects.get_or_create(username=username)[0]
          user.username = username
          user.email = user_data.get('email', user.email)
          user.save()
  
          # instance.user = user
          instance.date_of_birth = validated_data.get('date_of_birth', instance.date_of_birth)
          instance.save()
  </code></pre>
  
  <p>And here is view set for Customer:</p>
  
  <pre><code>from rest_framework import viewsets
  
  from customers.models import Customer
  from customers.serializers import CustomerSerializer
  from api.permissions import IsOwnerOrAdmin
  
  from rest_framework import authentication, permissions, status
  from rest_framework.response import Response
  
  
  class CustomerViewSet(viewsets.ModelViewSet):
      serializer_class = CustomerSerializer
      queryset = Customer.objects.all()
      authentication_classes = (authentication.TokenAuthentication,
                                authentication.SessionAuthentication,
                                authentication.SessionAuthentication, )
  
      def get_permissions(self):
          if self.action == 'list':
              self.permission_classes = (permissions.IsAdminUser,)
          elif self.action == 'create':
              self.permission_classes = (permissions.AllowAny,)
  
          return super(self.__class__, self).get_permissions()
  
      def create(self, request, *args, **kwargs):
          print "This is view create -----------------------------"
          serializer = self.get_serializer(data=request.data)
          # print serializer
  
          if serializer.is_valid():  # It passes because here there are no new objects created yet
              print "serializer is valid ......"
              # self.pre_save(serializer.object)
              # user_data = serializer.validated_data.get("user")
              # print user_data
              self.object = serializer.create(serializer.validated_data)  # It creates the User (triggering the signal) instance and then when saving UserProfile, it give the integrity error
              # self.post_save(self.object, created=True)
              # headers = self.get_success_headers(serializer.data)
              print 'coming here ....1'
              print self.object
              return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
          print 'coming here..'
          return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  </code></pre>
  
  <p>So, basically I would like to create new customers with all data returned as response and status 201 and if username already exists, then 409 or status code which I define and the some data which DRF should not complaint about i.e; right now it says that OrderDict does not contain PK if I modify the serializer.</p>
  
  <p>Thanks</p>
  
  <hr>
  
  <p><strong>Edit 1</strong></p>
  
  <hr>
  
  <p>Here is updated serilizer with custom exception:</p>
  
  <pre><code>from django.contrib.auth.models import User
  from django.contrib.auth import get_user_model
  from django.db import IntegrityError
  
  from rest_framework import serializers, status
  from rest_framework.response import Response
  from rest_framework.exceptions import APIException
  
  from customers.models import Customer
  from api.serializers import UserSerializer
  
  
  class CustomerSerializer(serializers.HyperlinkedModelSerializer):
      user = UserSerializer()
      class Meta:
          model = Customer
          fields = ('url', 'pk', 'date_of_birth', 'user')
  
      def create(self, validated_data):
          print "coming inside serializer create"
          user_data = validated_data.pop("user")
          print user_data
          try:
              userinstance = User.objects.create_user(**user_data)
              print "user..."
              print userinstance
              print validated_data
              customer = Customer.objects.create(user=userinstance, **validated_data)
              print customer.user
              return customer
          # except TypeError as exception:
          #     print exception
          #     # print "customer --&gt; %s " % customer
          #     raise TypeError(exception)
          except IntegrityError as exception:
              raise Custom409(exception)
  
  
  
      def update(self, instance, validated_data):
          print "coming inside update"
          user_data = validated_data.pop("user")
          username = user_data.pop('username')
          user = get_user_model().objects.get_or_create(username=username)[0]
          user.username = username
          user.email = user_data.get('email', user.email)
          user.save()
  
          # instance.user = user
          instance.date_of_birth = validated_data.get('date_of_birth', instance.date_of_birth)
          instance.save()
  
          return instance
  
  class Custom409(APIException):
      status_code = status.HTTP_409_CONFLICT
      default_detail = "User already there."
  </code></pre>
  
  <p>But still get :</p>
  
  <pre><code>    Traceback (most recent call last):
    File "/home/naveen/projects/gratis/customers/tests.py", line 37, in test_if_anyone_could_create_customers
      format='json')
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/test.py", line 299, in post
      path, data=data, format=format, content_type=content_type, **extra)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/test.py", line 221, in post
      return self.generic('POST', path, data, content_type, **extra)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/django/test/client.py", line 379, in generic
      return self.request(**r)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/test.py", line 288, in request
      return super(APIClient, self).request(**kwargs)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/test.py", line 240, in request
      request = super(APIRequestFactory, self).request(**kwargs)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/django/test/client.py", line 466, in request
      six.reraise(*exc_info)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
      response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
      return view_func(*args, **kwargs)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/viewsets.py", line 83, in view
      return self.dispatch(request, *args, **kwargs)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/views.py", line 477, in dispatch
      response = self.handle_exception(exc)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/views.py", line 437, in handle_exception
      self.raise_uncaught_exception(exc)
    File "/home/naveen/.virtualenvs/gratis/local/lib/python2.7/site-packages/rest_framework/views.py", line 448, in raise_uncaught_exception
      raise exc
  IntegrityError: duplicate key value violates unique constraint "auth_user_username_key"
  DETAIL:  Key (username)=(user2) already exists.
  </code></pre>
  
  <p>And also the test case is as follows:</p>
  
  <pre><code>def test_if_anyone_could_create_customers(self):
          create_user = self.client.post('/api/customers/',
                                         {'user':{'username': 'user2', 'email': 'user2@gmail.com'}, 'date_of_birth':"1982-10-20"},
                                         format='json')
          print create_user
          self.assertEqual(create_user.status_code, 201)
  
          create_user = self.client.post('/api/customers/',
                                         {'user': {'username': 'user2', 'email': 'user2@gmail.com'},'date_of_birth': "1982-10-20"},
                                         format='json')
          print create_user
          # no duplicates
          user = User.objects.all()
          print user
          self.assertEqual(create_user.status_code, 409)
  </code></pre>