-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Closed
Labels
Description
Checklist
- I have verified that that issue exists against the
master
branch of Django REST framework. - I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- This is not a usage question. (Those should be directed to the discussion group instead.)
- This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
- I have reduced the issue to the simplest possible case.
- I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)
Steps to reproduce
- Create a fresh Django project
- Create an app called "widgets"
- Use this code for the "widgets" app's "models.py" file:
from django.core.exceptions import ValidationError from django.db import models class Widget(models.Model): STATUS_INCOMPLETE = 'i' STATUS_IN_PROGRESS = 'p' STATUS_COMPLETE = 'c' STATUS_CHOICES = ( (STATUS_INCOMPLETE, 'Incomplete'), (STATUS_IN_PROGRESS, 'In Progress'), (STATUS_COMPLETE, 'Complete'), ) name = models.CharField(max_length=255, unique=True) foo_status = models.CharField(choices=STATUS_CHOICES, max_length=1) bar_status = models.CharField(choices=STATUS_CHOICES, max_length=1) baz_status = models.CharField(choices=STATUS_CHOICES, max_length=1) class Meta: ordering = ('name',) def __str__(self): return self.name def clean(self): in_progress = 0 excess_in_progress_status_fields = [] for status_field in ( 'foo_status', 'bar_status', 'baz_status', ): if getattr(self, status_field) == self.STATUS_IN_PROGRESS: in_progress += 1 if in_progress > 1: excess_in_progress_status_fields.append(status_field) if excess_in_progress_status_fields: errors = {} for status_field in excess_in_progress_status_fields: errors[status_field] = ( 'You cannot have multiple status dropdown menus set to ' '"In Progress".' ) raise ValidationError(errors)
- Use this code for the "widgets" app's "admin.py" file:
from django.contrib import admin from .models import Widget admin.site.register(Widget)
- Use this code for the project's "urls.py" file:
from django.conf.urls import url, include from django.contrib import admin from rest_framework import routers, serializers, viewsets from widgets.models import Widget class WidgetSerializer(serializers.ModelSerializer): class Meta: model = Widget fields = '__all__' def validate(self, attrs): instance = Widget(**attrs) instance.clean() return attrs class WidgetViewSet(viewsets.ModelViewSet): queryset = Widget.objects.all() serializer_class = WidgetSerializer router = routers.DefaultRouter() router.register(r'widgets', WidgetViewSet) urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url(r'^admin/', admin.site.urls), ]
- Try to create a record with all three status fields set to "In Progress"
Expected behavior
The "bar_status" and "baz_status" fields should each be given an error message. This is how it's handled in the admin:
Actual behavior
The two error messages intended for the "bar_status" and "baz_status" fields are added to "non_field_errors" instead:
iwaszko, meteozond, cebamps, xuhcc and mehranj73