Django序列化程序定义初始对象

Django序列化程序定义初始对象,django,django-rest-framework,django-rest-viewsets,Django,Django Rest Framework,Django Rest Viewsets,我似乎不知道如何将初始值传递给序列化程序。我有一个多租户django站点,我现在正试图设置API。客户端字段存在,但需要隐藏并只读。我认为这就像是传统django中的一种形式和视图。我通常会在视图中传入get_首字母。我先试过了,但没用。我想我需要直接在序列化程序中获取值,但我似乎无法让它工作 型号: class Location(ClientAwareModel): name = models.CharField(max_length=64, blank=True) addre

我似乎不知道如何将初始值传递给序列化程序。我有一个多租户django站点,我现在正试图设置API。客户端字段存在,但需要隐藏并只读。我认为这就像是传统django中的一种形式和视图。我通常会在视图中传入get_首字母。我先试过了,但没用。我想我需要直接在序列化程序中获取值,但我似乎无法让它工作

型号:

class Location(ClientAwareModel):
    name = models.CharField(max_length=64, blank=True)
    address = models.CharField(max_length=64)
    address2 = models.CharField(max_length=64, blank=True)
    city = models.CharField(max_length=64)
    state = USStateField()
    zip_code = USZipCodeField()

class Client(models.Model):
    name = models.CharField(max_length=100)
    subdomain_prefix = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name

class ClientAwareModel(models.Model):
    client = models.ForeignKey(Client, on_delete=models.PROTECT)

    class Meta:
        abstract = True

def hostname_from_request(request):
    # split on `:` to remove port
    return request.get_host().split(':')[0].lower()

def client_from_request(request):
    hostname = hostname_from_request(request)
    subdomain_prefix = hostname.split('.')[0]
    return Client.objects.filter(subdomain_prefix=subdomain_prefix).first()
序列化程序您可以看到我所有失败的尝试都被注释掉了:

class LocationSerializer(serializers.ModelSerializer):
    def get_client(self, obj):
        # return client_from_request(self.request)
        return client_from_request(self.context['request'])

    # client = serializers.SerializerMethodField('get_client')
    # client = serializers.SerializerMethodField()
    # client = serializers.Field(source='get_client', read_only=True)
    # client = serializers.ReadOnlyField(source='get_client')
    # client = serializers.PrimaryKeyRelatedField(read_only=True, default='get_client')
    client = serializers.PrimaryKeyRelatedField(read_only=True, source='get_client')
    # client = serializers.HiddenField(default=get_client(self))

    class Meta:
        model = Location
        fields = ['name', 'address', 'address2', 'city', 'state', 'zip_code', 'client']
视图集:

class LocationViewSet(viewsets.ModelViewSet):
    queryset = Location.objects.all()
    serializer_class = LocationSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        client = client_from_request(self.request)
        return super().get_queryset().filter(client=client)
你可以看到我试图传递值的不同方式,但无论我做什么,我都会得到

IntegrityError at /locations/
null value in column "client_id" violates not-null constraint

在视图集中,当您的位置模型没有客户端FK时,您正试图通过过滤客户端来获取位置

就在这里:

def get_queryset(self):
        client = client_from_request(self.request)
        return super().get_queryset().filter(client=client) <----
正如@gregory在上面的评论中提到的,添加外键可以解决您的问题,然后您只需将其添加到序列化程序中即可。

将客户端对象传递给序列化程序的一种简单方法是在perform\u create方法中传递它,类似于:

from rest_framework import serializers


class LocationViewSet(viewsets.ModelViewSet):
    queryset = Location.objects.all()
    serializer_class = LocationSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        client = client_from_request(self.request)
        return super().get_queryset().filter(client=client)

    def perform_create(self, serializer):
        client = client_from_request(self.request)
        if not client:
            raise serializers.ValidationError("Client does not exist")
        serializer.save(client=client)
并从序列化程序中删除客户端字段:

class LocationSerializer(serializers.ModelSerializer):

    class Meta:
        model = Location
        fields = ['name', 'address', 'address2', 'city', 'state', 'zip_code']

什么是客户端请求?客户端是系统中的用户?你能把你的客户模型附在你的问题上吗?ClientWareModel有什么意义?为什么不在客户端添加一个位置FK?@gregory这是一个多租户站点,有大量的模型。当用户访问该站点时,他们只允许查看他们有权访问的客户端记录。我使用clientware进行继承并强制执行一些安全性。它有很多比显示的更多的东西。我只是抽出一点代码来尝试理解API为什么不工作。@Baivaras client_from_request这是决定用户访问哪个客户端站点的原因。如果有帮助的话,我添加了代码。Python是一种面向对象的语言。位置继承自ClientWareModel,该模型具有到客户端的FK。这将导致Location对象具有客户端FK。代码显示了所有现有的位置。问题是如何将初始值传递给serializer@HobbyHack很好,很抱歉以前没有看到继承: