I developed api with django. I created a code structure like below.
How do I get the user's first_name and last_name in class ProfileSerializer?
that is, with ProfileSerializer, I want to get information such as the user's name, surname, id number
``
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework import serializers
from account.models import Profile
class ProfileSerializer(ModelSerializer):
class Meta:
model = Profile
fields = ('id', 'userKey', 'phone', 'email', 'address', 'userState')
class UserSerializer(ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'profile')
def update(self, instance, validated_data):
profile = validated_data.pop('profile')
profile_serializer = ProfileSerializer(instance=instance.profile, data=profile)
profile_serializer.is_valid(raise_exception=True)
profile_serializer.save()
return super(UserSerializer, self).update(instance, validated_data)
``
Simply define serializers.CharField() as,
class ProfileSerializer(ModelSerializer):
first_name = serializers.CharField(source='user.first_name', read_only=True)
last_name = serializers.CharField(source='user.last_name' read_only=True)
class Meta:
model = Profile
fields = ('id', 'userKey', 'phone', 'email',
'address', 'userState', 'first_name', 'last_name')
Just change your serializer like this
class ProfileSerializer(ModelSerializer):
class Meta:
model = Profile
fields = ('id', 'userKey', 'phone', 'email', 'address', 'userState')
def to_representation(self, instance):
data = super().to_representation(instance)
data.update({'username': instance.userKey.username, 'first_name': instance.userKey.first_name, 'last_name': instance.userKey.last_name})
return data
Related
I have these 2 models:
# core/models.py
Class Certificate:
user = models.Foreignkey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL,
related_name='certificates')
name = models.Charfield()
.
.
# users/models.py
Class User(AbstractBaseUser):
.
.
and I want to send the certificates of a user along with its other pieces of information.
this is my serializer:
# users/serializers.py
class CertificationSerializer(serializers.ModelSerializer):
"""Serializer for the certificate object"""
class Meta:
model = Certificate
class UserSerializer(serializers.ModelSerializer):
"""Serializer for the user object"""
# TODO
# videos = serializers.PrimaryKeyRelatedField(
# many=True,
# queryset=Tag.objects.all()
# )
certificates = CertificationSerializer(many=True)
class Meta:
model = get_user_model()
# TODO add certificates and videos
fields = ('id', 'email', 'password', 'first_name', 'last_name',
'phone_number', 'credit', 'points', 'certificates')
extra_kwargs = {'password': {'write_only': True,
'label': 'گذرواژه', 'min_length': 5}}
read_only_fields = ('id', 'certificates',)
def create(self, validated_data):
"""Create a new user and return it"""
return get_user_model().objects.create_user(**validated_data)
def update(self, instance, validated_data):
"""Update a user and return it"""
password = validated_data.pop('password', None)
user = super().update(instance, validated_data)
if password:
user.set_password(password)
user.save()
return user
now when I want to create a new user it tells me that field certificates can not be empty, how can I make the certificates field not required?
Currently any password that I PUT or PATCH do not get encrypted.
I am using a ModelSerializer.
class UserSerializer (serializers.ModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'pk')
With a ModelViewSet
class UserViewSet (ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
Why are my passwords saved as plain text? And how do I fix this?
Should I overwrite the update () in serialiser or update () in ViewSet? Where's the problem?
You should overwrite create and update methods in your serializers to make encryption possible:
from django.contrib.auth.hashers import make_password
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = User.objects.create_user(
password=make_password(
validated_data['user'].pop('password')
),
**validated_data.pop('user')
)
def update(self, instance, validated_data):
if 'user' in validated_data:
instance.user.password = make_password(
validated_data.get('user').get('password', instance.user.password)
)
instance.user.save()
class Meta:
model = User
fields = (
'url', 'username', 'email', 'pk'
)
I am trying to create a api for user Registration using the django rest framework.
I have the following models.py file
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE , primary_key = True)
mobileNumber = models.IntegerField(default=0)
avatar= models.ImageField(upload_to = 'User/' , default = '/static/User/defaultProfileImage.png')
def create_user_profile(sender, **kwargs):
if kwargs['created']:
profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_user_profile, sender=User)
This is my Serializers.py file
from rest_framework import serializers
from User.models import UserProfile
from django.contrib.auth.models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
username = serializers.CharField()
password1 = serializers.CharField(
style={'input_type': 'password'},
write_only=True)
password2 = serializers.CharField(
style={'input_type': 'password'},
write_only=True)
email = serializers.EmailField()
class Meta:
model = User
fields = (
'id',
'username',
'password1',
'password2',
'email',
'first_name',
'last_name',
)
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = UserProfile
fields = (
'user',
'mobileNumber',
'avatar')
And following is my views.py file
from User.models import UserProfile
from .serializers import UserProfileSerializer
from rest_framework.viewsets import ModelViewSet
class UserProfileViewSet(ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
What is the best way to create a User Registeration using the api view that i have created. I tried many alternatives like overriding the create method in the UserProfile Serializer class and also the drf-writable-nested but got errors.
Please suggest me a way out. Also i want that the api is able to register users when called on by an android app.
You can do this in your Serializers.py file, this should work.
class UserSerializer(serializers.HyperlinkedModelSerializer):
mobileNumber = serializers.IntegerField()
avatar= serializers.ImageField()
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password', 'mobileNumber', 'avatar')
def create(self, validated_data):
mobile_number = validated_data.pop('mobileNumber', None)
user = super(UserSerializer, self).create(validated_data)
user.set_password(raw_password=validated_data['password'])
user.save()
userprofile = user.userprofile
userprofile.mobileNumber = mobile_number
userprofile.save()
return user
def update(self, instance, validated_data):
mobile_number = validated_data.pop('mobileNumber', None)
userprofile = instance.userprofile
userprofile.mobileNumber = mobile_number
userprofile.save()
return super(UserSerializer, self).update(instance, validated_data)
Chuck the UserProfileSerializer for this use case, i feel here its not really needed.
Your views.py and models.py look cool to me.
Hope this helps you :-)
I have a custom user model and I am using django-rest-framework to create API
models.py:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
unique=True,
max_length=254,
)
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=15)
mobile = models.IntegerField(unique=True)
date_joined = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
serializers.py:
class UserSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'mobile', 'password1', 'password2')
views.py:
#api_view(['POST'])
#permission_classes((AllowAny,))
def create_user(request):
serialized = UserSerializer(data=request.data)
if serialized.is_valid():
User.objects.create_user(
serialized.save()
)
return Response(serialized.data, status=status.HTTP_201_CREATED)
else:
return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)
However, when I try to create a new user I am getting this error:
Got a TypeError when calling User.objects.create(). This may be because you have a writable field on the serializer class that is not a valid argument to User.objects.create(). You may need to make the field read-only, or override the UserSerializer.create() method to handle this correctly.
This maybe because there's no password1 or password2 fields in the User model. But so, how can I create an API to create a new user using django-rest-framework?
I think one password field is enough. If you want to check the user's twice password input is same, do it in the front-end. You can override a create method from serializer like following.
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'mobile', 'password')
def create(self, validated_data):
user = super(UserSerializer, self).create(validated_data)
user.set_password(validated_data['password'])
user.save()
return user
views.py
from rest_framework import generics
from rest_framework.permissions import AllowAny
from .models import User
from .serializers import UserSerializer
class UserCreateAPIView(generics.CreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (AllowAny,)
I am new to Django rest and serializers concept
I have this kind of DB structure
User 1->N Address,
User 1->N Phone
User is a django.contrib.auth.models.User. Address and Phone both models contains this field user_id = models.ForeignKey(User, on_delete=models.CASCADE)
In my UserSerializer looks like this
class UserSerializer(serializers.ModelSerializer):
address = AddressSerializer(many=False)
phone = PhoneSerializer(many=False)
class Meta:
model = User
fields = (
'id', 'username',
'first_name', 'last_name',
'email', 'password',
'address', 'phone')
def create(self, validated_data):
# Save user.
user = User.objects.create(
first_name=validated_data['first_name'],
last_name=validated_data['last_name'],
username=validated_data['username'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
# User's address
address_data = validated_data['address']
address_data['user_id'] = user.id
address = Address.objects.create(**address_data)
# User's phone
phone_data = validated_data['phone']
phone_data['user_id'] = user.id
phone = Phone.objects.create(**phone_data)
return user
And AddressSerializer:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = (
'user_id', 'address', 'pin_code', 'state', 'city', 'country')
I am able to create User but while doing serializer.data I am getting this error:
AttributeError: Got AttributeError when attempting to get a value for field `address` on serializer `UserSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.
Original exception text was: 'User' object has no attribute 'address'.
EDIT:
My create method looks like this
def create(self, validated_data):
password = validated_data.pop('password')
validated_data['username'] = validated_data['email']
user = User.objects.create(**validated_data)
user.set_password(password)
user.save()
return user
Your fields for address and phone should be called address_set and phone_set if you haven't specified related_name explicitly
class UserSerializer(serializers.ModelSerializer):
address_set = AddressSerializer(many=False)
phone_set = PhoneSerializer(many=False)
class Meta:
model = User
fields = (
'id', 'username',
'first_name', 'last_name',
'email', 'password',
'address_set', 'phone_set'
)
or
class UserSerializer(serializers.ModelSerializer):
address = AddressSerializer(many=False, source='address_set')
phone = PhoneSerializer(many=False, source='phone_set')
class Meta:
model = User
fields = (
'id', 'username',
'first_name', 'last_name',
'email', 'password',
'address', 'phone'
)