来自 rest_framework modelSerializer 的模型方法

Posted

技术标签:

【中文标题】来自 rest_framework modelSerializer 的模型方法【英文标题】:Model Method from rest_framework modelSerializer 【发布时间】:2015-03-22 04:50:47 【问题描述】:

这是一个简单的问题,但我对 django-rest-framework 很陌生。

我想知道是否有任何方法可以从序列化程序访问模型上定义的方法。?

假设我有一个模型

class Listing(models.Model):
    listingid           = models.BigIntegerField(primary_key=True)
    mappingid           = models.BigIntegerField()
    projectlevelid      = models.IntegerField()
    subsellerid         = models.IntegerField()
    iscreatedbyadmin    = models.BooleanField(default=None, null=True)
    createdon           = models.DateTimeField(auto_now_add=True, editable=False)
    validationstatus    = models.SmallIntegerField(default=0)

    def is_project(self):
        """ Returns True if listing is of Project Type (projectlevelid=6) else False""" 
        if self.projectlevelid == 6:
            return True
        else:
            return False

    def get_project_info(self):
        """Returns False if listing is not mapped to a project, else returns the project info"""
        if self.is_project() == False:
            return False
        return models.Project.objects.get(projectid=self.mappingid)

序列化器可以吗

class ListingSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.MasterListing

要访问Listing.is_project,即对于Listing 模型的对象,序列化程序可以调用其is_project 方法吗?

如果是这样,我可以在序列化程序中设置一个字段,以便如果is_project 返回 true,则填充该字段? 我正在尝试这样的事情,

class ListingSerializer(serializers.ModelSerializer):
    project = serializers.SomeRELATEDFieldTYPE()    # this field if populated if the `is_project` is true

    class Meta:
        model = models.MasterListing

我知道我可以使用required=FalseSerializerMethodField 的某种组合来做到这一点,但也许有更简单的方法?

注意:我无法为mappingid 设置外键,因为它依赖于projectlevelid。我也不能影响这种关系,所以不可能进一步正常化。我知道可能有某种方式使用内容类型,但如果可能的话,我们会尽量避免这种情况..


编辑:我解决了问题,但没有按照指定的问题。 我用这个:

class ListingSerializer(serializers.ModelSerializer):
    project = serializers.SerializerMethodField()

    def get_project(self, obj):
        """Returns False if listing is not mapped to a project, else returns the project info"""
        if str(obj.projectlevelid) == str(6):
            projectObj = models.Project(projectid=obj.mappingid)
            projectObjSerialized = ProjectSerializer(projectObj)
            return projectObjSerialized.data
        return False

    class Meta:
        model = models.MasterListing

所以,原来的问题仍然存在:“modelSerializer 是否可以访问它的模型方法?”

另外,现在出现的另一个问题是,我可以让序列化程序按需排除字段,即如果它确实是一个项目,它可以排除mappingidprojectlevelid吗?

【问题讨论】:

您可以使用class Meta:下的fields来控制应该包含哪些字段django-rest-framework.org/api-guide/serializers/… 这允许您排除它们,但不能动态排除。只有当 is_project 值为 false 时,他才想排除 【参考方案1】:

对于你的第一个问题source 属性就是答案,引用:

可能是只接受self参数的方法,例如 URLField('get_absolute_url')

对于您的第二个答案,是的,这也是可能的。检查它在他们的文档中提供的示例:http://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields

PS:我真的很喜欢 drf,因为它的文档非常完整 =)。

编辑

要使用源属性,您可以像这样声明一个新的显式字段:

is_project = serializers.BooleanField(source='is_project')

这样,is_project 字段就具有您实例的 is_project 方法的值。有了这个,在创建动态序列化器时(通过修改它的 init 方法),如果它是 True,你可以添加 'project' 字段。

【讨论】:

“PS:我真的很喜欢 drf,因为它的文档非常完整 =)。” 注意到了:) 但是你能提供一个如何实现源代码的例子吗?因为SerializerMethodField对应的方法获取了序列化器实例的一个对象,所以我想知道如何使用source得到相同的对象? 我已经编辑了答案,因为 source 是序列化器 Field 类的核心参数,您可以将它与 CharField、BooleanField 等任何子类一起使用。【参考方案2】:

@argaen 是绝对正确的,source 是 DRF 的核心论点,绝对可以解决您的问题。但是,如果字段名称与source 相同,则使用source 是多余的。所以上面的答案不需要你指定source,因为field 名称is_projectsource 名称is_project 相同。

所以在你的情况下:

is_project = serializers.BooleanField()

【讨论】:

以上是关于来自 rest_framework modelSerializer 的模型方法的主要内容,如果未能解决你的问题,请参考以下文章

rest_framework频率组件

django使用rest_framework

ModuleNotFoundError: No module named 'rest_framework' 我已经安装了 djangorestframework

错误:找不到 Requirement.parse('rest_framework>=3.6.3') 的合适分布

python rest_framework.py

rest_framework-序列化-总结完结篇