【问题标题】:Django Rest Framework - 'User' object has no attribute 'payments'Django Rest Framework - “用户”对象没有属性“付款”
【发布时间】:2026-01-20 03:00:01
【问题描述】:

我花了很多时间试图理解我遇到的这个错误。

来自models.py

class Company(models.Model):
    name = models.CharField(max_length=100, unique=True, default="")
    email = models.CharField(max_length=100, unique=True, default="")
    password = models.CharField(max_length=100, unique=True, default="")
    bsb = models.IntegerField(default=0)
    account = models.IntegerField(default=0)
    sign_up_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name


class Payment(models.Model):
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="payments")
    name = models.CharField(max_length=100, unique=True, default="")
    bsb = models.IntegerField(default=0)
    account = models.IntegerField(default=0)
    created_date = models.DateTimeField(auto_now_add=True)
    paid_date = models.DateTimeField(default=datetime.now() + timedelta(days=36500))
    status = models.IntegerField(default=0)

来自serializers.py

from rest_framework import serializers

from .models import Payment, Company


class PaymentSerializer(serializers.ModelSerializer):
    company = serializers.ReadOnlyField(source='company.name')

    class Meta:
        model = Payment
        fields = ['company', 'name', 'bsb', 'account', 'created_date', 'paid_date', 'status']


class CompanySerializer(serializers.ModelSerializer):
    payments = serializers.PrimaryKeyRelatedField(many=True, queryset=Payment.objects.all())

    class Meta:
        model = Company
        fields = ["name", "email", "password", "payments",
                  "bsb", "account", "sign_up_date"]

如您所见,我在 Payment 类中包含了相关名称作为公司属性的“payments”。但是当我访问 http://localhost:8000/bill_payer/resources/company 时出现以下错误:

AttributeError: 'User' object has no attribute 'payments'

我已经通过 manage.py shell 验证了我的 Company 类确实有支付类。

有什么想法吗?我是新的。这是views.py,以防它很重要:

class PaymentList(APIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def get(self, request):
        payments = Payment.objects.all()
        serializer = PaymentSerializer(payments, many=True)
        return Response(serializer.data)

    def perform_create(self, serializer):
        serializer.save(company=self.request.user)


class PaymentDetail(APIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def get_object(self, pk):
        try:
            return Payment.objects.get(pk=pk)
        except Payment.DoesNotExist:
            raise Http404

    def get(self, request, pk):
        payment = self.get_object(pk)
        serializer = PaymentSerializer(payment)
        return Response(serializer.data)

    def put(self, request, pk):
        payment = self.get_object(pk)
        serializer = PaymentSerializer(payment, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        payment = self.get_object(pk)
        payment.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


class CompanyList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = CompanySerializer


class CompanyDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = CompanySerializer

【问题讨论】:

    标签: python django rest django-rest-framework


    【解决方案1】:

    您收到错误是因为您尝试将 User 对象用于 CompanySerializer,它需要 Company 模型对象。如果您按以下方式修复它,它将起作用。

    class CompanyList(generics.ListAPIView):
        queryset = Company.objects.all()
        serializer_class = CompanySerializer
    
    
    class CompanyDetail(generics.RetrieveAPIView):
        queryset = Company.objects.all()
        serializer_class = CompanySerializer
    

    【讨论】:

    • 感谢您极快的回复!我使用 User 的原因是因为我正在关注本教程:django-rest-framework.org/tutorial/…。我相信用户是从 django.contrib.auth.models 导入用户的一部分。你知道他们为什么使用 User 吗?它有什么好处?再次感谢,你是最棒的。
    • 不客气!链接中的示例通过 User 模型进行,它在 UserSerializer 的 Meta 类中给出。这实际上与您的示例不同。如果您想使用 UserListView 或 UserDetailView,您应该这样做。但是你想为公司做这件事,这是一个完全不同的模型。
    【解决方案2】:

    请改一下

    class CompanyList(generics.ListAPIView):
        queryset = User.objects.all()
        serializer_class = CompanySerializer
    
    
    class CompanyDetail(generics.RetrieveAPIView):
        queryset = User.objects.all()
        serializer_class = CompanySerializer
    

    class CompanyList(generics.ListAPIView):
        queryset = Company.objects.all()
        serializer_class = CompanySerializer
    
    
    class CompanyDetail(generics.RetrieveAPIView):
        queryset = Company.objects.all()
        serializer_class = CompanySerializer
    

    你在 perform_create 方法中也做错了。

    class PaymentList(APIView):
        permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    
        def get(self, request):
            payments = Payment.objects.all()
            serializer = PaymentSerializer(payments, many=True)
            return Response(serializer.data)
    
        def perform_create(self, serializer):
            serializer.save(company=self.request.user)
    

    不应该

    serializer.save(company=self.request.user)
    

    因为它不是公司对象。 self.request.user 是一个用户对象。并且您正在尝试将用户对象保存到公司对象。这是错的。 尝试使用

    serializer.save()
    or
    serializer.save(company=serializer.data.get("company"))
    

    【讨论】:

    • 嗨@jeevu94,我认为perform_create 方法有助于使用URL 中隐含提及的公司字段创建Payment 对象。也许你可以纠正我?这是参考:django-rest-framework.org/tutorial/…
    • 是的,它有帮助。但是您传递的变量不正确。例如:如果那是serializer.save(user=self.request.user),那很好。但是你通过(company=self.request.user) (company obj != user obj) 你明白了吗?对于您的项目,只需使用 serializer.save()
    • 不需要 perform_create 方法。它会由序列化程序自动完成。仅当您想在保存前进行一些编码时才对其进行编辑。如果不只是在查看代码中使用 serializer.save() 。就是这样。