我正在编写Django REST Framework API。 我的模型具有供内部使用的默认Django PK和供外部参考的uuid字段。
class BaseModel(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
class Event(BaseModel):
title = models.TextField()
location = models.ForeignKey('Location', null=True, on_delete=models.SET_NULL)
class Location(BaseModel):
latitude = models.FloatField()
longitude = models.FloatField()
还有我的序列化器:
class BaseSerializer(serializers.ModelSerializer):
default_fields = ('uuid',)
class EventSerializer(BaseSerializer):
class Meta:
model = Event
lookup_field = 'uuid' # This does not work
fields = BaseSerializer.default_fields + ('title', 'location',)
class LocationSerializer(BaseSerializer):
class Meta:
model = Location
lookup_field = 'uuid' # This does not work
fields = BaseSerializer.default_fields + ('latitude', 'longitude',)
这很好用,这是我检索事件时得到的:
{
"uuid": "ef33db27-e98b-4c26-8817-9784dfd546c6",
"title": "UCI Worldcup #1 Salzburg",
"location": 1 # Note here I have the PK, not UUID
}
但是我想要的是:
{
"uuid": "ef33db27-e98b-4c26-8817-9784dfd546c6",
"title": "UCI Worldcup #1 Salzburg",
"location": "2454abe7-7cde-4bcb-bf6d-aaff91c107bf" # I want UUID here
}
当然,我希望此行为适用于我的所有ForeignKeys和ManyToMany字段。 有没有一种方法可以自定义DRF用于嵌套模型的字段? 谢谢!
答案 0 :(得分:1)
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ObjectDoesNotExist
from rest_framework.relations import RelatedField
class UUIDRelatedField(RelatedField):
"""
A read-write field that represents the target of the relationship
by a unique 'slug' attribute.
"""
default_error_messages = {
'does_not_exist': _('Object with {uuid_field}={value} does not exist.'),
'invalid': _('Invalid value.'),
}
def __init__(self, uuid_field=None, **kwargs):
assert uuid_field is not None, 'The `uuid_field` argument is required.'
self.uuid_field = uuid_field
super().__init__(**kwargs)
def to_internal_value(self, data):
try:
return self.get_queryset().get(**{self.uuid_field: data})
except ObjectDoesNotExist:
self.fail('does_not_exist', slug_name=self.uuid_field, value=smart_text(data))
except (TypeError, ValueError):
self.fail('invalid')
def to_representation(self, obj):
return getattr(obj, self.uuid_field)
样品用量:
class ProductSerializer(serializers.ModelSerializer):
category = UUIDRelatedField(
queryset=Category.objects.all(),
uuid_field='alias'
)
class Meta:
model = Product
fields = (
'id',
'alias',
'name',
'category',
)
read_only_fields = (
'id',
'alias',
)
答案 1 :(得分:0)
对于嵌套模型字段,您可以在类似这样的序列化器中使用source
参数
class EventSerializer(BaseSerializer):
location = serializers.CharField(source='location.uuid')
class Meta:
model = Event
lookup_field = 'uuid' # This does not work
fields = BaseSerializer.default_fields + ('title', 'location',)
答案 2 :(得分:0)
我的一个朋友给我发送此解决方案: 它适用于我所有相关的对象。
from rest_framework import serializers
from rest_framework.relations import SlugRelatedField
class UuidRelatedField(SlugRelatedField):
def __init__(self, slug_field=None, **kwargs):
slug_field = 'uuid'
super().__init__(slug_field, **kwargs)
class BaseSerializer(serializers.ModelSerializer):
default_fields = ('uuid',)
serializer_related_field = UuidRelatedField
class Meta:
pass