def test_filter_queryset_returns_empty_queryset(self): queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) filtered_queryset = validator.filter_queryset('anonymous', queryset) self.assertEqual(len(filtered_queryset), 0)
def test_set_context(self): queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) self.assertEqual(validator.field_name, 'name') self.assertIsNone(validator.instance)
def test_exclude_current_instance_returns_queryset_with_exclude(self): admin = self.User.objects.get(name='admin') queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) serializer.fields['name'].parent.instance = admin validator.set_context(serializer.fields['name']) filtered_queryset = validator.exclude_current_instance(queryset) self.assertNotIn(queryset, filtered_queryset)
def test_exclude_current_instance_returns_queryset(self): queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) self.assertEqual( validator.exclude_current_instance(queryset), queryset )
def test_filter_queryset(self): queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) filtered_queryset = validator.filter_queryset('admin', queryset) self.assertEqual(len(filtered_queryset), 1) self.assertIsInstance(filtered_queryset[0], self.User) self.assertEqual(filtered_queryset[0].name, 'admin')
def test_repr(self): queryset = self.User.objects.all().order_by('id') serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) self.assertEqual( validator.__repr__(), "'<UniqueValidator(queryset=<QuerySet [<User: <User(admin)>>, " "<User: <User(manager)>>, <User: <User(author)>>]>)>'" )
def get_relation_kwargs(field_name, relation_info): """ Creates a default instance of a flat relational field. """ model_field = relation_info.model_field related_model = relation_info.related_model to_many = relation_info.to_many to_field = relation_info.to_field has_through_model = relation_info.has_through_model kwargs = { 'queryset': related_model._default_manager, 'view_name': get_detail_view_name(related_model) } if to_many: kwargs['many'] = True if to_field: kwargs['to_field'] = to_field if has_through_model: kwargs['read_only'] = True kwargs.pop('queryset', None) if model_field: if model_field.verbose_name and needs_label(model_field, field_name): kwargs['label'] = capfirst(model_field.verbose_name) if model_field.help_text: kwargs['help_text'] = model_field.help_text if not model_field.editable: kwargs['read_only'] = True kwargs.pop('queryset', None) if kwargs.get('read_only', False): # If this field is read-only, then return early. # No further keyword arguments are valid return kwargs if model_field.has_default() or model_field.blank or model_field.null: kwargs['required'] = False if model_field.null: kwargs['allow_null'] = True if model_field.validators: kwargs['validators'] = model_field.validators if getattr(model_field, 'unique', False): queryset = model_field.model._default_manager validator = UniqueValidator(queryset=queryset) kwargs['validators'] = kwargs.get('validators', []) + [validator] if to_many and not model_field.blank: kwargs['allow_empty'] = False return kwargs
def get_field_kwargs(field_name, model_field): """ Creates a default instance of a basic non-relational field. """ kwargs = {} validator_kwarg = list(model_field.validators) # The following will only be used by ModelField classes. # Gets removed for everything else kwargs['model_field'] = model_field if model_field.verbose_name and needs_label(model_field.verbose_name, field_name): # NOQA kwargs['label'] = capfirst(model_field.verbose_name) if model_field.help_text: kwargs['help_text'] = model_field.help_text max_digits = getattr(model_field, 'max_digits', None) if max_digits is not None: kwargs['max_digits'] = max_digits decimal_places = getattr(model_field, 'decimal_places', None) if decimal_places is not None: kwargs['decimal_places'] = decimal_places if isinstance(model_field, models.AutoField) or not model_field.editable: # If this field is read-only, then return early. # Further keyword arguments are not valid kwargs['read_only'] = True return kwargs if model_field.has_default() or model_field.blank or model_field.null: kwargs['required'] = False is_nullable_field = not isinstance(model_field, models.NullBooleanField) if model_field.null and is_nullable_field: kwargs['allow_null'] = True if model_field.blank and (isinstance(model_field, models.CharField) or isinstance(model_field, models.TextField)): kwargs['allow_blank'] = True if isinstance(model_field, models.FilePathField): kwargs['path'] = model_field.path if model_field.match is not None: kwargs['match'] = model_field.match if model_field.recursive is not False: kwargs['recursive'] = model_field.recursive if model_field.allow_files is not True: kwargs['allow_files'] = model_field.allow_files if model_field.allow_folders is not False: kwargs['allow_folders'] = model_field.allow_folders if model_field.choices: # If this model field contains choices, then return early. # Further keyword arguments are not valid kwargs['choices'] = model_field.choices return kwargs # Our decimal validation is handled in the field code, not validator code. if isinstance(model_field, models.DecimalField): validator_kwarg = [ validator for validator in validator_kwarg if not isinstance(validator, DecimalValidator) ] # Ensure that max_length is passed explicitly as a keyword arg, # rather than as a validator max_length = getattr(model_field, 'max_length', None) if max_length is not None and (isinstance(model_field, models.CharField) or isinstance(model_field, models.TextField)): kwargs['max_length'] = max_length validator_kwarg = [ validator for validator in validator_kwarg if not isinstance(validator, MaxLengthValidator) ] # Ensure that min_length is passed explicitly as a keyword arg, # rather than as a validator min_length = next((validator.limit_value for validator in validator_kwarg if isinstance(validator, MinLengthValidator)), None) if min_length is not None and isinstance(model_field, models.CharField): kwargs['min_length'] = min_length validator_kwarg = [ validator for validator in validator_kwarg if not isinstance(validator, MinLengthValidator) ] # Ensure that max_value is passed explicitly as a keyword arg, # rather than as a validator max_value = next((validator.limit_value for validator in validator_kwarg if isinstance(validator, MaxValueValidator)), None) if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): kwargs['max_value'] = max_value validator_kwarg = [ validator for validator in validator_kwarg if not isinstance(validator, MaxValueValidator) ] # Ensure that max_value is passed explicitly as a keyword arg, # rather than as a validator min_value = next((validator.limit_value for validator in validator_kwarg if isinstance(validator, MinValueValidator)), None) if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): kwargs['min_value'] = min_value validator_kwarg = [ validator for validator in validator_kwarg if not isinstance(validator, MinValueValidator) ] # URLField does not need to include the URLValidator argument, # as it is explicitly added in if isinstance(model_field, models.URLField): validator_kwarg = [ validator for validator in validator_kwarg if not isinstance(validator, URLValidator) ] # EmailField does not need to include the validate_email argument, # as it is explicitly added in if isinstance(model_field, models.EmailField): validator_kwarg = [ validator for validator in validator_kwarg if validator is not validate_email ] # SlugField do not need to include the 'validate_slug' argument if isinstance(model_field, models.SlugField): validator_kwarg = [ validator for validator in validator_kwarg if validator is not validate_slug ] # for IPAddressField exclude the 'validate_ipv46_address' argument if isinstance(model_field, models.GenericIPAddressField): validator_kwarg = [ validator for validator in validator_kwarg if validator is not validate_ipv46_address ] if getattr(model_field, 'unique', False): unique_error_message = model_field.error_messages.get('unique', None) if unique_error_message: unique_error_message = unique_error_message % { 'model_name': model_field.model._meta.verbose_name, 'field_label': model_field.verbose_name } validator = UniqueValidator( queryset=model_field.model._default_manager, message=unique_error_message) validator_kwarg.append(validator) if validator_kwarg: kwargs['validators'] = validator_kwarg return kwargs
def test_call_raises_validation_error(self): queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) self.assertRaises(ValidationError, validator, 'admin')
def test_call_passed_successfully(self): queryset = self.User.objects.all() serializer = self.user_serializer() validator = UniqueValidator(queryset) validator.set_context(serializer.fields['name']) self.assertIsNone(validator('unnamed'))