Marco de descanso de Django AttributeError: Got Attribute Error al intentar obtener un valor para el campo
He estado intentando añadir atributos al UserProfile creando un OneToOneField
a Usuario y agregando diferentes campos. Ahora corro esto y llamo al api con el cuerpo abajo. El api es capaz de ser analizado con éxito. Un usuario se crea en la tabla de usuario y la tabla de perfil de usuario con los atributos correctos. Sin embargo, Django devuelve un error AttributeError: Got AttributeError when attempting to get a value for field first_name on serializer UserProfileSerializer
. Esto tiene sentido ya que el modelo no tiene estos atributos, pero cuál es la manera correcta de pasar el json de la misma manera y crear el usuario en el User
Cuadro y UserProfile
¿Mesa?
{
"first_name": "Jay",
"last_name" : "Patel",
"email": "[email protected]",
"password": "password",
"tier": "Gold",
"bkms_id": "12234"
}
modelo.py
# Create your models here.
class UserProfile(models.Model):
MedalType: List[Tuple[str, str]] = [('Bronze', 'Bronze'), ('Silver', 'Silver'), ('Gold', 'Gold')]
bkms_id = models.PositiveIntegerField()
tier = models.CharField(choices=MedalType, max_length=100)
user = models.OneToOneField(to=User, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
serializador.py
from typing import Dict
from django.contrib.auth.models import User
from rest_framework import serializers
from authentication.models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
password = serializers.CharField(max_length=65, min_length=8, write_only=True, required=True,
style={'input_type': 'password'})
email = serializers.EmailField(max_length=255, min_length=4, required=True)
first_name = serializers.CharField(max_length=255, min_length=2, required=True)
last_name = serializers.CharField(max_length=255, min_length=2, required=True)
bkms_id = serializers.IntegerField(required=True, min_value=0)
tier = serializers.CharField(required=True)
class Meta:
model = UserProfile
fields = ['first_name', 'last_name', 'email', 'password', 'bkms_id', 'tier']
def validate(self, attrs):
if User.objects.filter(email=attrs.get('email', '')).exists():
raise serializers.ValidationError({'email': 'Email is already in use'})
if UserProfile.objects.filter(bkms_id=attrs.get('bkms_id', '')).exists():
raise serializers.ValidationError({'bkms_id': 'BKMS is already in use'})
return super().validate(attrs)
def create(self, validated_data: Dict):
email = validated_data.pop('email', '')
password = validated_data.pop('password', '')
first_name = validated_data.pop('first_name', '')
last_name = validated_data.pop('last_name', '')
user = User.objects.create_user(email, email, password, first_name=first_name, last_name=last_name)
user.save()
validated_data['user'] = user
return UserProfile.objects.create(**validated_data)
vistas. py
# Create your views here.
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from authentication.serializers import UserProfileSerializer
class RegisterView(GenericAPIView):
serializer_class = UserProfileSerializer
permission_classes = [AllowAny]
def post(self, request):
serializer = UserProfileSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Pregunta hecha hace 3 años, 5 meses, 0 días - Por csharpsorcerer
3 Respuestas:
-
Sugiero crear diferentes serializadores como este:
class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(max_length=65, min_length=8, write_only=True, required=True, style={'input_type': 'password'}) email = serializers.EmailField(max_length=255, min_length=4, required=True) first_name = serializers.CharField(max_length=255, min_length=2, required=True) last_name = serializers.CharField(max_length=255, min_length=2, required=True) class Meta: model = User fields = ['first_name', 'last_name', 'email', 'password'] class UserProfileSerializer(serializers.ModelSerializer): user = UserSerializer() bkms_id = serializers.IntegerField(required=True, min_value=0) tier = serializers.CharField(required=True) class Meta: model = UserProfile fields = ['user', 'bkms_id', 'tier'] def validate(self, attrs): if User.objects.filter(email=attrs.get('email', '')).exists(): raise serializers.ValidationError({'email': 'Email is already in use'}) if UserProfile.objects.filter(bkms_id=attrs.get('bkms_id', '')).exists(): raise serializers.ValidationError({'bkms_id': 'BKMS is already in use'}) attrs['user'] = { 'email': attrs.get('email', ''), 'first_name': attrs.get('first_name', ''), 'last_name': attrs.get('last_name', ''), 'password': attrs.get('password', '') } return super().validate(attrs) def create(self, validated_data: Dict): validated_user = validated_data.pop('user', {}) email = validated_user.pop('email', '') password = validated_user.pop('password', '') first_name = validated_user.pop('first_name', '') last_name = validated_user.pop('last_name', '') user = User.objects.create_user(email=email, password=password, first_name=first_name, last_name=last_name) user.save() validated_data['user'] = user return UserProfile.objects.create(**validated_data)
Respondida el Dec 16, 2020 a las 16:30 - por algorithmadept
Votos positivos: 0 | Votos negativos: 0 -
El error que estás experimentando se debe a que estás pasando campos que no están definidos en tu serializer
UserProfileSerializer
. En tu caso, estás pasandofirst_name
,last_name
,email
,password
,bkms_id
, ytier
en tu solicitud de JSON, pero estos campos no están definidos en tu serializerUserProfileSerializer
.Para solucionar este error, necesitas modificar tu serializer
UserProfileSerializer
para que maneje estos campos, ya que actualmente solo está configurado para manejar los camposfirst_name
,last_name
,email
,password
,bkms_id
, ytier
.Aquí te dejo un ejemplo de cómo puedes modificar tu serializer para manejar los campos adicionales:
python class UserProfileSerializer(serializers.ModelSerializer): password = serializers.CharField(max_length=65, min_length=8, write_only=True, required=True, style={'input_type':'password'}) email = serializers.EmailField(max_length=255, min_length=4, required=True) first_name = serializers.CharField(max_length=255, min_length=2, required=True) last_name = serializers.CharField(max_length=255, min_length=2, required=True) bkms_id = serializers.IntegerField(required=True, min_value=0) tier = serializers.CharField(required=True) class Meta: model = UserProfile fields = ['password', 'email', 'first_name', 'last_name', 'bkms_id', 'tier'] def validate(self, attrs): if User.objects.filter(email=attrs.get('email', '')).exists(): raise serializers.ValidationError({'email': 'Email is already in use'}) return attrs def create(self, validated_data): user_data = { 'email': validated_data['email'], 'password': validated_data['password'], 'first_name': validated_data['first_name'], 'last_name': validated_data['last_name'] } user = User.objects.create_user(*user_data) user_profile_data = { 'user': user, 'bkms_id': validated_data['bkms_id'], 'tier': validated_data['tier'] } user_profile = UserProfile.objects.create(*user_profile_data) return user_profile
Es importante asegurarse de que los campos esperados en el serializer coincidan con los campos en tu solicitud de JSON para evitar errores de atributo en Django. Si necesitas manejar más campos o personalizar la lógica de creación y validación, puedes modificar el serializer según tus necesidades.
Respondida el Dec 17, 2020 a las 16:29 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El error que estás encontrando se debe a que el modelo
UserProfile
no tiene los atributosfirst_name
ylast_name
. Estos atributos pertenecen al modeloUser
. Para resolver este problema, puedes hacer lo siguiente:- Agrega los atributos `first_name` y `last_name` al modelo `UserProfile`.
python class UserProfile(models.Model): first_name = models.CharField(max_length=100, null=True, blank=True) last_name = models.CharField(max_length=100, null=True, blank=True)
... resto de los atributos
- Actualiza el serializador `UserProfileSerializer` para incluir los nuevos atributos.
python class UserProfileSerializer(serializers.ModelSerializer): first_name = serializers.CharField(max_length=100, required=False) last_name = serializers.CharField(max_length=100, required=False)
... resto de los campos
- Actualiza la vista `RegisterView` para asignar los valores de `first_name` y `last_name` al modelo `User`.
python def post(self, request): serializer = UserProfileSerializer(data=request.data) if serializer.is_valid(): user_data = serializer.validated_data
Crea el usuario
user = User.objects.create_user( email=user_data['email'], username=user_data['email'],Puedes personalizar el nombre de usuario aquí
password=user_data['password'], first_name=user_data['first_name'], last_name=user_data['last_name'], )Crea el perfil de usuario
user_profile = UserProfile.objects.create( user=user,... resto de los atributos
) serializer = UserProfileSerializer(user_profile) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)Estos cambios te permitirán crear correctamente los usuarios y los perfiles de usuario con los atributos
first_name
ylast_name
.Respondida el Dec 17, 2020 a las 16:38 - por Gemini
Votos positivos: 0 | Votos negativos: 0