Я новичок в Django и API в целом, и я хочу создать API на основе Django с использованием Django Rest Framework.
Вот что я хочу сделать:
От конечной точки до отчета по возрастному диапазону:
curl -H 'Content-Type: application/json' localhost:8000/reports/employees/age/
Ответ:
{
"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"
}
От конечной точки к отчету о диапазоне зарплат:
curl -H 'Content-Type: application/json' localhost:8000/reports/employees/salary/
Ответ:
{
"lowest ": {
"id": "2",
"name": "Obi-Wan Kenobi",
"email": "[email protected]",
"department": "Back-End",
"salary": "3000.00",
"birth_date": "01-01-1977"},
"highest": {
"id": "3",
"name": "Leia Organa",
"email": "[email protected]",
"department": "DevOps",
"salary": "5000.00",
"birth_date": "01-01-1980"},
"average": "4000.00"
}
У меня есть два приложения, employees
и reports
.
Вот сотрудники/models.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()
Вот сотрудники/serializers.py:
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = ['id', 'name', 'email', 'departament', 'salary', 'birth_date']
Я не знаю, как создавать представления и сериализаторы для своего приложения для отчетов. Как мне подойти к этому?
Как я могу вернуть дополнительное поле с расчетом между значениями другого поля? Должен ли я создать настраиваемое поле в моем сериализаторе?
Прочитав документы, я понял, что запрос, который я должен использовать, должен выглядеть примерно так:
Employee.objects.aggregate(Max("salary"), Min("salary"), Avg("salary"))
Или, например, для зарплаты:
Employee.objects.all().order_by('salary')
Но как мне его использовать?
Я не знаю, где это использовать и как это сделать, поскольку мое понимание API и Django Rest Framework все еще очень слабое.
Должен ли он идти в моем отчеты/view.py? Или в моем сотрудники/serializers.py?
Должен ли я создать файл отчеты/serializers.py?
Нужен ли мне класс отчеты/модель с полями lowest
, highest
, average
плюс поле объекта сотрудника?
Должен ли я переопределить функцию list()
моего класса ReportSalaryListAPIView
в моем отчеты/views.py? (Этот класс еще не существует)
Я очень потерян и сбит с толку. Пожалуйста, помогите указать мне правильное направление.
Заранее спасибо.
Редактировать:
Мой сотрудники /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()
@property
def get_age(self):
delta = relativedelta(self.birth_date.days, datetime.today()).years
return delta
def save(self, *args, **kwargs):
self.age = self.get_age()
super(Employee, self).save(*args, **kwargs)
Мой сотрудники/serializers.py сейчас:
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = ['id', 'name', 'email', 'departament', 'salary', 'birth_date', 'age']
На всякий случай я запустил команды makemigrations
и migrate
с manager.py
.
Но теперь я сталкиваюсь с этой ошибкой при попытке создать нового сотрудника:
'datetime.date' object has no attribute 'days'
Что происходит?
🤔 А знаете ли вы, что...
С Python можно создавать роботов и автоматизированные системы с использованием библиотеки Raspberry Pi.
Никаких дополнительных полей для хранения рассчитанных значений не требуется, поскольку они вычисляются на основе строк в базе данных.
min_salary
, max_salary
и avg_salary
, используя метод агрегата.min_salary
и max_salary
, чтобы найти сотрудников.highest
, lowest
и average
отчет о зарплате сотрудников.lowest
, highest
и avarage
с помощью реализованного класса сериализатора.На мой взгляд, код для выполнения логики должен быть на другом уровне, обычно называемом сервисным.
# employees/services.py
class EmployeeSalaryReport:
def __init__(self, lowest, highest, average):
self.lowest = lowest
self.highest = highest
self.average = average
def get_employee_salary_report():
salary_report_dict = Employee.objects.aggregate(
min_salary=Min("salary"),
max_salary=Max("salary"),
avg_salary=Avg("salary"),
)
lowest_salary_employee = Employee.objects.filter(
salary=salary_report_dict.get("min_salary")
).first()
highest_salary_employee = Employee.objects.filter(
salary=salary_report_dict.get("max_salary")
).first()
return EmployeeSalaryReport(
lowest=lowest_salary_employee,
highest=highest_salary_employee,
average=salary_report_dict.get("avg_salary"),
)
# employees/serializers.py
class EmployeeSalaryReportSerializer(serializers.Serializer):
lowest = EmployeeSerializer()
highest = EmployeeSerializer()
average = serializers.FloatField()
# employees/views.py
from rest_framework import views
from rest_framework.response import Response
from employees.services import get_employee_salary_report
from employees.serializers import EmployeeSalaryReportSerializer
class ReportSalaryView(views.APIView):
def get(self, request, *args, **kwargs):
employee_salary_report = get_employee_salary_report()
serializer = EmployeeSalaryReportSerializer(employee_salary_report)
return Response(serializer.data)
# employees/urls.py
from django.urls import path
from employees.views import ReportSalaryView
urlpatterns = [
... # other paths
path("reports/employees/salary/", ReportSalaryView.as_view(), name = "report-salary"),
]