如何根据Django Rest Framework

时间:2016-06-03 12:48:40

标签: python django django-rest-framework

我有三个模型TransactionBusinessLocation。它们的定义如下:

class Business(models.Model): 
    # Can have zero or more locations. A user can have many businesses.
    name  = models.CharField(max_length=200, validators=[MinLengthValidator(1)])
    # ... and some other fields ...

class Location(models.Model): 
    # Must have one business. Locations cannot exist without a business
    suburb   = models.CharField(max_length=150, validators=[MinLengthValidator(1)])
    business = models.ForeignKey(Business, related_name='locations')
    # ... and some other fields ...

class Transaction(models.Model): 
    # Can have zero or one business
    # Can have zero or one location and the location must belong to the business. If business is empty, location must be empty
    business = models.ForeignKey(Business, on_delete=models.SET_NULL, null=True, blank=True, related_name='transactions')
    location = models.ForeignKey(Location, on_delete=models.SET_NULL, null=True, blank=True, related_name='transactions')
    # ... and some other fields ...

序列化器:

class BusinessRelatedField(serializers.PrimaryKeyRelatedField):

    def get_queryset(self):
        owner = get_owner_from_context(self.context)
        return Business.objects.filter(owner=owner)

class LocationRelatedField(serializers.PrimaryKeyRelatedField):

    def get_queryset(self):
        params = self.context['request'].query_params
        business_params = params.get('business')
        if business_params is not None:
            owner = get_owner_from_context(self.context)
            return Location.objects.filter(owner=owner, business=business_params)
        else:
            return None

class TransactionSerializer(serializers.ModelSerializer):

    business = BusinessRelatedField(required=False, allow_null=True)
    location = LocationRelatedField(required=False, allow_null=True)

我遇到的问题是我不知道如何根据Location的值限制Business的值。我在TransactionSerializer的{​​{1}}方法中手动执行此检查,直到我发现创建validate子类并覆盖PrimaryKeyRelatedField方法。这对我来说似乎是一种更好的方法(而且它确实在起作用),但我想知道这是否是“正常”的做法。

我现在面临的另一个问题是'可浏览的API'不再显示get_queryset的任何选择,我觉得这可能是我可能做错了什么。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:0)

您可以覆盖序列化程序的get_fields()方法,并将querysetbusiness字段location修改为所需的值。< / p> 当访问get_fields()属性时,序列化程序使用

field names -> field instances方法生成.fields映射。

class TransactionSerializer(serializers.ModelSerializer):

    class Meta:
        model = Transaction
        fields = (.., business, transaction)

    def get_fields(self):
        # get the original field names to field instances mapping
        fields = super(TransactionSerializer, self).get_fields()

        # get the required parameters
        owner = get_owner_from_context(self.context)
        business_params = self.context['request'].query_params.get('business')

        # modify the queryset
        fields['business'].queryset = Business.objects.filter(owner=owner)
        fields['location'].queryset = Location.objects.filter(owner=owner, business=business_params)

        # return the modified fields mapping
        return fields