class HttpHttpsOnlyURLFieldTestCase(TestCase): def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() self.field = HttpHttpsOnlyURLField() def test_invalid_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'javascript://foo.com/') def test_invalid_ftp_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftp://foo.com/') def test_invalid_ftps_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftps://foo.com/') def test_no_scheme_assumes_http(self): assert self.field.clean(u'foo.com') == 'http://foo.com' def test_http_scheme(self): assert self.field.clean(u'http://foo.com/') == u'http://foo.com/' def test_https_scheme(self): assert self.field.clean(u'https://foo.com/') == u'https://foo.com/' def test_catches_invalid_url(self): # https://github.com/mozilla/addons-server/issues/1452 with self.assertRaises(exceptions.ValidationError): assert self.field.clean(u'https://test.[com')
class HttpHttpsOnlyURLFieldTestCase(TestCase): def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() self.field = HttpHttpsOnlyURLField() def test_invalid_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'javascript://foo.com/') def test_invalid_ftp_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftp://foo.com/') def test_invalid_ftps_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftps://foo.com/') def test_no_scheme_assumes_http(self): assert self.field.clean(u'foo.com') == 'http://foo.com' def test_http_scheme(self): assert self.field.clean(u'http://foo.com/') == u'http://foo.com/' def test_https_scheme(self): assert self.field.clean(u'https://foo.com/') == u'https://foo.com/' def test_catches_invalid_url(self): # https://github.com/mozilla/addons-server/issues/1452 with self.assertRaises(exceptions.ValidationError): assert self.field.clean(u'https://test.[com')
class HttpHttpsOnlyURLFieldTestCase(TestCase): def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() self.field = HttpHttpsOnlyURLField() def test_invalid_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'javascript://foo.com/') def test_invalid_ftp_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftp://foo.com/') def test_invalid_ftps_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftps://foo.com/') def test_no_scheme_assumes_http(self): assert self.field.clean(u'foo.com') == 'http://foo.com/' def test_http_scheme(self): assert self.field.clean(u'http://foo.com/') == u'http://foo.com/' def test_https_scheme(self): assert self.field.clean(u'https://foo.com/') == u'https://foo.com/'
class HttpHttpsOnlyURLFieldTestCase(TestCase): def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() self.field = HttpHttpsOnlyURLField() def test_invalid_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'javascript://foo.com/') def test_invalid_ftp_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftp://foo.com/') def test_invalid_ftps_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftps://foo.com/') def test_no_scheme_assumes_http(self): assert self.field.clean(u'foo.com') == 'http://foo.com/' def test_http_scheme(self): assert self.field.clean(u'http://foo.com/') == u'http://foo.com/' def test_https_scheme(self): assert self.field.clean(u'https://foo.com/') == u'https://foo.com/'
class AddonFormBasic(AddonFormBase): name = TransField(max_length=50) slug = forms.CharField(max_length=30) summary = TransField(widget=TransTextarea(attrs={'rows': 4}), max_length=250) tags = forms.CharField(required=False) contributions = HttpHttpsOnlyURLField(required=False, max_length=255) is_experimental = forms.BooleanField(required=False) requires_payment = forms.BooleanField(required=False) class Meta: model = Addon fields = ('name', 'slug', 'summary', 'tags', 'is_experimental', 'requires_payment', 'contributions') def __init__(self, *args, **kw): super(AddonFormBasic, self).__init__(*args, **kw) if self.fields.get('tags'): self.fields['tags'].initial = ', '.join( self.get_tags(self.instance)) def clean_slug(self): return clean_addon_slug(self.cleaned_data['slug'], self.instance) def clean_contributions(self): if self.cleaned_data['contributions']: hostname = urlsplit(self.cleaned_data['contributions']).hostname if not hostname.endswith(amo.VALID_CONTRIBUTION_DOMAINS): raise forms.ValidationError( ugettext('URL domain must be one of [%s], or a subdomain.') % ', '.join(amo.VALID_CONTRIBUTION_DOMAINS)) return self.cleaned_data['contributions'] def save(self, addon, commit=False): if self.fields.get('tags'): tags_new = self.cleaned_data['tags'] tags_old = [slugify(t, spaces=True) for t in self.get_tags(addon)] # Add new tags. for t in set(tags_new) - set(tags_old): Tag(tag_text=t).save_tag(addon) # Remove old tags. for t in set(tags_old) - set(tags_new): Tag(tag_text=t).remove_tag(addon) # We ignore `commit`, since we need it to be `False` so we can save # the ManyToMany fields on our own. addonform = super(AddonFormBasic, self).save(commit=False) addonform.save() return addonform
class UserRegisterForm(happyforms.ModelForm, UsernameMixin): """ For registering users. We're not building off d.contrib.auth.forms.UserCreationForm because it doesn't do a lot of the details here, so we'd have to rewrite most of it anyway. """ username = forms.CharField(max_length=50, required=False) email = forms.EmailField(widget=RequiredEmailInput) display_name = forms.CharField(label=_lazy(u'Display Name'), max_length=50, required=False) location = forms.CharField(label=_lazy(u'Location'), max_length=100, required=False) occupation = forms.CharField(label=_lazy(u'Occupation'), max_length=100, required=False) recaptcha = ReCaptchaField() homepage = HttpHttpsOnlyURLField(label=_lazy(u'Homepage'), required=False) class Meta: model = UserProfile fields = ('username', 'display_name', 'location', 'occupation', 'recaptcha', 'homepage', 'email') def __init__(self, *args, **kwargs): instance = kwargs.get('instance') if instance and instance.has_anonymous_username(): kwargs.setdefault('initial', {}) kwargs['initial']['username'] = '' super(UserRegisterForm, self).__init__(*args, **kwargs) if not settings.NOBOT_RECAPTCHA_PRIVATE_KEY: del self.fields['recaptcha'] errors = { 'invalid': _('This URL has an invalid format. ' 'Valid URLs look like ' 'http://example.com/my_page.') } self.fields['homepage'].error_messages = errors def clean_display_name(self): name = self.cleaned_data['display_name'] if BlacklistedName.blocked(name): raise forms.ValidationError(_('This display name cannot be used.')) return name
class UserRegisterForm(happyforms.ModelForm, UsernameMixin, PasswordMixin): """ For registering users. We're not building off d.contrib.auth.forms.UserCreationForm because it doesn't do a lot of the details here, so we'd have to rewrite most of it anyway. """ username = forms.CharField(max_length=50, required=False) email = forms.EmailField(widget=RequiredEmailInput) display_name = forms.CharField(label=_lazy(u'Display Name'), max_length=50, required=False) location = forms.CharField(label=_lazy(u'Location'), max_length=100, required=False) occupation = forms.CharField(label=_lazy(u'Occupation'), max_length=100, required=False) password = forms.CharField(max_length=255, min_length=PasswordMixin.min_length, error_messages=PasswordMixin.error_msg, widget=PasswordMixin.widget(render_value=False, required=True)) password2 = forms.CharField(max_length=255, widget=PasswordMixin.widget(render_value=False, required=True)) recaptcha = ReCaptchaField() homepage = HttpHttpsOnlyURLField(label=_lazy(u'Homepage'), required=False) class Meta: model = UserProfile fields = ('username', 'display_name', 'location', 'occupation', 'password', 'password2', 'recaptcha', 'homepage', 'email') def __init__(self, *args, **kwargs): instance = kwargs.get('instance') if instance and instance.has_anonymous_username(): kwargs.setdefault('initial', {}) kwargs['initial']['username'] = '' super(UserRegisterForm, self).__init__(*args, **kwargs) if not settings.NOBOT_RECAPTCHA_PRIVATE_KEY: del self.fields['recaptcha'] errors = { 'invalid': _('This URL has an invalid format. ' 'Valid URLs look like ' 'http://example.com/my_page.') } self.fields['homepage'].error_messages = errors def clean_email(self): d = self.cleaned_data['email'].split('@')[-1] if BlacklistedEmailDomain.blocked(d): raise forms.ValidationError( _('Please use an email address from a ' 'different provider to complete ' 'your registration.')) return self.cleaned_data['email'] def clean_display_name(self): name = self.cleaned_data['display_name'] if BlacklistedName.blocked(name): raise forms.ValidationError(_('This display name cannot be used.')) return name def clean(self): super(UserRegisterForm, self).clean() data = self.cleaned_data # Passwords p1 = data.get('password') p2 = data.get('password2') # If p1 is invalid because its blocked, this message is non sensical. if p1 and p1 != p2: msg = _('The passwords did not match.') self._errors['password2'] = ErrorList([msg]) if p2: del data['password2'] return data
class AdditionalDetailsForm(AddonFormBase): default_locale = forms.TypedChoiceField(choices=LOCALES) homepage = TransField.adapt(HttpHttpsOnlyURLField)(required=False) tags = forms.CharField(required=False) contributions = HttpHttpsOnlyURLField(required=False, max_length=255) class Meta: model = Addon fields = ('default_locale', 'homepage', 'tags', 'contributions') def __init__(self, *args, **kw): super(AdditionalDetailsForm, self).__init__(*args, **kw) if self.fields.get('tags'): self.fields['tags'].initial = ', '.join( self.get_tags(self.instance)) def clean_contributions(self): if self.cleaned_data['contributions']: hostname = urlsplit(self.cleaned_data['contributions']).hostname if not hostname.endswith(amo.VALID_CONTRIBUTION_DOMAINS): raise forms.ValidationError(ugettext( 'URL domain must be one of [%s], or a subdomain.' ) % ', '.join(amo.VALID_CONTRIBUTION_DOMAINS)) return self.cleaned_data['contributions'] def clean(self): # Make sure we have the required translations in the new locale. required = 'name', 'summary', 'description' if not self.errors and 'default_locale' in self.changed_data: fields = dict((k, getattr(self.instance, k + '_id')) for k in required) locale = self.cleaned_data['default_locale'] ids = filter(None, fields.values()) qs = (Translation.objects.filter(locale=locale, id__in=ids, localized_string__isnull=False) .values_list('id', flat=True)) missing = [k for k, v in fields.items() if v not in qs] if missing: raise forms.ValidationError(ugettext( 'Before changing your default locale you must have a ' 'name, summary, and description in that locale. ' 'You are missing %s.') % ', '.join(map(repr, missing))) return super(AdditionalDetailsForm, self).clean() def save(self, addon, commit=False): if self.fields.get('tags'): tags_new = self.cleaned_data['tags'] tags_old = [slugify(t, spaces=True) for t in self.get_tags(addon)] # Add new tags. for t in set(tags_new) - set(tags_old): Tag(tag_text=t).save_tag(addon) # Remove old tags. for t in set(tags_old) - set(tags_new): Tag(tag_text=t).remove_tag(addon) # We ignore `commit`, since we need it to be `False` so we can save # the ManyToMany fields on our own. addonform = super(AdditionalDetailsForm, self).save(commit=False) addonform.save() return addonform
def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() self.field = HttpHttpsOnlyURLField()
class UserEditForm(happyforms.ModelForm): username = forms.CharField(max_length=50, required=False) display_name = forms.CharField(label=_(u'Display Name'), max_length=50, required=False) location = forms.CharField(label=_(u'Location'), max_length=100, required=False) occupation = forms.CharField(label=_(u'Occupation'), max_length=100, required=False) homepage = HttpHttpsOnlyURLField(label=_(u'Homepage'), required=False) email = forms.EmailField( required=False, help_text=fxa_error_message( _(u'You can change your email address on Firefox Accounts.'), LOGIN_HELP_URL), widget=forms.EmailInput(attrs={'readonly': 'readonly'})) photo = forms.FileField(label=_(u'Profile Photo'), required=False) biography = forms.CharField(widget=forms.Textarea, required=False) notifications = forms.MultipleChoiceField( choices=[], widget=NotificationsSelectMultiple, initial=notifications.NOTIFICATIONS_DEFAULT, required=False) def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) instance = kwargs.get('instance') if instance and instance.has_anonymous_username: kwargs.setdefault('initial', {}) kwargs['initial']['username'] = '' super(UserEditForm, self).__init__(*args, **kwargs) errors = { 'invalid': ugettext('This URL has an invalid format. Valid URLs look like ' 'http://example.com/my_page.') } self.fields['homepage'].error_messages = errors if self.instance: # We are fetching all `UserNotification` instances and then, # if the waffle-switch is active overwrite their value with the # data from basket. This simplifies the process of implementing # the waffle-switch. Once we switched the integration "on" on prod # all `UserNotification` instances that are now handled by basket # can be deleted. default = { idx: notification.default_checked for idx, notification in notifications.NOTIFICATIONS_BY_ID.items() } user = { notification.notification_id: notification.enabled for notification in self.instance.notifications.all() } default.update(user) if waffle.switch_is_active('activate-basket-sync'): newsletters = fetch_subscribed_newsletters(self.instance) by_basket_id = notifications.REMOTE_NOTIFICATIONS_BY_BASKET_ID for basket_id, notification in by_basket_id.items(): default[notification.id] = basket_id in newsletters # Add choices to Notification. if self.instance.is_developer: choices = [(l.id, l.label) for l in notifications.NOTIFICATIONS_COMBINED] else: choices = [(l.id, l.label) for l in notifications.NOTIFICATIONS_COMBINED if l.group != 'dev'] # Append a "NEW" message to new notification options. saved = self.instance.notifications.values_list('notification_id', flat=True) self.choices_status = {} for idx, label in choices: self.choices_status[idx] = idx not in saved self.fields['notifications'].choices = choices self.fields['notifications'].initial = [ i for i, v in default.items() if v ] self.fields['notifications'].widget.form_instance = self class Meta: model = UserProfile fields = ( 'username', 'email', 'display_name', 'location', 'occupation', 'homepage', 'photo', 'biography', 'display_collections', 'display_collections_fav', 'notifications', ) def clean_username(self): name = self.cleaned_data['username'] if not name: if self.instance.has_anonymous_username: name = self.instance.username else: name = self.instance.anonymize_username() # All-digits usernames are disallowed since they can be # confused for user IDs in URLs. (See bug 862121.) if name.isdigit(): raise forms.ValidationError( ugettext('Usernames cannot contain only digits.')) slug_validator( name, lower=False, message=ugettext( 'Enter a valid username consisting of letters, numbers, ' 'underscores or hyphens.')) if DeniedName.blocked(name): raise forms.ValidationError( ugettext('This username cannot be used.')) # FIXME: Bug 858452. Remove this check when collation of the username # column is changed to case insensitive. if (UserProfile.objects.exclude(id=self.instance.id).filter( username__iexact=name).exists()): raise forms.ValidationError( ugettext('This username is already in use.')) return name def clean_display_name(self): name = self.cleaned_data['display_name'] if DeniedName.blocked(name): raise forms.ValidationError( ugettext('This display name cannot be used.')) return name def clean_email(self): # TODO(django 1.9): Change the field to disabled=True and remove this. return self.instance.email def clean_photo(self): photo = self.cleaned_data['photo'] if not photo: return image_check = ImageCheck(photo) if (photo.content_type not in amo.IMG_TYPES or not image_check.is_image()): raise forms.ValidationError( ugettext('Images must be either PNG or JPG.')) if image_check.is_animated(): raise forms.ValidationError(ugettext('Images cannot be animated.')) if photo.size > settings.MAX_PHOTO_UPLOAD_SIZE: msg = ugettext('Please use images smaller than %dMB.') size_in_mb = settings.MAX_PHOTO_UPLOAD_SIZE / 1024 / 1024 raise forms.ValidationError(msg % size_in_mb) return photo def clean_biography(self): biography = self.cleaned_data['biography'] normalized = clean_nl(unicode(biography)) if has_links(normalized): # There's some links, we don't want them. raise forms.ValidationError(ugettext('No links are allowed.')) return biography def save(self, log_for_developer=True): user = super(UserEditForm, self).save(commit=False) data = self.cleaned_data photo = data['photo'] if photo: user.picture_type = 'image/png' tmp_destination = user.picture_path_original with storage.open(tmp_destination, 'wb') as fh: for chunk in photo.chunks(): fh.write(chunk) tasks.resize_photo.delay( tmp_destination, user.picture_path, set_modified_on=user.serializable_reference()) visible_notifications = (notifications.NOTIFICATIONS_BY_ID if self.instance.is_developer else notifications.NOTIFICATIONS_BY_ID_NOT_DEV) for (notification_id, notification) in visible_notifications.items(): enabled = (notification.mandatory or (str(notification_id) in data['notifications'])) UserNotification.objects.update_or_create( user=self.instance, notification_id=notification_id, defaults={'enabled': enabled}) if waffle.switch_is_active('activate-basket-sync'): by_basket_id = notifications.REMOTE_NOTIFICATIONS_BY_BASKET_ID for basket_id, notification in by_basket_id.items(): needs_subscribe = str(notification.id) in data['notifications'] needs_unsubscribe = (str(notification.id) not in data['notifications']) if needs_subscribe: subscribe_newsletter(self.instance, basket_id, request=self.request) elif needs_unsubscribe: unsubscribe_newsletter(self.instance, basket_id) log.debug(u'User (%s) updated their profile' % user) user.save() return user
class HttpHttpsOnlyURLFieldTestCase(TestCase): domain = 'example.com' def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() with override_settings(DOMAIN=self.domain): self.field = HttpHttpsOnlyURLField() def test_invalid_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'javascript://foo.com/') def test_invalid_ftp_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftp://foo.com/') def test_invalid_ftps_scheme_validation_error(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'ftps://foo.com/') def test_no_scheme_assumes_http(self): assert self.field.clean(u'foo.com') == 'http://foo.com' def test_http_scheme(self): assert self.field.clean(u'http://foo.com/') == u'http://foo.com/' def test_https_scheme(self): assert self.field.clean(u'https://foo.com/') == u'https://foo.com/' def test_catches_invalid_url(self): # https://github.com/mozilla/addons-server/issues/1452 with self.assertRaises(exceptions.ValidationError): assert self.field.clean(u'https://test.[com') def test_with_domain_and_no_scheme(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'%s' % self.domain) def test_with_domain_and_http(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'http://%s' % self.domain) def test_with_domain_and_https(self): with self.assertRaises(exceptions.ValidationError): self.field.clean(u'https://%s' % self.domain) def test_domain_is_escaped_in_regex_validator(self): assert self.field.clean(u'example-com.fr') == u'http://example-com.fr'
def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() with override_settings(DOMAIN=self.domain): self.field = HttpHttpsOnlyURLField()
class UserEditForm(happyforms.ModelForm): username = forms.CharField(max_length=50, required=False) display_name = forms.CharField(label=_(u'Display Name'), max_length=50, required=False) location = forms.CharField(label=_(u'Location'), max_length=100, required=False) occupation = forms.CharField(label=_(u'Occupation'), max_length=100, required=False) homepage = HttpHttpsOnlyURLField(label=_(u'Homepage'), required=False) email = forms.EmailField( required=False, help_text=fxa_error_message( _(u'Firefox Accounts users cannot currently change their ' u'email address.')), widget=forms.EmailInput(attrs={'readonly': 'readonly'})) photo = forms.FileField(label=_(u'Profile Photo'), required=False) biography = forms.CharField(widget=forms.Textarea, required=False) notifications = forms.MultipleChoiceField( choices=[], widget=NotificationsSelectMultiple, initial=notifications.NOTIFICATIONS_DEFAULT, required=False) def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) instance = kwargs.get('instance') if instance and instance.has_anonymous_username(): kwargs.setdefault('initial', {}) kwargs['initial']['username'] = '' super(UserEditForm, self).__init__(*args, **kwargs) errors = { 'invalid': ugettext('This URL has an invalid format. Valid URLs look like ' 'http://example.com/my_page.') } self.fields['homepage'].error_messages = errors if self.instance: default = dict( (i, n.default_checked) for i, n in notifications.NOTIFICATIONS_BY_ID.items()) user = dict((n.notification_id, n.enabled) for n in self.instance.notifications.all()) default.update(user) # Add choices to Notification. choices = notifications.NOTIFICATIONS_CHOICES if not self.instance.is_developer: choices = notifications.NOTIFICATIONS_CHOICES_NOT_DEV # Append a "NEW" message to new notification options. saved = self.instance.notifications.values_list('notification_id', flat=True) self.choices_status = {} for idx, label in choices: self.choices_status[idx] = idx not in saved self.fields['notifications'].choices = choices self.fields['notifications'].initial = [ i for i, v in default.items() if v ] self.fields['notifications'].widget.form_instance = self class Meta: model = UserProfile fields = ( 'username', 'email', 'display_name', 'location', 'occupation', 'homepage', 'photo', 'biography', 'display_collections', 'display_collections_fav', 'notifications', ) def clean_username(self): name = self.cleaned_data['username'] if not name: if self.instance.has_anonymous_username(): name = self.instance.username else: name = self.instance.anonymize_username() # All-digits usernames are disallowed since they can be # confused for user IDs in URLs. (See bug 862121.) if name.isdigit(): raise forms.ValidationError( ugettext('Usernames cannot contain only digits.')) slug_validator( name, lower=False, message=ugettext( 'Enter a valid username consisting of letters, numbers, ' 'underscores or hyphens.')) if DeniedName.blocked(name): raise forms.ValidationError( ugettext('This username cannot be used.')) # FIXME: Bug 858452. Remove this check when collation of the username # column is changed to case insensitive. if (UserProfile.objects.exclude(id=self.instance.id).filter( username__iexact=name).exists()): raise forms.ValidationError( ugettext('This username is already in use.')) return name def clean_display_name(self): name = self.cleaned_data['display_name'] if DeniedName.blocked(name): raise forms.ValidationError( ugettext('This display name cannot be used.')) return name def clean_email(self): # TODO(django 1.9): Change the field to disabled=True and remove this. return self.instance.email def clean_photo(self): photo = self.cleaned_data['photo'] if not photo: return if photo.content_type not in ('image/png', 'image/jpeg'): raise forms.ValidationError( ugettext('Images must be either PNG or JPG.')) if photo.size > settings.MAX_PHOTO_UPLOAD_SIZE: msg = ugettext('Please use images smaller than %dMB.') size_in_mb = settings.MAX_PHOTO_UPLOAD_SIZE / 1024 / 1024 - 1 raise forms.ValidationError(msg % size_in_mb) return photo def clean_biography(self): biography = self.cleaned_data['biography'] normalized = clean_nl(unicode(biography)) if has_links(normalized): # There's some links, we don't want them. raise forms.ValidationError(ugettext('No links are allowed.')) return biography def save(self, log_for_developer=True): u = super(UserEditForm, self).save(commit=False) data = self.cleaned_data photo = data['photo'] if photo: u.picture_type = 'image/png' tmp_destination = u.picture_path + '__unconverted' with storage.open(tmp_destination, 'wb') as fh: for chunk in photo.chunks(): fh.write(chunk) tasks.resize_photo.delay(tmp_destination, u.picture_path, set_modified_on=[u]) for (i, n) in notifications.NOTIFICATIONS_BY_ID.items(): enabled = n.mandatory or (str(i) in data['notifications']) UserNotification.objects.update_or_create( user=self.instance, notification_id=i, defaults={'enabled': enabled}) log.debug(u'User (%s) updated their profile' % u) u.save() return u
def setUp(self): super(HttpHttpsOnlyURLFieldTestCase, self).setUp() self.field = HttpHttpsOnlyURLField()