1

我正在尝试在 DRF 中实现多种用户类型,我正在通过一个

  1. 用户模型- 在所有角色中都有登录相关字段和公共字段,还有一个表示用户类型的选择字段。
  2. 客户模型- 带有用户模型的 OneToOneField。
  3. 卖家模型- 带有用户模型的 OneToOneField。

我已经为 User 模型设置了身份验证和权限,现在我可以登录了。我希望登录的用户能够创建他各自的配置文件(基于 User 模型的 user_type 字段)。

class User(AbstractBaseUser, PermissionsMixin):
    """ A Generic User inside our system. The fields used are common to all users in system. """
    ....


class Customer(models.Model):
    """A Class to represent a Customer in  System """

    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)

现在我试图弄清楚如何允许用户创建与他的 user_type(客户/卖家)相对应的配置文件。更令人困惑的部分是我如何将用户设置为我的当前登录用户CustomerSerializerSellerSerializer

这是我正在尝试使用的权限类:

class UpdateCustomerProfile(permissions.BasePermission):
    """Allow users to edit their own profile """

    def has_object_permission(self, request, view, obj):
        """Check if user is trying to edit their own profile"""

        return obj.user.id == request.user.id

这是客户序列化程序:

 class CustomerSerializer(serializers.ModelSerializer):
  """A Serizlier class for customer """

    class Meta:
        model = models.Customer
        fields = ('user', 'first_name', 'last_name', 'dob', 'gender')

    def create(self, validated_data):
     """Create and return a new customer."""

客户视图集:

class CustomerViewSet(viewsets.ModelViewSet):
    """Handle creating reading and updating Users in  system"""

    serializer_class = serializers.CustomerSerializer
    queryset = models.User.objects.filter( user_type = "CS" )
    authentication_classes = (TokenAuthentication,)
    permission_classes = (permissions.UpdateCustomerProfile,)

但我得到一个错误

/api/customer-profile/ 处的 AttributeError 尝试获取userserializer 上字段的值时出现 AttributeError CustomerSerializer。序列化器字段可能命名不正确,并且与User实例上的任何属性或键都不匹配。原始异常文本是:“用户”对象没有属性“用户”。

我是 Django 的新手,所以我不确定这是一种方法还是我做错了什么。我怎样才能解决这个问题?任何遵循类似策略的示例项目也将非常有帮助。

4

3 回答 3

2

由于您的序列化程序适用于 a Customer,因此您的查询集应适用于 a Customer

queryset = models.Customer.objects.filter(user=request.user)

例如,如果您只想查看Customer当前user.

于 2019-03-05T12:30:58.777 回答
0
class CustomerViewSet(viewsets.ModelViewSet):
"""Handle creating reading and updating Users in  system"""

serializer_class = serializers.CustomerSerializer
#you are using customer model for serializer but for query set you are using 
 #User model.
queryset = models.Customer.objects.filter( user__type = "CS" )
authentication_classes = (TokenAuthentication,)
permission_classes = (permissions.UpdateCustomerProfile,)
于 2019-03-05T12:31:01.270 回答
0

嘿,我的代码在下面用于序列化多种用户类型的注册。我跟着这个:https ://www.freecodecamp.org/news/nested-relationships-in-serializers-for-onetoone-fields-in-django-rest-framework-bdb4720d81e6/

这是我的models.py:

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    is_individual = models.BooleanField(default=False)
    is_company = models.BooleanField(default=False)


class Company(models.Model):
    user                   = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    company_name           = models.CharField(max_length=100)
    email_address = models.EmailField(max_length=254, blank=True, null=True)

class Individual(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    email_address = models.EmailField(max_length=254)

这是我的serializers.py:

from rest_framework import serializers
from classroom.models import User, Individual, Company
from django.contrib.auth import authenticate

class IndividualSerializer(serializers.ModelSerializer):
    class Meta:
        model = Individual
        fields = ('user', 'email_address')

class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ('user', 'email_address', 'company_name')

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'is_individual', 'is_company')
        extra_kwargs = {'password': {'write_only': True}}



class IndividualRegisterSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)
    
    class Meta:
        model = Individual
        fields = ('user', 'email_address')
        extra_kwargs = {'password': {'write_only': True}, 'username': {'write_only': True}}

    def create(self, validated_data, *args, **kwargs):
        user = User.objects.create_user(validated_data['user']['username'], validated_data['email_address'], validated_data['user']['password'])
        individual = Individual.objects.create(user=user, email_address=validated_data.pop('email_address'))
        return individual


class CompanyRegisterSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    class Meta:
        model = Company
        fields = ('user', 'company_name', 'email_address')
        extra_kwargs = {'password': {'write_only': True}, 'username': {'write_only': True}}

    def create(self, validated_data, *args, **kwargs):
        user = User.objects.create_user(validated_data['user']['username'], validated_data['email_address'],
                                        validated_data['user']['password'])
        company = Company.objects.create(user=user, email_address=validated_data.pop('email_address'), company_name=validated_data.pop('company_name'))
        return company

class IndividualLoginSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()

    def validate(self, data):
        individual = authenticate(**data)
        if individual and individual.is_active:
            return individual
        raise serializers.ValidationError("Incorrect Credentials")

    class Meta:
        fields = ['username','password','is_individual','is_company']
        extra_kwargs = {'is_individual': {'required': False},
                        'is_company': {'required': False}}

这是我的 api.py:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import generics, permissions
from knox.models import AuthToken
from ..serializers import  \
    UserSerializer, \
    IndividualRegisterSerializer, CompanyRegisterSerializer, \

class RegisterIndividualAPI(generics.GenericAPIView):
    serializer_class = IndividualRegisterSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        individual = serializer.save()
        individual_data = IndividualSerializer(individual, context=self.get_serializer_context()).data
        
        return Response({
             "individual": individual_data,
             "username": individual.user.username,
             "token": AuthToken.objects.create(individual.user)[1]
        })

class RegisterCompanyAPI(generics.GenericAPIView):
    serializer_class = CompanyRegisterSerializer
    
    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        company = serializer.save()
        company_data = CompanySerializer(company, context=self.get_serializer_context()).data
        return Response({
             "company": company_data,
             "username": company.user.username,
             "token": AuthToken.objects.create(company.user)[1]
        })

class LoginCompanyAPI(generics.GenericAPIView):
    serializer_class = CompanyLoginSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        company = serializer.validated_data
        company_data = CompanySerializer(company, context=self.get_serializer_context()).data
        return Response({
            "company": company_data,
             "username": company.user.username,
             "token": AuthToken.objects.create(company.user)[1]
        })

这是我的 API POST 请求的正文:

{
    "user": {
        "username":"nind5",
        "password": "123456",
        "is_individual" : "True",
        "is_company" : "False"
    },
    "email_address":"n@gmail.com"
}

我也使用了这个资源https://www.youtube.com/watch?v=0d7cIfiydAc&t=437s。诺克斯也在此视频中进行了解释。

此外,使用此在线工具查看您的数据库(db.sqlite3)表:https ://sqliteonline.com/

最好的,尼克

于 2020-07-20T01:07:34.323 回答