Python Django Rest - Return 具有其他字段的最低、最高和平均值的额外字段
Python Django Rest - Return extra field with lowest, highest and average values of some other field
我是 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"
}
工资范围报告的端点:
curl -H 'Content-Type: application/json' localhost:8000/reports/employees/salary/
回复:
{
"lowest ": {
"id": "2",
"name": "Obi-Wan Kenobi",
"email": "kenobi@ssys.com.br",
"department": "Back-End",
"salary": "3000.00",
"birth_date": "01-01-1977"},
"highest": {
"id": "3",
"name": "Leia Organa",
"email": "organa@ssys.com.br",
"department": "DevOps",
"salary": "5000.00",
"birth_date": "01-01-1980"},
"average": "4000.00"
}
我有两个应用程序,employees
和 reports
。
这里是employees/models.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):
class Meta:
model = Employee
fields = ['id', 'name', 'email', 'departament', 'salary', 'birth_date']
我不确定如何为我的报表应用程序创建视图和序列化程序。我该如何处理?
如何 return 一个额外的字段,在另一个字段的值之间进行计算?我应该在序列化程序中创建自定义字段吗?
通过阅读 docs 我发现我应该使用的查询应该是这样的:
Employee.objects.aggregate(Max("salary"), Min("salary"), Avg("salary"))
或者,例如薪水:
Employee.objects.all().order_by('salary')
但是我该如何使用它呢?
我不知道在哪里使用或如何去做,因为我对 APIs 和 Django Rest Framework 的理解仍然非常缺乏。
它应该放在我的 reports/view.py 中吗?或者在我的 employees/serializers.py?
我应该创建一个 reports/serializers.py 文件吗?
我需要 reports/model class 和 lowest
、highest
、average
字段加上一个员工对象字段?
我是否应该在 reports/views.py 中覆盖 ReportSalaryListAPIView
class 的 list()
函数? (这个class还不存在)
我很迷茫和困惑。请帮我指明正确的方向。
提前致谢。
编辑:
我的 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()
@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)
我的employees/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'
发生了什么事?
想法
不需要额外的字段来存储计算值,因为它们是根据数据库中的行计算的。
- 首先用聚合的方法求出
min_salary
、max_salary
、avg_salary
。
- 使用 found
min_salary
和 max_salary
查找员工。
- 实施序列化程序 class,序列化
highest
、lowest
和 average
员工工资报告。
- 使用已实现的序列化程序 class.
序列化 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"),
]
我是 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"
}
工资范围报告的端点:
curl -H 'Content-Type: application/json' localhost:8000/reports/employees/salary/
回复:
{
"lowest ": {
"id": "2",
"name": "Obi-Wan Kenobi",
"email": "kenobi@ssys.com.br",
"department": "Back-End",
"salary": "3000.00",
"birth_date": "01-01-1977"},
"highest": {
"id": "3",
"name": "Leia Organa",
"email": "organa@ssys.com.br",
"department": "DevOps",
"salary": "5000.00",
"birth_date": "01-01-1980"},
"average": "4000.00"
}
我有两个应用程序,employees
和 reports
。
这里是employees/models.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):
class Meta:
model = Employee
fields = ['id', 'name', 'email', 'departament', 'salary', 'birth_date']
我不确定如何为我的报表应用程序创建视图和序列化程序。我该如何处理?
如何 return 一个额外的字段,在另一个字段的值之间进行计算?我应该在序列化程序中创建自定义字段吗?
通过阅读 docs 我发现我应该使用的查询应该是这样的:
Employee.objects.aggregate(Max("salary"), Min("salary"), Avg("salary"))
或者,例如薪水:
Employee.objects.all().order_by('salary')
但是我该如何使用它呢?
我不知道在哪里使用或如何去做,因为我对 APIs 和 Django Rest Framework 的理解仍然非常缺乏。
它应该放在我的 reports/view.py 中吗?或者在我的 employees/serializers.py?
我应该创建一个 reports/serializers.py 文件吗?
我需要 reports/model class 和 lowest
、highest
、average
字段加上一个员工对象字段?
我是否应该在 reports/views.py 中覆盖 ReportSalaryListAPIView
class 的 list()
函数? (这个class还不存在)
我很迷茫和困惑。请帮我指明正确的方向。
提前致谢。
编辑:
我的 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()
@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)
我的employees/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'
发生了什么事?
想法
不需要额外的字段来存储计算值,因为它们是根据数据库中的行计算的。
- 首先用聚合的方法求出
min_salary
、max_salary
、avg_salary
。 - 使用 found
min_salary
和max_salary
查找员工。 - 实施序列化程序 class,序列化
highest
、lowest
和average
员工工资报告。 - 使用已实现的序列化程序 class. 序列化
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"),
]