Django REST: Custom field, list may not be empty - python

I'm trying to add the employees field to my custom user model in Django REST 2.2. This is how I implemented my custom user (first answer). The employees field is just a list of custom users (so it's related to itself, with a many-to-many relationship).
When I try to add a custom user model from the django interface, it says "this list may not be empty". How can I make it so it can be empty? I thought that's what I added "required=False" for.
users/models.py
class CustomUser(AbstractUser):
employees = models.ManyToManyField("self", related_name='employees')
users/serializers.py (CustomRegisterSerializer is used for registering with rest-auth, CustomUserSerializer is used to view and edit)
class CustomRegisterSerializer(RegisterSerializer):
employees = serializers.RelatedField(many=True, required=False, queryset=CustomUser.objects.all())
def get_cleaned_data(self):
data_dict = super().get_cleaned_data()
data_dict['employees'] = self.validated_data.get('employees', '')
return data_dict
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ('id', 'email', 'employees')
users/views.py
class CustomUserViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer

Related

How to serialize object field in django rest framework

I have Profile model, which is auth model. And I have Blog model. I want to serialize model as it will give me {author: {user_name:.., photo: photo_path}, blog_title:some_title, ..}. Shortly, I want use author field as inner serialiser. I have already ProfileSerialiser and BlogSerializer. Here's my BlogList serializer:
class BlogListSerializer(serializers.ModelSerializer):
author = MiniProfileSerializer()
class Meta:
model = Blog
fields = ['title', 'content', 'like_count', 'author']
read_only_fields = ['views', 'author', 'like_count']
And MiniProfileSerializer:
class MiniProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['user_name', 'image']
and view:
class BlogListAPIView(generics.ListCreateAPIView):
serializer_class = BlogListSerializer
queryset = Blog.published.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
Django REST Framework does not support writing to a nested serializer out of the box. You can check out DRF Writeable Nested, or write your own custom behavior on create by overwriting create() in the BlogListSerializer.
EDIT: Here's some more docs on the topic: https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers

How to filter a child object's parent field for Django

I want to have a form with fields that are filtered based on Django group model name field.
For example, I have a model that is connected to Django User model which is connected to Django group model like so:
class customUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.first_name
I have added a row of data in Django group using Django admin panel called 'Teacher'.
What I'm trying to do is to have my form list only customUser that is listed as "Teacher" in Django group model.
My form:
class myForm(ModelForm):
class Meta:
model = customUser
fields = ['user ']
def __init__(self,*args,**kwargs):
super (myForm,self ).__init__(*args,**kwargs)
**# What I want to achieve but doesnt work.**
self.fields['user'].queryset = customUser.objects.filter(user.group.name = "Teacher")
Any help is greatly appreciated.
Try:
customUser.objects.filter(user__groups__name='Teacher')
Check documentation about Lookup reference

De-serializing many to many field with a through table in DRF

I am working on developing a Trello-like website with Django Rest Framework.
I want to add selected users to BoardAccess model, a through table for User model and Board model, two of which are in Many to Many relationship. Being added to BoardAccess table will mean that the respective users will be having access to matching boards.
Models.py
class Board(models.Model):
name = models.CharField(max_length=50)
access_granted = models.ManyToManyField(User, through='BoardAccess', related_name='access_boards')
team = models.ForeignKey(Team, on_delete=models.CASCADE) # a team can have many boards
class BoardAccess(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
board = models.ForeignKey('Board', on_delete=models.CASCADE)
For User, I am currently using Django's default Auth User model and extending it with a Profile model via OneToOne Field.
Serializers.py
class BoardAccessSerializer(serializers.ModelSerializer):
members = serializers.SerializerMethodField()
added_users = # ???
new_name = serializers.CharField(
write_only=True, required=False, source='name') # in case of requests for renaming the board
def get_members(self, instance):
members = User.objects.filter(profile__team=instance.team)
return UserBoardSerializer(members, many=True).data
I would like to know what field / relations / another serializer should be assigned to added_users, which I think should be write_only=True, in order to successfully de-serialize input from the client-side containing primary keys of selected users.
get_members() method is used to first display information of all team members, from which a client will select users to be added to the board.
Views.py
class BoardAccessRetrieveUpdateAPIView(generics.RetrieveUpdateAPIView):
serializer_class = BoardAccessSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
team_id = self.kwargs.get('team_id')
team = get_object_or_404(Team, id=team_id)
queryset = Board.objects.select_related(
'team').prefetch_related(
'access_granted').filter(team=team)
return queryset
I am new to DRF, so there may be a lot of points to be improved from the above. I would really appreciate every help!!
You can override the update method in your serializer, and get the user ids from the client side from initial_data
def update(self, instance, validated_data):
// do the actions on create
users = self.initial_data.get('users')
instance.access_granted.add(*users)
instance.save()
return instance
Also when using ModelSerializer have to add Meta class:
class BoardAccessSerializer(serializers.ModelSerializer):
class Meta:
model = Board
fields = "__all__"

How to serialize the return value of a method in a model?

I have a Django app that uses Django REST Framework and Django-allauth. Now, I'm trying to retrieve the avatar URL that's present in the social account. However, I'm having trouble forming the serializer.
For background info, the allauth's SocialAccount is related to the user model via a foreign key:
class SocialAccount(models.Model):
user = models.ForeignKey(allauth.app_settings.USER_MODEL)
# the method I'm interested of
def get_avatar_url(self):
...
Now, here's the serializer I currently have:
class ProfileInfoSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'first_name', 'last_name')
In the end, I'd like to have an extra field avatar_url which takes the result of the method call in the SocialAccount model. How do I do that?
I found a solution using a SerializerMethodField:
class ProfileInfoSerializer(serializers.ModelSerializer):
avatar_url = serializers.SerializerMethodField()
def get_avatar_url(obj, self):
return obj.socialaccount_set.first().get_avatar_id()
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'avatar_url')

ForiegnKey field serializer in Django Rest framework

Before posting this question I've read few questions on SOF. but they are from 2012 and very confusing as well.
for e.g Django Rest Framework - Get related model field in serializer
my question is very straight forward
models.py
class User(models.Model):
username = models.CharField(max_length=100,unique=True)
password = models.CharField(max_length=100,null=False,blank=False)
class Car(models.Model):
user = models.ForeignKey(User)
car_name = models.CharField(max_length=100,null=True,blank=True)
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username','password' )
class CarSerializer(serializers.ModelSerializer):
#user = ?? what should I write or is there any better approach for serializing Car objects
class Meta:
model = Car
fields = ('user','car_name')
views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class CarViewSet(viewsets.ModelViewSet):
queryset = Car.objects.all()
serializer_class = CarSerializer
Please suggest all possible approaches.
1 more query. which one is better ModelSerializer or HyperlinkModelSerializer. as I saw different different answers containing these two.
You just need to do:
class CarSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Car
fields = ('user','car_name')
that is all.
Also, you should take a look to the kindnesses of serializers.Field and serializers.SerializerMethodField, you can play with them and customize your response data as much as you wish.
As to the question around HyperlinkedModelSerializer-ModelSerializer, very clear here:
The HyperlinkedModelSerializer has the following differences from ModelSerializer:
It does not include the pk field by default.
It includes a url field, using HyperlinkedIdentityField.
Relationships use HyperlinkedRelatedField, instead of PrimaryKeyRelatedField.
Hope that helps.

Categories