多个用户类型的Django DRF OneToOneField

时间:2019-03-05 12:07:11

标签: python django django-rest-framework

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

  1. 用户模型-具有所有角色中与登录相关的字段和公共字段,还具有表示用户类型的选择字段。
  2. 客户模型-具有用户模型的OneToOneField。
  3. 卖方模型-具有用户模型的OneToOneField。

我已经为用户模型设置了身份验证和权限,现在可以登录。我希望登录的用户能够创建其各自的配置文件(基于用户模型的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."""

CustomerViewSet:

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   尝试获取序列化程序user上字段CustomerSerializer的值时,出现AttributeError。   序列化程序字段的名称可能不正确,并且与User实例上的任何属性或键都不匹配。   原始异常文本为:“用户”对象没有属性“用户”。

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

3 个答案:

答案 0 :(得分:2)

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

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

例如,如果您只想访问当前Customer的{​​{1}}个人资料。

答案 1 :(得分:0)

user

答案 2 :(得分:0)

嘿,下面有我的代码可用于序列化多个用户类型的注册。我遵循了这个规则:https://www.freecodecamp.org/news/nested-relationships-in-serializers-for-onetoone-fields-in-django-rest-framework-bdb4720d81e6/

这是我的模型。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(db.sqlite3)表:https://sqliteonline.com/

最好, 尼克