如何在Django Rest框架的视图集中使用update方法并执行一些任务(比如发送邮件)?

2024-04-25 22:38:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个简单的性能管理系统,前端是react,后端是django。他们是监督员,可以对被监督者进行审查,被监督者可以作出回应。我希望所有员工在收到主管的评论时都能收到电子邮件,所有主管在回复他们的评论时都能收到电子邮件。对于评论和响应,我使用了两个不同的序列化程序,但模型相同

响应的序列化程序为:

class ResponseSerializer(serializers.ModelSerializer):
    supervisor_name = serializers.SerializerMethodField('get_supervisor_name')
    supervisor_email = serializers.SerializerMethodField('get_supervisor_email')
    supervisee_name = serializers.SerializerMethodField('get_supervisee_name')
    supervisee_email = serializers.SerializerMethodField('get_supervisee_email')

    class Meta:
        model = Review
        fields = (
            'id', 'review_text', 'response_text', 'date_of_review', 'date_of_response', 'supervisor', 'supervisor_name',
            'supervisor_email', 'supervisee', 'supervisee_name', 'supervisee_email')
        read_only_fields = ('review_text', 'date_of_review', 'supervisor', 'supervisee')

    def get_supervisor_name(self, obj):
        return obj.supervisor.first_name + " " + obj.supervisor.last_name

    def get_supervisor_email(self, obj):
        return obj.supervisor.email

    def get_supervisee_name(self, obj):
        return obj.supervisee.first_name + " " + obj.supervisee.last_name

    def get_supervisee_email(self, obj):
        return obj.supervisee.email

对于发送邮件,我使用来自django.core的send_-mail方法,并使用viewset进行评论和回复

现在,响应操作将始终是更新操作,因为响应将始终用于更新现有的审阅对象,其中response_text字段将被更新

class ResponseViewSet(viewsets.ModelViewSet):
    queryset = Review.objects.all()
    permission_classes = [
        # permissions.IsAuthenticated,
        permissions.AllowAny,
    ]
    serializer_class = ResponseSerializer

    def update(self, request, *args, **kwargs):
        serializer = ResponseSerializer(data=request.data)

        if serializer.is_valid():
            supervisor = serializer.data["supervisor_name"]
            supervisee = serializer.data["supervisee_name"]
            query = serializer.save()
            mail_text = "Hi {}\n\nYou got a response for your 1:1 from {}.\n\nClick below to see the response:\n\n{}".format(
                supervisor,
                supervisee,
                "https://example.com/#/pms/reviewsBySupervisor",
            )
            try:
                if not settings.DEFAULT_EMAIL_RECIPIENTS:
                    settings.DEFAULT_EMAIL_RECIPIENTS.append(
                        str(serializer.data["supervisor_email"])
                    )
                send_mail(
                    subject="New Response Received",
                    message=mail_text,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=settings.DEFAULT_EMAIL_RECIPIENTS,
                    fail_silently=False,
                )
            except (SMTPRecipientsRefused, SMTPSenderRefused):
                LOGGER.exception("There was a problem submitting the form.")
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

因此,我面临的问题是,当我尝试在ResponseViewset中使用update方法发送邮件时,如上所示。我得到以下错误:

Internal Server Error: /UMS/api/responses/38/
Traceback (most recent call last):
  File "/home/shishir/Projects/performance_management/performance_management/reviews/serializers.py", line 77, in get_supervisor_name
    return obj.supervisor.first_name + " " + obj.supervisor.last_name
AttributeError: 'NoneType' object has no attribute 'first_name'

因此,发生的事情是由于某种原因,在我尝试更新时,该特定审查的所有字段都被设置为null,因此得到NoneType object has no attribute。我已经签入了数据库表(MySQL),所有字段都被设置为空。谁能告诉我为什么会这样?我哪里做错了?正确的方法是什么


Tags: textnameselfobjdatagetreturnemail
1条回答
网友
1楼 · 发布于 2024-04-25 22:38:11

最后,我通过将方法update更改为partial_update找到了解决方案。显然,update方法更新了所有字段,而在上面的例子中,我正在尝试查看模型中名为response_text的字段,如果可以,则将其他字段设置为null。同样在这样做之后,我不得不在前端将请求从PUT更改为PATCH。此外,我还必须做一些其他小的编码更改,比如从supervisorsupervisee字段中删除read_only_fieldsResponseSerializer。更新的ResponseViewset代码如下所示:

class ResponseViewSet(viewsets.ModelViewSet):
    queryset = Review.objects.all()
    permission_classes = [
        permissions.IsAuthenticated,
        #permissions.AllowAny,
    ]
    serializer_class = ResponseSerializer

    def partial_update(self, request,*args, **kwargs):
        obj = self.get_object()
        serializer = self.serializer_class(obj, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            mail_text = "Hi {},\n\nYou got a response for your 1:1 from {}.\n\nClick below to see the response:\n\n{}".format(
                serializer.data["supervisor_name"],
                serializer.data["supervisee_name"],
                get_product_link("UMS/reviewsForDR"),
            )
            try:
                if not settings.DEFAULT_EMAIL_RECIPIENTS:
                    settings.DEFAULT_EMAIL_RECIPIENTS.append(
                        # supervisor_email
                        serializer.data["supervisor_email"]
                    )

                send_mail(
                    subject="New Response Received",
                    message=mail_text,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=settings.DEFAULT_EMAIL_RECIPIENTS,
                    fail_silently=False,
                )
                settings.DEFAULT_EMAIL_RECIPIENTS = []
            except (SMTPRecipientsRefused, SMTPSenderRefused):
                LOGGER.exception("There was a problem submitting the form.")
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

相关问题 更多 >