yung peso
yung peso

Reputation: 1766

Serializer not working correctly when trying to incorporate username of user

I have a serializer, I'm trying to add an additional field, from a different model. The goal is to add the username from the user who requested the data.

Here is my serializer, I try to accomplish my goal using the username variable and adding it to fields.

class BucketListSerializer(serializers.ModelSerializer, EagerLoadingMixin):

    stock_count = serializers.SerializerMethodField()
   
    username = serializers.CharField(source='User.username', read_only=True)

        model = Bucket
        fields = ('id','username','category','name','stock_count',
                'stock_list','owner','admin_user',
                'guest_user','about','created','slug',
                'bucket_return', 'bucket_sectors','bucket_pos_neg')

    def get_stock_count(self, obj):
        if obj.stock_count:
            return obj.stock_count
        return 0

There aren't any syntax errors with this serializer, however the username field is not working. There is no data in the dictionary returned with the key username

User model:

class CustomAccountManager(BaseUserManager):

    def create_superuser(self, email, username, first_name, last_name, password, **other_fields):

        other_fields.setdefault('is_staff', True)
        other_fields.setdefault('is_superuser', True)
        other_fields.setdefault('is_active', True)

        if other_fields.get('is_staff') is not True:
            raise ValueError(
                'Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')

        return self.create_user(email, username, first_name, last_name, password, **other_fields)

    def create_user(self, email, username, first_name, last_name, password, **other_fields):

        if not email:
            raise ValueError(_('You must provide an email address'))

        if not username:
            raise ValueError(_('You must provide a username'))

        if not first_name:
            raise ValueError(_('You must provide your first name'))

        if not last_name:
            raise ValueError(_('You must provide your last name'))
        
        if not password:
            raise ValueError(_('You must provide a valid password'))

        email = self.normalize_email(email)
        user = self.model(email=email, username=username,
                          first_name=first_name, last_name=last_name, password=password, **other_fields)
        user.set_password(password)
        user.save()
        return user


class User(AbstractBaseUser, PermissionsMixin):

    email = CIEmailField(_('email address'), unique=True)
    username = CICharField(max_length=150, unique=True)
    first_name = models.CharField(max_length=150, blank=True)
    last_name = models.CharField(max_length=150, blank=True)
    start_date = models.DateTimeField(default=timezone.now)
    subscribed = models.BooleanField(default=False)
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    objects = CustomAccountManager()


    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'first_name', 'last_name','password']

    def __str__(self):
        return self.username

Here is the view used:

class BucketList(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = BucketListSerializer
    filter_backends = [OwnerOrUserFilterBackend]
    queryset = Bucket.objects.all()

how can I simply add the username of a user to my serializer class above?


EDIT:

Here is my bucket model:


class Bucket(models.Model):

    category_options = (
        ('personal', 'Personal'),
        ('social', 'Social'),
    )


    class BucketObjects(models.Manager):
        def get_queryset(self):
            return super().get_queryset()

    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='buckets')
    admin_user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='admin_user')
    guest_user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='guest_user', blank=True)
    category = models.CharField(max_length=30, choices=category_options)
    name = models.CharField(max_length=35)
    created = models.DateTimeField(default=timezone.now, blank=True)
    slug = AutoSlugField(populate_from = "random_string", blank=True) 
    stock_count = models.IntegerField(blank=True, null=True)
    stock_list = ArrayField(models.CharField(max_length=6,null=True),size=30,null=True, blank=True)
    about = models.CharField(max_length=200)

    objects = models.Manager()
    bucketobjects = BucketObjects()

EDIT #2

class BucketListSerializer(serializers.ModelSerializer):
   
    user = serializers.SerializerMethodField('get_user')

    class Meta:
        model = Bucket
        fields = (...'user')


    def getUsername(self, obj):
        user = self.context['request'].user
        return obj.user

Upvotes: 0

Views: 407

Answers (3)

paras chauhan
paras chauhan

Reputation: 787

username = serializers.SerializerMethodField('_user')

def _user(self, obj):
    request = self.context.get('request', None)
    if request and request.user:
        return request.user.username
    return ''

This will work for you.

Upvotes: 1

Neeraj
Neeraj

Reputation: 997

I think you can use context in your serializer:

user = self.context['request'].user

So if you want to display the username you can create username as SerailizerMethodField and return the username from the user object which you get from request context.

class BucketListSerializer(serializers.ModelSerializer):

user = serializers.SerializerMethodField(read_only=True)

class Meta:
    model = Bucket
    fields = (...'user')


def get_user(self, instance):
    user = self.context['request'].user
    return user

Upvotes: 0

panchicore
panchicore

Reputation: 11932

The correct traverse attribute should be

class BucketListSerializer(serializers.ModelSerializer, EagerLoadingMixin):
    ...
    username = serializers.CharField(source='owner.username', read_only=True)
    ...

Upvotes: 0

Related Questions