Reputation: 1766
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
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
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
Reputation: 11932
The correct traverse attribute should be
class BucketListSerializer(serializers.ModelSerializer, EagerLoadingMixin):
...
username = serializers.CharField(source='owner.username', read_only=True)
...
Upvotes: 0