def test_upload_to(self): """ Ensure that the field cannot be initialized with a callable `upload_to` as this will break the filename-generation template logic. """ def dummy_upload_to(instance, filename): # pylint: disable=missing-docstring, unused-argument return 'foo' with self.assertRaises(Exception) as exc_context: self.field = ResizingImageField('testing/{attr}/path', TEST_SIZES, upload_to=dummy_upload_to) self.assertEquals( exc_context.exception.message, 'ResizingImageField does not support passing a custom callable for the `upload_to` keyword arg.', )
class ProgramDefault(SingletonModel): """ Model used to store default program configuration. This includes a default, resizable banner image which is used if a given program has not specified its own banner image. This model is a singleton - only one instance exists. """ banner_image = ResizingImageField( path_template='program/banner/default', sizes=RESIZABLE_IMAGE_SIZES, null=True, blank=True, max_length=1000, )
class Program(TimeStampedModel): """ Representation of a Program. """ uuid = models.UUIDField( blank=True, default=uuid4, editable=False, unique=True, ) name = models.CharField( help_text=_('The user-facing display name for this Program.'), max_length=255, unique=True, ) subtitle = models.CharField( help_text=_('A brief, descriptive subtitle for the Program.'), max_length=255, blank=True, ) category = models.CharField( help_text=_('The category / type of Program.'), max_length=32, choices=_choices(constants.ProgramCategory.XSERIES), ) status = models.CharField( help_text=_('The lifecycle status of this Program.'), max_length=24, choices=_choices( constants.ProgramStatus.UNPUBLISHED, constants.ProgramStatus.ACTIVE, constants.ProgramStatus.RETIRED, constants.ProgramStatus.DELETED, ), default=constants.ProgramStatus.UNPUBLISHED, # though this field is not nullable, setting blank=True ensures validators # will reject the empty string, instead of implicitly replacing it with the # default value. This is consistent with how None/null is handled. blank=True, ) marketing_slug = models.CharField( help_text=_('Slug used to generate links to the marketing site'), blank=True, max_length=255) banner_image = ResizingImageField( path_template='program/banner/{uuid}', sizes=RESIZABLE_IMAGE_SIZES, null=True, blank=True, max_length=1000, ) def save(self, *a, **kw): """ Verify that the marketing slug is not empty if the user has attempted to activate an XSeries. """ if self.category == constants.ProgramCategory.XSERIES and self.status == constants.ProgramStatus.ACTIVE: if not self.marketing_slug: raise ValidationError( _("Active XSeries Programs must have a valid marketing slug." )) return super(Program, self).save(*a, **kw) class Meta(object): # pylint: disable=missing-docstring index_together = ('status', 'category') def __unicode__(self): return unicode(self.name)
def setUp(self): super(ResizingImageFieldTestCase, self).setUp() self.model_instance = mock.Mock(attr='test-attr') self.field = ResizingImageField('testing/{attr}/path', TEST_SIZES)
class ResizingImageFieldTestCase(TestCase): """ Test the behavior of the definition of our custom field in the context of a model instance. """ def setUp(self): super(ResizingImageFieldTestCase, self).setUp() self.model_instance = mock.Mock(attr='test-attr') self.field = ResizingImageField('testing/{attr}/path', TEST_SIZES) def test_generate_filename(self): """ Ensure that the path_template is used to generate filenames correctly. """ self.assertEqual( self.field.generate_filename(self.model_instance, 'test-filename'), 'testing/test-attr/path/test-filename' ) @mock.patch(PATCH_MODULE + '.validate_image_type') @mock.patch(PATCH_MODULE + '.validate_image_size') @ddt.data( (None, False), ('test-filename', False), ('test-filename', True), ) @ddt.unpack def test_pre_save(self, filename, is_existing_file, mock_validate_size, mock_validate_type): """ Ensure that image validation and resizing take place only when a new file is being stored. """ # pylint: disable=too-many-function-args field_value = ResizingImageFieldFile(self.model_instance, self.field, filename) self.model_instance.resized_image = field_value self.field.attname = 'resized_image' self.field.name = 'resized_image' with mock.patch(PATCH_MODULE + '.ResizingImageFieldFile.create_resized_copies') as mock_resize: # actual file data is needed for this test to work with make_uploaded_file('image/jpeg', (1000, 1000)) as image_file: if filename: field_value.file = image_file field_value._committed = is_existing_file # pylint: disable=protected-access self.field.pre_save(self.model_instance, False) expected_called = bool(filename) and not is_existing_file for actual_called in (mock_validate_size.called, mock_validate_type.called, mock_resize.called): self.assertEqual(actual_called, expected_called) def test_upload_to(self): """ Ensure that the field cannot be initialized with a callable `upload_to` as this will break the filename-generation template logic. """ def dummy_upload_to(instance, filename): # pylint: disable=missing-docstring, unused-argument return 'foo' with self.assertRaises(Exception) as exc_context: self.field = ResizingImageField('testing/{attr}/path', TEST_SIZES, upload_to=dummy_upload_to) self.assertEquals( exc_context.exception.message, 'ResizingImageField does not support passing a custom callable for the `upload_to` keyword arg.', )
def setUp(self): super(ResizingImageFieldFileTestCase, self).setUp() self.model_instance = mock.Mock() self.field = ResizingImageField('test-path', TEST_SIZES)
class ResizingImageFieldTestCase(TestCase): """ Test the behavior of the definition of our custom field in the context of a model instance. """ def setUp(self): super(ResizingImageFieldTestCase, self).setUp() self.model_instance = mock.Mock(attr='test-attr') self.field = ResizingImageField('testing/{attr}/path', TEST_SIZES) def test_generate_filename(self): """ Ensure that the path_template is used to generate filenames correctly. """ self.assertEqual( self.field.generate_filename(self.model_instance, 'test-filename'), 'testing/test-attr/path/test-filename') @mock.patch(PATCH_MODULE + '.validate_image_type') @mock.patch(PATCH_MODULE + '.validate_image_size') @ddt.data( (None, False), ('test-filename', False), ('test-filename', True), ) @ddt.unpack def test_pre_save(self, filename, is_existing_file, mock_validate_size, mock_validate_type): """ Ensure that image validation and resizing take place only when a new file is being stored. """ # pylint: disable=too-many-function-args field_value = ResizingImageFieldFile(self.model_instance, self.field, filename) self.model_instance.resized_image = field_value self.field.attname = 'resized_image' self.field.name = 'resized_image' with mock.patch(PATCH_MODULE + '.ResizingImageFieldFile.create_resized_copies' ) as mock_resize: # actual file data is needed for this test to work with make_uploaded_file('image/jpeg', (1000, 1000)) as image_file: if filename: field_value.file = image_file field_value._committed = is_existing_file # pylint: disable=protected-access self.field.pre_save(self.model_instance, False) expected_called = bool(filename) and not is_existing_file for actual_called in (mock_validate_size.called, mock_validate_type.called, mock_resize.called): self.assertEqual(actual_called, expected_called) def test_upload_to(self): """ Ensure that the field cannot be initialized with a callable `upload_to` as this will break the filename-generation template logic. """ def dummy_upload_to(instance, filename): # pylint: disable=missing-docstring, unused-argument return 'foo' with self.assertRaises(Exception) as exc_context: self.field = ResizingImageField('testing/{attr}/path', TEST_SIZES, upload_to=dummy_upload_to) self.assertEquals( exc_context.exception.message, 'ResizingImageField does not support passing a custom callable for the `upload_to` keyword arg.', )