【问题标题】:Django REST Framework: default fields in browseable API formDjango REST Framework:可浏览 API 表单中的默认字段
【发布时间】:2013-12-27 13:39:31
【问题描述】:

我有一个模型:

class XCall(models.Model):
    created_on = models.DateTimeField(auto_now_add=True)
    send_on = models.DateTimeField(default=datetime.now)
    recipient = models.ForeignKey(User)
    text = models.CharField(max_length=4096)
    backup_calls = models.IntegerField(blank=True, null=True)

以及该模型的序列化程序:

class CallSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name='call-detail',
    )
    # some validation and custom field definitions
    ...

    class Meta:
        model = XCall
        fields = ('url', 'id', 'text', 'recipient', 'send_on', 'backup_calls', 'status')
        lookup_field= 'pk'

这是列表视图:

class CallList(generics.ListCreateAPIView):
    serializer_class = CallSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrSuperuser,)

    def pre_save(self, obj):
        auth_user = self.request.user
        obj.auth_user = auth_user

    def get_queryset(self):
        """
        This view should return a list of all the calls
        for the currently authenticated user.
        """
        auth = self.request.user
        if isinstance(auth, AnonymousUser):
            return []
        elif auth.is_superuser:
            return XCall.objects.all()
        else:
            return XCall.objects.filter(auth_user=auth)

在CallList 的可浏览API 中,我在底部的POST 表单中看到以下内容:

我的问题是:为什么send_on 没有设置默认值,而backup_calls 设置了一个默认值?我假设表单将遵循XCall 模型规范并使用datetime.now() 来默认前者,并将backup_calls 留空(因为它可以为空)。如何让表格符合型号规格?

【问题讨论】:

  • 你解决过这个问题吗?我目前正在遇到它。

标签: django django-rest-framework


【解决方案1】:

您实际上想要设置initial 值,而不是默认值。请参阅docs。你的代码应该是:

from django.utils import timezone


class CallSerializer(serializers.HyperlinkedModelSerializer):
    send_on = serializers.DateTimeField(initial=timezone.now())
    ...

如果没有为字段设置值,则默认值是提供给属性的值。 initial 和 default 参数之间的区别反映了 Django 的表单字段 initial 参数和 Django 模型字段的 default 参数之间的区别。

【讨论】:

    【解决方案2】:

    模型默认值和表单中的初始值是有区别的。对于实际上是函数的默认值尤其如此,因为它们仅在保存实例时才被调用。例如,您想要哪个now - 这次是显示空白表单的时间,还是用户按下“POST”的时间?如果缺少字段值,Django 在保存模型时应用默认值。要实现您想要的,您需要在序列化字段中手动设置默认值,例如:

    class CallSerializer(serializers.HyperlinkedModelSerializer):
        send_on = serializers.DateTimeField(default=datetime.now)
        ...
    

    【讨论】:

    • 我不确定我是否看到了您描述的行为。当我尝试在未填写 send_on 的情况下发布时,我收到一个验证错误“此字段是必需的”。如果您说 Django 在保存时应用默认值,为什么会出现验证错误?其他一些信息:1)我在Django 1.6上;我隐约记得在我从 1.4 升级之前,所有这些工作方式都不同。 2)奇怪的是,我看到默认表单值在 Django 开发模式中按预期工作,但在我的生产环境(Django + Apache + mod_wsgi)中却没有。
    • 此外,这个答案并没有解释为什么我看到 backup_calls 字段的默认值。我没有在CallSerializer 中明确设置它
    • IIRC,字段验证首先发生在表单中。表单看到 send_on 中没有输入任何内容,它是必需的,并且根据表单字段没有默认值,因此在进入模型之前会引发异常。我不知道为什么它在生产中的工作方式会有所不同 - 听起来可能是一些奇怪的缓存问题。
    • 我怀疑因为backup_calls 是一个整数字段,所以它使用了一个整数格式的文本框,它显示了一个零默认值。您可以通过检查 html 来看到这一点。该字段设置为空白和 null 的事实使它看起来像一个错误。
    • 好的,我看到我的开发环境正在运行 DRF 2.3.6,而生产是在 2.3.10 上。所以这解释了不同的行为。那么 2.3.6 是否有副作用,使其尊重模型默认值?
    猜你喜欢
    • 2014-06-07
    • 2016-03-24
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2016-01-31
    • 2015-02-19
    • 2014-05-28
    相关资源
    最近更新 更多