在用例上,我现在有两个模型时间表和雇员,我想使用<来自动保存时间表的员工字段。 strong> perform_create ,但api返回错误“ / api / timesheet_entry / \ n的ValueError” \\ ,,]> \“:\” Timesheet.employee \“必须是\” Employee \”实例。
我想做的是使用 id 将时间表的员工字段保存到员工的登录字段中。
以下是有关模型,序列化器和视图集的信息。
class Timesheet(models.Model):
start_date = models.DateTimeField(verbose_name="Start Date", null=True, blank=True, default=None, editable=True, help_text="", unique=False, db_index=False,)
end_date = models.DateTimeField(verbose_name="End Date", null=True, blank=True, default=None, editable=True, help_text="", unique=False, db_index=False,)
employee = models.ForeignKey('Employee', on_delete=models.PROTECT, related_name="timesheet_entry_employee",
verbose_name="Employee", null=True, blank=True, editable=True, unique=False)
comment = models.CharField(verbose_name="Comment", null=True, blank=True, default=None, editable=True, max_length=255,)
total_hours = models.DecimalField(verbose_name="Total Hours", null=True, blank=True, default=0.00, max_digits=19, decimal_places=2,)
和
class Employee(models.Model):
name = models.CharField(verbose_name="Name", max_length=255,)
login = models.ForeignKey(User, on_delete=models.PROTECT, related_name="employee_login",
verbose_name="Login", editable=True)
hourly_cost = models.DecimalField(verbose_name="Hourly Cost", null=False, blank=False, editable=True, max_digits=19, decimal_places=2,)
charge_out_rate = models.DecimalField(verbose_name="Charge Out Rate", null=False, blank=False, max_digits=19, decimal_places=2,)
和序列化器
class TimesheetEntrySerializer(WritableNestedModelSerializer):
employee = PrimaryKeyRelatedField(many=False, read_only=False, allow_null=True, queryset=models.Employee.objects.all())
viewset的执行创建
def perform_create(self, serializer):
user_id = self.request.user
employee_user = models.Employee.objects.get(employee__login=user_id)
return serializer.save(employee=employee_user)
答案 0 :(得分:1)
Employee.objects.filter(...)
返回一个QuerySet,它是Employees
的列表。因为您的查询足够具体,所以列表将只包含一个元素but it will still be a list.
此外,您应该只使用login__id,因为您已经在查询员工。检索单个对象的正确方法是改用Employee.objects.get(login__id = request)
。
请注意,当.get()
无法找到对象时,它将引发DoesNotExist
异常。
检索当前员工的另一种方法是通过用户对象在员工上使用related_name
:
employee = self.request.user.employee_login
关于您的代码,我注意到了一些无关的东西:
login
来引用用户,并使用相关名称"employee_login"
来引用员工。最好仅将它们称为user
和'employee'
。self.request.user.id
并将其存储在名为request
的变量中。虽然这本身并不会引起问题,但最好选择一个更唯一的冗长名称,例如user_id
。self.request.user.id
获取用户ID,然后使用login__id
查询员工。您也可以简单地使用self.request.user
检索用户,然后使用login = user
查询该用户。编辑:
我看到您正在使用
employee_user = models.TimesheetEntry.objects.get(employee__login=user_id)
这没有意义,您想要检索当前用户的雇员对象,就在这里,您正在尝试获取TimesheetEntry。
user_id = self.request.user
employee_user = models.Employee.objects.get(login=user_id)
现在,我不确定是否可以将对象实例简单地传递给PrimaryKeyRelatedField,所以可以使用
return serializer.save(employee=employee_user)
或
return serializer.save(employee=employee_user.id)
编辑2:
您可以通过执行以下操作完全绕过串行器:
def perform_create(self, serializer):
user_id = self.request.user
employee_user = models.Employee.objects.get(employee__login=user_id)
timesheet_entry = serializer.save()
timesheet_entry.employee = employee_user
timesheet_entry.save()
return timesheet_entry