Hello I'm trying to learn django and django-restful-framework.
I was wondering can I add more fields to User(contrib.auth) like so
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'firstName', 'lastName', 'ssn', 'email',
'phone', 'jobTitle','image', 'isActive','groups')
This gives me error on firstName. I also tried to tie this with person, but no luck either
class PersonSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
class Meta:
model = Person
fields = ('url', 'firstName', 'lastName', 'ssn', 'owner')
class UserSerializer(serializers.HyperlinkedModelSerializer):
persons = serializers.ManyHyperlinkedRelatedField(view_name='person-detail')
class Meta:
model = User
fields = ('url', 'username', 'persons')
I'm trying to make this so that the user can register with more information.
I suggest you head to the Django docs on extending and/or replacing the existing user model.
Once you've got what you want as the model level see if you can serialize that to your needs. (If not post again.)
The field names are lowercase with underscores. E.g it should be first_name and not firstName.
Related
Her it is my django serializer:
class ShopSerializer(serializers.ModelSerializer):
rest = RestSerializer(many=True)
class Meta:
model = RestaurantLike
fields = ('id', 'created', 'updated', 'rest')
This will wrap whole RestSerializer inside ShopSerializer on response.
How can I get only one or two fields from RestSerializer instead of having all the fields inside ShopSerializer?
Get only two field of RestSerializer instead of whole RestSerializer
If you want to have limited amount of fields from RestSerializer, then you can simply limit it in the fields:
class RestSerializer(serializers.ModelSerializer):
class Meta:
model = Restaurant
fields = ('id', 'name', ...)
If you want just want field, lets say the primary key or Slug, then you can use PrimaryKeyRelatedField or SlugRelatedField for that. For example:
class ShopSerializer(serializers.ModelSerializer):
rest = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='name'
)
class Meta:
model = RestaurantLike
fields = ('id', 'created', 'updated', 'rest')
I have a doubt with the serializers and so far I have not been able to solve it. I explain the doubt with the following example:
I have a User model and this model has the following attributes: username, password, first_name, last_name, age, gender. I also have a serializer, which is called UserSerializer. The UserSerializer should do the following:
When inserting information into the database, UserSerializer should only take into account the fields: username, password, first_name, last_name.
When retrieving information from the database, UserSerializer should only take into account the fields: age, gender.
When updating the database information, UserSerializer should only take into account the fields: password.
My solution:
class UserSerializer:
class UserCreateSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'password', 'first_name', 'last_name']
class UserGetSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['age', 'gender']
class UserUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['password']
Question:
The question: is there any way to synthesize the three serializers into one, or what is the best solution for this problem?
Thank you very much.
Use write_only and read_only parameters in serializer fields to specify fields for creating and retrieving
class UserSerializer(serializers.ModelSerializer):
username = serializers.CharField(write_only=True, required=False)
password = serializers.CharField(write_only=True)
first_name = serializers.CharField(write_only=True, required=False)
last_name = serializers.CharField(write_only=True, required=False)
age = serializers.IntegerField(read_only=True)
gender = serializers.CharField(read_only=True)
class Meta:
model = User
fields = ['username', 'password', 'first_name', 'last_name', 'age', 'gender']
If any field is optional, then you can add the required=False
Model:
class Demo(models.Model):
name = models.CharField(max_length=255)
desc = models.TextField()
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
Serializer:
class DemoSerializer(serializers.ModelSerializer):
class Meta:
model = Demo
fields = '__all__'
I have form in frontend side where I'm adding name, desc and assigning to User so here I'm getting on an issue.
I'm passing data to API {name: "demo", desc: "lorem ipsum", user: 1 }
It's working on save but after saving it's return same response but I want user first_name, last_name, and email in return response.
Because I have a table showing a list of demo table content. but always getting only User ID not a detail of user.
If I'm increasing depth of Serializer It's creating an issue in save time but on get records time I'm getting all details of User model. Like Password also in response so that is a security issue for me show all thing.
You can use depth = 1 to get all the data of foreign key object:
class DemoSerializer(serializers.ModelSerializer):
class Meta:
model = Demo
fields = '__all__'
depth = 1
You could separate the Create and Retrieve serializer. For example, the create serializer will be the one you are currently using:
class DemoCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Demo
fields = '__all__'
On the other hand, Retrieve serializer will serialize the User with a different serializer using Nested Relationship.
class DemoRetrieveSerializer(serializers.ModelSerializer):
user = UserMinimalSerializer # or you could use your UserSerializer, see the last part of the answer
class Meta:
model = Demo
fields = ('id', 'name', 'desc', 'user')
read_only = ('id', 'name', 'desc', 'user',)
In your view, you will create the data with the first serializer and respond with the second. An example using APIView:
class DemoView(APIView):
def post(self, request, format=None):
create_serializer = DemoCreateSerializer(data=request.data)
if create_serializer.is_valid():
instance = create_serializer.save()
retrive_serializer = DemoRetrieveSerializer(instance)
return Response(retrive_serializer.data, status=status.HTTP_201_CREATED)
return Response(create_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
You might have to customize DRF provided views to achieve this, i.e. for Generic views.
Since you don't want to include all the fields of User model, you will have to write a minimal representation of User using another serializer.
class UserMinimalSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'email')
read_only = ('id', 'first_name', 'last_name', 'email',)
Hope it helps.
How do I find an object with relationship and how to save an object in relationship with Django Rest Framework?
I looked in the documentation and found something similar to this
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'profile')
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('nome_empresa', 'cnpj')
profile = ProfileSerializer()
NameError: name 'ProfileSerializer' is not defined
Python is not a compiled language. Everything is created/done at runtime.
At the following line:
profile = ProfileSerializer()
you are using the ProfileSerializer but at this point it is not created yet. It is created a little later. To fix this, you need to put it before the UserSerializer class:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('nome_empresa', 'cnpj')
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'profile')
Hope it helps!
I have two models, the default User model and a UserProfile model that extends the user model:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='UserProfile')
universidad = models.ForeignKey(Universidad, related_name ='universidad')
group_admin = models.ManyToManyField(Group, related_name = 'group_admin')
I'm trying to obtain a user field that allows to GET, PUT and POST data with this format:
'username' = 'foo'
'password' = 'password'
'email' = 'a#b.com'
'universidad' = 'Harvard'
'group_admin' = [1] #list of groups id
I have used nested serializers but it's read only.
I also proved this solution, but i obtain a KeyError: 'universidad'.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'password', 'email','universidad', 'group_admin')
write_only_fields = ('password',)
Any help would be appreciated.
The KeyError occurs because you are trying to use the reverse relationship of UserProfile in the serializer. Reverse relationships aren't automatically included in HyperLinkedModelSerializers. See the docs for more information and try:
fields = ('url', 'username', 'password', 'email','UserProfile__universidad', 'group_admin')