Home > Back-end >  Extended the User model, but not quite sure how to serialize fields for both User and UserExtended
Extended the User model, but not quite sure how to serialize fields for both User and UserExtended

Time:11-12

I extended my User model with a new model just called UserExtended:

# Django imports
from django.db import models
from django.contrib.auth.models import User

class UserExtended(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    crm_guid = models.UUIDField(unique=True)     
    security_q1 = models.CharField(max_length=255, blank=True, null=True)
    security_a1 = models.CharField(max_length=255, blank=True, null=True)
    security_q2 = models.CharField(max_length=255, blank=True, null=True)
    security_a2 = models.CharField(max_length=255, blank=True, null=True)
    attempts = models.SmallIntegerField(blank=False, null=False, default=0)
    key = models.CharField(max_length=255, blank=True, null=True)
    key_expires = models.DateTimeField(blank=True, null=True)
    method = models.CharField(max_length=4, blank=True, null=True)

    class Meta:
        db_table = 'auth_user_extended'

I was hoping by just doing that some Django magic would take care of the rest and I wouldn't have to change my views.py or serializers.py. But when I send a request to the end-point I get:

[api] django.core.exceptions.ImproperlyConfigured: Field name `guid` is not valid for model `User`.

So it does apparently need to be specified. I've been looking at the documentation and similar SO questions to find an answer.

This is what I have for my views.py:

# Django imports
from django.contrib.auth.models import User

# Third party imports
from rest_framework import generics
from rest_framework.permissions import IsAdminUser

# App imports
from users.serializers import UserSerializer


class UsersListCreateView(generics.ListCreateAPIView):
    permission_classes = [IsAdminUser]
    serializer_class = UserSerializer

    def get_queryset(self):
        queryset = User.objects.all()
        email = self.request.query_params.get('email')
        username = self.request.query_params.get('username')
        if email:
            queryset = queryset.filter(email=email)
        if username:
            queryset = queryset.filter(username=username)
        return queryset


class UserRetrieveUpdateDeleteView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAdminUser]
    queryset = User.objects.all()
    serializer_class = UserSerializer

For my serializers.py I just have:

# Django imports
from django.contrib.auth.models import User
from users.models import UserExtended
from django.contrib.auth.hashers import make_password

# Third party imports
from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'last_login', 'first_name',
                  'last_name', 'username', 'email', 'is_active', 'guid']

If I change model = User to model = UserExtemded, then I'll get an error like:

[api] django.core.exceptions.ImproperlyConfigured: Field name `last_login` is not valid for model `UserExtended`.

I'm thinking I need to do one of two things:

  1. Create a serializer class for both models and call them both from the views.py. I've toyed with this a little by trying to pass a list or tuple in of serializer_class (apparently singular for a reason).
  2. Setup the relationship in the serializers.py. I'm looking into this now.

Suggestions for how to resolve this issue?

CodePudding user response:

You need a different serializer and viewset to operate on UserExtended My suggestion would be keep old serializer as is and create UserExtendedSerializer

class UserExtendedSerializer(serializers.ModelSerializer):
    user = UserSerializer(many=False, read_only=True)
    class Meta:
        model = UserExtended
        fields = "__all__"

and viewset would be simply:

class UserExtendedViewSet(ModelViewSet):
    serializer_class = UserExtendedSerializer
    queryset = UserExtended.objects.all()

this should solve your issue

  • Related