rest_framework modelSerializer的模型方法

kun*_*unl 6 django django-models python-3.x django-rest-framework

这是一个简单的问题,但我对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)
Run Code Online (Sandbox Code Playgroud)

串行器是否可能

class ListingSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.MasterListing
Run Code Online (Sandbox Code Playgroud)

要访问Listing.is_projectie对于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
Run Code Online (Sandbox Code Playgroud)

我明白我可以使用的某种组合做到这一点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
Run Code Online (Sandbox Code Playgroud)

因此,最初的问题仍然存在:"modelSerializer是否有可能访问其模型方法?"

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

arg*_*aen 6

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

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

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

PS:我非常喜欢drf的完整文档=).

编辑

要使用source属性,您只需声明一个新的显式字段,如下所示:

is_project = serializers.BooleanField(source='is_project')
Run Code Online (Sandbox Code Playgroud)

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


Gab*_*iel 5

@argaen 是绝对正确的,source是 DRF 的核心论点,并且肯定会解决您的问题。source但是,如果字段名称与 相同,则使用 是多余的source。因此,上述答案不需要您指定source,因为fieldname与nameis_project相同。sourceis_project

所以在你的情况下:

is_project = serializers.BooleanField()
Run Code Online (Sandbox Code Playgroud)