I'm new to Django and APIs in general and I want to create a Django based API using Django Rest Framework.
Here's what I want to do:
Endpoint to age range report:
curl -H 'Content-Type: application/json' localhost:8000/reports/employees/age/
Response:
{
"younger": {
"id": "1",
"name": "Anakin Skywalker",
"email": "[email protected]",
"department": "Architecture",
"salary": "4000.00",
"birth_date": "01-01-1983"},
"older": {
"id": "2",
"name": "Obi-Wan Kenobi",
"email": "[email protected]",
"department": "Back-End",
"salary": "3000.00",
"birth_date": "01-01-1977"},
"average": "40.00"
}
Here's my code so far:
employees/model.py:
class Employee(models.Model):
name = models.CharField(max_length=250, default='FirstName LastName')
email = models.EmailField(max_length=250, default='[email protected]')
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'
In employees/services.py I have:
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
)
But when I try to access http://localhost:8000/reports/employees/age/
I get this error:
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'.
Full Traceback:
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'.
What am I doing wrong and how do I fix it?
Thank you in advance.
CodePudding user response:
Try this,
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
getting a list instead of an object here.