从可重复使用的应用中覆盖DRF串行器

时间:2019-05-08 15:39:22

标签: django-rest-framework

在可重用的应用程序中,是否有一种明显的方法可以替代DRF用于视图集的序列化器?

我有一个ViewSet,它使用ModelSerializer子类。我想添加一个字段。 但是,我希望将模型以及与此外部字段相关的所有其他内容放到一个单独的应用程序中,因为它不是核心功能的一部分。

单独的应用可以依赖于核心Django项目中的应用,但反之则不行。显然,它并不是真正可重用的,但是为了简单起见,我们还是使用此术语。

对于一个人为的例子,假设我在核心项目的一个应用程序中有一个简单的Employee模型,并且我想添加一个“可重用”的应用程序,该应用程序可以存储员工的Facebook个人资料。 因此,在“ core_app”中将具有以下模型,视图集和序列化器:

models.py

from django.contrib.auth.models import User
from django.db import models


class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.CharField(max_length=100)

viewsets.py

from rest_framework import viewsets

from .models import Employee
from .serializers import EmployeeSerializer


class EmployeeViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = EmployeeSerializer

serializers.py

from rest_framework import serializers

from .models import Employee


class EmployeeSerializer(serializers.ModelSerializer):
    username = serializers.CharField(source="user.username")

    class Meta:
        model = Employee
        fields = ["username", "department"]

现在,我有一个可重用的应用程序,该应用程序的模型的模型为OneToOneField,其模型为Employee,还有一个序列化器子类,该子类添加了所需的字段:

models.py

from django.db import models

from core_app.models import Employee


class FacebookProfile(models.Model):
    employee = models.OneToOneField(Employee, on_delete=models.CASCADE)
    facebook_profile_link = models.CharField(max_length=1024)

serializers.py

from rest_framework import serializers

from core_app.models import Employee
from core_app.serializers import EmployeeSerializer


class FacebookProfileEmployeeSerializer(EmployeeSerializer):
    facebook_profile_link = serializers.CharField(source="facebookprofile")

    class Meta:
        model = Employee
        fields = ["username", "department", "facebook_profile_link"]

因此,基本上我想让core_app.viewsets.EmployeeViewSet使用“可重用”应用程序中的FacebookProfileEmployeeSerializer而不是core_app.serializers.EmployeeSerializer。 我不想对core_app进行任何更改,也不必对Django项目进行任何更改(除了将“可重用”应用添加到INSTALLED_SETTINGS中)。

我可以在“可重用”应用程序中覆盖完整的core_app.viewsets.EmployeeViewSet,然后通过覆盖ROOT_URLCONF中的URL在原始应用程序中使用它,但这不是一个很好的解决方案,需要我进行更改该项目。

另一个仅替换core_app.viewsets.EmployeeViewSet使用的序列化程序的解决方案是猴子补丁。如果可能的话,我想避免这种情况,因为这是一个骇人听闻的解决方案,可能会导致可维护性问题,而且还可能还需要我更改项目,以便在导入原始文件之前修补序列化程序。

因此,如果有更明确的方法可以实现,我会更喜欢。 我试图找到一种更好的方法,但到目前为止找不到任何方法。

1 个答案:

答案 0 :(得分:1)

  

在我的“可重用”应用程序中覆盖完整的core_app.viewsets.EmployeeViewSet,然后通过覆盖ROOT_URLCONF中的URL在原始应用程序上使用它,但这不是一个好的解决方案,并且需要我更改项目。

我建议:

facebook/viewsets.py

from core_app.viewsets import EmployeeViewSet

from .serializers import FacebookProfileEmployeeSerializer

class FacebookProfileEmployeeViewSet(EmployeeViewSet):
    serializer_class = FacebookProfileEmployeeSerializer

然后在urls.py

# Note that we use FacebookProfileEmployeeViewSet in preference to EmployeeViewSet
router.register(r"employee", FacebookProfileEmployeeViewSet)

我认为第三方应用程序需要两步安装:

  1. 在设置中将应用添加到INSTALLED_APPS
  2. 将网址添加到urls.py