Search code examples
djangodjango-rest-framework

Django REST Framework a boolean/None value in the request is getting set to False


I have a value named 'active' which defaults to 'True' in the Django model. I would like to not set this value and allow it to be created by the default action, however, somewhere in the Django REST Framework it is being set to 'False' before it gets to the validate methods in the Serializer. How can I prevent this action or at least trap it, so that I can set a non-existent 'active' value to 'True'?

I'm only posting the relevant code, this is a complex system and the complete code would be overwhelming. The status columns come from this abstract class model. As you can see only the active column is defaulted to True.

class StatusModelMixin(models.Model):
    active = models.BooleanField(
        verbose_name=_("Active"), default=True,
        help_text=_("If checked the record is active."))
    soft_delete = models.BooleanField(
        verbose_name=_("Hide"), default=False,
        help_text=_("If checked the record is removed from all queries."))
    purge = models.BooleanField(
        verbose_name=_("Purge"), default=False,
        help_text=_("If checked the record will be deleted."))

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        """
        Intercept the save and update the 'purge' and 'soft_delete' objects.
        This save will not be called during bulk creates and updates, so the
        logic below will need to be duplicated for each object in bulk
        operations.
        """
        if self.purge: self.soft_delete = True
        if self.soft_delete: self.active = False
        super(StatusModelMixin, self).save(*args, **kwargs)

This is but one of the serializer class' that are effected by the issue I am having. You can see some of my test code that didn't fix the issue.

class OrganizationSerializer(serializers.ModelSerializer):
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail', read_only=True)
    uri = serializers.HyperlinkedIdentityField(
        view_name='organization-detail')
    #active = serializers.BooleanField(default=True, required=True)

    class Meta:
        model = Organization
        fields = ('id', 'address_01', 'address_02', 'city', 'region',
                  'postal_code', 'country', 'phone', 'fax', 'active',
                  'soft_delete', 'purge', 'ctime', 'mtime', 'institution',
                  'user', 'uri')
        exclude = ('purge',)
        read_only_fields = ('id', 'ctime', 'mtime',)
        depth = 0

    #def validate(self, attrs):
    #    log.debug("attrs: %s", attrs)
    #    return attrs

Thanks


Solution

  • Okay so i have just tried, and really the model default is being ignored, even when you specify it in serializer. Seems like when the value is not sent explicitly it is being ignored.

    I have looked around and found a bug report for this:

    https://github.com/tomchristie/django-rest-framework/issues/1101.

    Until this is one is fixed you can try this ugly hack in your viewset:

    def get_serializer(self, *args, **kwargs):
        # data may be None
        data = kwargs['data']
        if data is not None:
            data = data.copy() # need to make copy because of immutable QueryDict
            data.setdefault('active', True)
            kwargs['data'] = data
        return super(OrganizationViewSet, self).get_serializer(*args, **kwargs)