Django Rest - Using a SerializerMethodField and getting an error: 'QuerySet' object has no attribute 'birth_date'

Django Rest - Using a SerializerMethodField and getting an error: 'QuerySet' object has no attribute 'birth_date'

我是 Django 和 API 的新手,我想使用 Django Rest Framework 创建一个基于 API 的 Django。

这是我想要做的:

年龄范围报告的终点:

curl -H 'Content-Type: application/json' localhost:8000/reports/employees/age/

回复:

{
    "younger": {
        "id": "1",
        "name": "Anakin Skywalker",
        "email": "skywalker@ssys.com.br",
        "department": "Architecture",
        "salary": "4000.00",
        "birth_date": "01-01-1983"},
    "older": {
        "id": "2",
        "name": "Obi-Wan Kenobi",
        "email": "kenobi@ssys.com.br",
        "department": "Back-End",
        "salary": "3000.00",
        "birth_date": "01-01-1977"},
    "average": "40.00"
}

到目前为止,这是我的代码:

employees/model.py:

class Employee(models.Model):
    name = models.CharField(max_length=250, default='FirstName LastName')
    email = models.EmailField(max_length=250, default='employee@email.com')
    departament = models.CharField(max_length=250, default='Full-Stack')
    salary = models.DecimalField(max_digits=15, decimal_places=2, default=0)
    birth_date = models.DateField()

employees/serializers.py:

class EmployeeSerializer(serializers.ModelSerializer):

    age = serializers.SerializerMethodField()

    class Meta:
        model = Employee
        fields = ['id', 'name', 'email', 'departament', 'salary', 'birth_date', 'age']

    def get_age(self, obj):
        delta = datetime.now().year - obj.birth_date.year
        return delta

class EmployeeAgeReportSerializer(serializers.Serializer):
    youngest = EmployeeSerializer()
    oldest = EmployeeSerializer()
    # average = serializers.FloatField()

    def create(self, validated_data):
        pass

    def update(self, instance, validated_data):
        pass

employees/views.py:

class EmployeeGenericViewSet(
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.CreateModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
    viewsets.GenericViewSet
):
    queryset = Employee.objects.all()
    serializer_class = EmployeeSerializer
    lookup_field = 'pk'

employees/services.py中我有:

class EmployeeAgeReport:
    def __init__(self, youngest, oldest):
        self.youngest = youngest
        self.oldest = oldest
        # self.average = average

def get_employee_age_report():
    age_report_dict = Employee.objects.aggregate(
        earliest_birth_date=Min("birth_date"),
        oldest_birth_date=Max("birth_date")
    )
    youngest_employee = Employee.objects.filter(
        birth_date=age_report_dict.get("earliest_birth_date")
    ).first()
    oldest_employee = Employee.objects.filter(
        birth_date=age_report_dict.get("oldest_birth_date")
    )

    return EmployeeAgeReport(
        youngest=youngest_employee,
        oldest=oldest_employee
    )

但是当我尝试访问 http://localhost:8000/reports/employees/age/ 时出现此错误:

Got AttributeError when attempting to get a value for field `birth_date` on serializer `EmployeeSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'birth_date'.

完整追溯:

Traceback (most recent call last):
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\fields.py", line 457, in get_attribute
    return get_attribute(instance, self.source_attrs)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\fields.py", line 97, in get_attribute
    instance = getattr(instance, attr)

During handling of the above exception ('QuerySet' object has no attribute 'birth_date'), another exception occurred:
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\django\views\generic\base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "D:\Programming\Desafios\Ssys\SSYS_Employee_Manager\applications\reports\views.py", line 21, in get
    return Response(serializer.data)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\serializers.py", line 555, in data
    ret = super().data
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\serializers.py", line 509, in to_representation
    attribute = field.get_attribute(instance)
  File "C:\Users\Laila\.virtualenvs\SSYS_Employee_Manager-Ih3-mAGZ\lib\site-packages\rest_framework\fields.py", line 490, in get_attribute
    raise type(exc)(msg)

Exception Type: AttributeError at /reports/employees/age/
Exception Value: Got AttributeError when attempting to get a value for field `birth_date` on serializer `EmployeeSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'birth_date'.

我做错了什么,我该如何解决?

提前致谢。

试试这个,

oldest_employee = Employee.objects.filter( birth_date=age_report_dict.get("oldest_birth_date") ) here add .first() in the end like you did for youngest_employee. 

oldest_employee 在此处获取列表而不是对象。