【问题标题】:Trying to override djoser serializer getting AttributeError: Got AttributeError when attempting to get a value for field error尝试覆盖 djoser 序列化程序获取 AttributeError:尝试获取字段错误值时出现 AttributeError
【发布时间】:2021-06-17 16:24:57
【问题描述】:

我是 djoser 的新手,我是验证用户的用户。然后,我希望在访问 user/me 时显示患者信息,但我覆盖它以也显示患者详细信息,但出现此错误

错误

AttributeError: Got AttributeError when attempting to get a value for field `blood_sugar_level` on serializer `PatientInfoSerializer`.     

序列化器字段可能命名不正确,并且与UserProfile 实例上的任何属性或键都不匹配。 原始异常文本为:“UserProfile”对象没有属性“blood_sugar_level”。

模型.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager

from django.db import models
from django.conf import settings # used to retreive AUTH_USER_MODEL from settings.py file

# These two imports allow for the default user model to be customized or overrided 
from django.contrib.auth.models import AbstractBaseUser 
from django.contrib.auth.models import PermissionsMixin

# Default model manager
from django.contrib.auth.models import BaseUserManager 


class UserProfileManager(BaseUserManager):
    """Manager for user profiles"""

    def create_user(self, email, name, password=None):
        """Create a new user profile"""
        if not email:
            raise ValueError('Users must have an email address')

        email = self.normalize_email(email)
        user = self.model(email=email, name=name,)

        user.set_password(password) #This hashes the user password so we do not have plain text passwordfs in our db
        user.save(using=self._db)

        return user

    def create_superuser(self, email, name, password):
        """Create and save a new superuser with given details"""
        user = self.create_user(email, name, password)

        user.is_superuser = True
        user.is_staff = True
        user.save(using=self._db)

        return user
            

class UserProfile(AbstractBaseUser, PermissionsMixin):
    """Database model for patients in the system"""
    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    #phone?
    #address?
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        """Retrieve full name for user"""
        return self.name

    def get_short_name(self):
        """Retrieve short name of user"""
        return self.name

    def __str__(self):
        """Return string representation of user"""
        return self.email


class PatientInfo(models.Model):
    """Database model for patient information"""

    user_profile = models.ForeignKey(
        settings.AUTH_USER_MODEL, # This points to the user model used for authentication in settings.py, if we need to change the model used change it there
        on_delete=models.CASCADE
    )

    # Patient insulin injected choices
    YES = 'YES'
    NO = 'NO'

    IS_INSULIN_INJECTED_CHOICES = [
        (YES, 'YES'),
        (NO, 'NO'),
    ]

    inject_date = models.DateField(auto_now_add=True, auto_now=False, blank= False)
    inject_time = models.TimeField(auto_now_add=True, auto_now=False, blank= False)
    blood_sugar_level = models.CharField(max_length=20, blank= False)
    is_insulin_injected = models.CharField(choices = IS_INSULIN_INJECTED_CHOICES, default = 1, max_length=3, blank= False)
    quantity = models.CharField(max_length=10, blank= False)
    inject_area = models.TextField(blank= False)

序列化器.py

from accounts import models
from djoser.serializers import UserCreateSerializer
from rest_framework import serializers
from django.contrib.auth import get_user_model
User = get_user_model()


class UserCreateSerializer(UserCreateSerializer):
    class Meta(UserCreateSerializer.Meta):
        model = User
        fields = ('id','email','name','password')


class UserProfileSerializer(serializers.ModelSerializer):
    """Serializes a user profile object"""

    class Meta:
        model = models.UserProfile
        fields = ('id', 'email', 'name', 'password')
        extra_kwargs = {
            'password': {
                'write_only': True,
                'style': {'input_type': 'password'}
            }
        }

    def create(self, validated_data):
        """Create and return a new user"""
        user = models.UserProfile.objects.create_user(
            email=validated_data['email'],
            name=validated_data['name'],
            password=validated_data['password']
        )

        return user

    def update(self, instance, validated_data):
        """Handle updating user account"""
        if 'password' in validated_data:
            password = validated_data.pop('password')
            instance.set_password(password)
 
        return super().update(instance, validated_data)   


class PatientInfoSerializer(serializers.ModelSerializer):
    """Serializes patient Info objects"""

    class Meta:
        model = models.PatientInfo # Points this serializer to the patient info model
        fields = ('id','user_profile','inject_date', 'inject_time', 'blood_sugar_level', 'is_insulin_injected', 'quantity', 'inject_area',)
        extra_kwargs = {
            'user_profile': {
                'read_only': True,
            }
        }

Views.py

from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated 
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.settings import api_settings

from accounts import serializers # Will use this to tell API what data to exect when making a POST PUT PATCH request to API
from accounts import models
from accounts import permissions

class PatientInfoViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating patient info objects"""
    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.PatientInfoSerializer # This points to the
    queryset = models.PatientInfo.objects.all()
    permission_classes = (permissions.UpdateOwnReading, IsAuthenticated,) # Validates that a user is authenticated to read or modify objects
    

    def perform_create(self, serializer): # overridijg this function so that when a user tries to create an object they are validated as the current user
        """Sets the patient profile to the logged in user"""
        serializer.save(user_profile=self.request.user) # This sets the user profile to the current user from the serializer passed in 


【问题讨论】:

    标签: python django djoser


    【解决方案1】:

    我不确定,但您似乎正在将用户对象传递给没有这些字段的患者序列化程序。

    尝试:

        def create(self, serializer):
            patinet_info = PatientInfo.objects.filter(user_profile=self.request.user)
            serializer = self.get_serializer(patinet_info, many = True) # This sets the user profile to the current user from the serializer passed in 
            serializer.is_valid(raise_exceptions=True)
            self.perform_create(serializer)
            return Response(serializer.data)
    

    现在,问题是 user_profile 是一个外键,因此根据您的模型,它们可以是患者的多个用户。 这就是为什么我添加了many= True 您还应该注意到我正在覆盖 create 而不是 perform create 方法。 这是一个更适合的地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-11
      • 2023-02-03
      • 2022-11-29
      • 1970-01-01
      相关资源
      最近更新 更多