用于ContentType对象的django-rest-framework序列化程序

Aam*_*amu 8 django django-contenttypes django-rest-framework

我正在构建一个活动模型,有点类似于这个.它有演员,动词​​和目标.

class Activity(models.Model):
    actor_type = models.ForeignKey(ContentType, related_name='actor_type_activities')
    actor_id = models.PositiveIntegerField()
    actor = GenericForeignKey('actor_type', 'actor_id')
    verb = models.CharField(max_length=10)
    target_type = models.ForeignKey(ContentType, related_name='target_type_activities')
    target_id = models.PositiveIntegerField()
    target = GenericForeignKey('target_type', 'target_id')
    pub_date = models.DateTimeField(default=timezone.now)
Run Code Online (Sandbox Code Playgroud)

现在,无论何时创建任何模型(投标,作业和新闻)的新对象,都会创建一个新的Activity对象,其中target包含这三个模型中任何一个的对象.

例如.用户(演员)发表(动词)标题(目标)

class Tender(models.Model):
    title = models.CharField(max_length=256)
    description = models.TextField()

class Job(models.Model):
    title = models.CharField(max_length=256)
    qualification = models.CharField(max_length=256)

class News(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    title = models.CharField(max_length=150)
Run Code Online (Sandbox Code Playgroud)

为了得到这些数据,我正在制作一个API,它将获得所需的json数据.我正在使用django-rest-framework,而且非常新.

class ActorSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email')

class ActivitySerializer(serializers.HyperlinkedModelSerializer):
    actor = ActorSerializer()
    class Meta:
        model = Activity
        fields = ('url', 'actor', 'verb', 'pub_date')
Run Code Online (Sandbox Code Playgroud)

在上面的序列化器中,我知道actor将是用户.所以我在ActorSerializer课堂上使用了User模型.但至于target它,它可以是这三种模型中的任何一种(新闻/工作/招标).

如何TargetSerialier为ContentType对象创建一个序列化程序(例如,类),以便我可以targetActivitySerializer类字段中使用它?

Aam*_*amu 5

好的,所以在这里回答我自己的问题。我对 zymud 的回答有一些帮助。因此,显然在文档中,有一种方法可以序列化通用关系。

所以,我所要做的就是创建一个自定义字段并将该字段关联到序列化程序本身:

class ActivityObjectRelatedField(serializers.RelatedField):
    def to_representation(self, value):
        if isinstance(value, User):
            return 'User: ' + value.username
        elif isinstance(value, News):
            return 'News: ' + value.title
        elif isinstance(value, Job):
            return 'Job: ' + value.title
        elif isinstance(value, Tender):
            return 'Tender: ' + value.title
        raise Exception('Unexpected type of tagged object')


class ActivitySerializer(serializers.HyperlinkedModelSerializer):
    actor = ActivityObjectRelatedField(read_only=True)
    target = ActivityObjectRelatedField(read_only=True)

    class Meta:
        model = Activity
        fields = ('url', 'actor', 'verb', 'target', 'pub_date')
Run Code Online (Sandbox Code Playgroud)

  • 但这是否意味着这些字段现在是只读的?如果我想保存一个 ActivityObject 怎么办?如果你不给它一个只读,你必须给它一个查询集,但我不知道在它到达之前它会是什么模型。我误会了吗? (3认同)