def favicon_url(): reload_maybe() # used in celery tasks, so needs config loaded if config.hs_favicon: # favicon = get_object_or_404(ImageResource, pk=config.hs_favicon) return config.hs_favicon.image.url else: return static('icon/favicon.ico')
def notify_user_order_collected(order_id): order = Order.objects.get(id=order_id) site = get_site_for_order(order) send_sms( order.phone, "Заказ №%s собран и ожидает оплаты. Перейдите по ссылке, чтобы оплатить заказ: https://%s%s" % (order_id, site.domain, reverse('shop:order', args=[order_id]))) if order.email: if not validate_email(order.email): return reload_maybe() context = { 'site': site, 'site_profile': SiteProfile.objects.get(site=site), 'owner_info': getattr(settings, 'SHOP_OWNER_INFO', {}), 'order': order } msg_plain = render_to_string('mail/shop/order_collected.txt', context) msg_html = render_to_string('mail/shop/order_collected.html', context) return send_mail( 'Оплата заказа №%s' % order_id, msg_plain, config.sw_email_from, [order.email], html_message=msg_html, )
def test_config_load(self): """ Load initial configuration into the cache """ djconfig.register(FooForm) djconfig.reload_maybe() keys = ['boolean', 'boolean_false', 'char', 'email', 'float_number', 'integer', 'url', 'choices', 'model_choices', 'model_m_choices', 'image', 'file'] values = {k: getattr(config, k) for k in keys} self.assertDictEqual( values, { 'boolean': True, 'boolean_false': False, 'char': "foo", 'email': "*****@*****.**", 'float_number': 1.23, 'integer': 123, 'url': "foo.com/", 'choices': None, 'model_choices': None, 'model_m_choices': None, 'image': None, 'file': None } )
def setUp(self): djconfig.reload_maybe() # https://github.com/nitely/django-djconfig/issues/31#issuecomment-451587942 User = get_user_model() self.teacher = Recipe(User, is_staff=True).make() # need a teacher or student creation will fail. self.student = mommy.make(User) self.submission = mommy.make(QuestSubmission, quest__name="Test")
def test_config_middleware_process_request(self): """ config middleware, reload cache """ ConfigModel.objects.create(key="char", value="foo") djconfig.register(BarForm) djconfig.reload_maybe() config._set('char', None) # Should not reload since _updated_at does not exists (form was not saved) middleware = DjConfigMiddleware() middleware.process_request(request=None) self.assertIsNone(config._cache.get('char')) # Changing _updated_at should make it reload ConfigModel.objects.create(key="_updated_at", value="111") middleware.process_request(request=None) self.assertEqual(config._cache.get('char'), "foo") self.assertEqual(config._cache.get("_updated_at"), "111") # It does not update again, since _updated_at has not changed ConfigModel.objects.filter(key="char").update(value="bar") middleware.process_request(request=None) self.assertNotEqual(config._cache.get('char'), "bar") self.assertEqual(config._cache.get("_updated_at"), "111") # Changing _updated_at should make it reload ConfigModel.objects.filter(key="_updated_at").update(value="222") middleware.process_request(request=None) self.assertEqual(config._cache.get('char'), "bar") self.assertEqual(config._cache.get("_updated_at"), "222")
def send_announcement_emails(content, url): reload_maybe() # needed for automated user: hs_hackerspace_ai users_to_email = User.objects.filter( is_active=True, profile__get_announcements_by_email=True).exclude( email='').values_list('email', flat=True) print(config) subject = '{} Announcement'.format(config.hs_site_name_short) text_content = content html_template = get_template('announcements/email_announcement.html') html_content = html_template.render({ 'content': content, 'absolute_url': url, 'domain': Site.objects.get_current().domain }) email_msg = EmailMultiAlternatives(subject, body=text_content, to=['*****@*****.**'], bcc=users_to_email) email_msg.attach_alternative(html_content, "text/html") email_msg.send()
def notify_user_order_delivered(order_id): order = Order.objects.get(id=order_id) if order.delivery == Order.DELIVERY_PICKPOINT: title = 'PickPoint' else: title = 'ТК' send_sms( order.phone, "Заказ №%s доставлен в %s: %s" % (order_id, title, order.delivery_info)) if order.email: if not validate_email(order.email): return site = get_site_for_order(order) reload_maybe() context = { 'site': site, 'site_profile': SiteProfile.objects.get(site=site), 'owner_info': getattr(settings, 'SHOP_OWNER_INFO', {}), 'order': order } msg_plain = render_to_string('mail/shop/order_delivered.txt', context) msg_html = render_to_string('mail/shop/order_delivered.html', context) return send_mail( 'Получение заказа №%s' % order_id, msg_plain, config.sw_email_from, [order.email], html_message=msg_html, )
def site_logo_url(): reload_maybe() # used in celery tasks, so needs config loaded if config.hs_site_logo: site_logo = get_object_or_404(ImageResource, pk=config.hs_site_logo) return site_logo.image.url else: return static('img/default_icon.png')
def test_config_load_unicode(self): """ Load configuration into the cache """ ConfigModel.objects.create(key='char', value=u"áéíóú") djconfig.register(FooForm) djconfig.reload_maybe() self.assertEqual(config.char, u"áéíóú")
def test_config_load_from_database_invalid(self): """ Load initial if the db value is invalid """ ConfigModel.objects.create(key='integer', value="string") djconfig.register(FooForm) djconfig.reload_maybe() self.assertEqual(config.integer, 123)
def test_config_form_initial(self): """ config form, populate initial data """ djconfig.register(BarForm) djconfig.reload_maybe() form = BarForm() self.assertEqual(form.initial['char'], 'foo')
def test_config_reload_maybe(self): """ Reload if not loaded """ self.assertRaises(AttributeError, lambda: config.char) djconfig.register(FooForm) self.assertRaises(AttributeError, lambda: config.char) djconfig.reload_maybe() self.assertEqual(config.char, "foo")
def update_1c_stocks(self): reload_maybe() filename = 'ВыгрузкаНаСайтПоВсемСкладам.csv' url = 'https://cloud-api.yandex.net/v1/disk/resources?path={}'.format( quote('disk:/' + filename)) headers = { 'Authorization': 'OAuth {token}'.format(token=config.sw_bonuses_ydisk_token), 'Content-Type': 'application/json; charset=utf-8' } request = Request(url, None, headers) try: response = urlopen(request) result = json.loads(response.read().decode('utf-8')) bonus_file = result.get('file', None) bonus_md5 = result.get('md5', None) modified = result.get('modified', None) if not bonus_file: log.error('No file') raise self.retry(countdown=600, max_retries=4) # 10 minutes import_dir = getattr(settings, 'SHOP_IMPORT_DIRECTORY', 'import') filepath = os.path.join(import_dir, filename) if modified: mdate = dateparse.parse_datetime(modified) fdate = timezone.make_aware( datetime.fromtimestamp(os.path.getmtime(filepath))) if mdate < fdate: log.info( 'File is not modified since last update: {} < {}'.format( mdate, fdate)) return None log.info('Getting file %s' % bonus_file) request = Request(bonus_file, None, headers) response = urlopen(request) result = response.read() md5 = hashlib.md5(result).hexdigest() if md5 != bonus_md5: log.error('MD5 checksums differ') raise self.retry(countdown=600, max_retries=4) # 10 minutes f = open(filepath, 'wb') f.write(result) f.close() import1c.delay(filename) return modified except HTTPError as e: content = e.read() error = json.loads(content.decode('utf-8')) message = error.get( 'message', 'Неизвестная ошибка взаимодействия с Яндекс.Диском') log.error(message) raise self.retry(countdown=600, max_retries=12, exc=e) # 10 minutes return 0
def notify_review_posted(review_id): review = reviews.get_review_model().objects.get(id=review_id) reload_maybe() msg_plain = render_to_string('mail/reviews/review_posted.txt', {'review': review}) return send_mail('Новый обзор для %s' % review.content_object, msg_plain, config.sw_email_from, [manager_tuple[1] for manager_tuple in settings.MANAGERS])
def setUp(self): djconfig.reload_maybe( ) # https://github.com/nitely/django-djconfig/issues/31#issuecomment-451587942 User = get_user_model() self.teacher = Recipe(User, is_staff=True).make( ) # need a teacher or student creation will fail. self.user = mommy.make(User) # Profiles are created automatically with each user, so we only need to access profiles via users self.profile = self.user.profile
def save_announcement_signal(sender, instance, **kwargs): """ After an announcement is saves, check if it's a draft and that it should auto-publish the results. If it should, then check if there is already a beat task scheduled and replace it, or create a new schedule """ task_name = "Autopublication task for announcement #{}".format(instance.id) if instance.draft and instance.auto_publish: reload_maybe() # djconfig for "AI" user sending_user, _ = User.objects.get_or_create( pk=config.hs_hackerspace_ai, defaults={ 'username': "******", 'password': "******", }, ) schedule, _ = ClockedSchedule.objects.get_or_create( clocked_time=instance.datetime_released) # PeriodicTask doesn't have an update_or_create method for some reason, so do it long way # https://github.com/celery/django-celery-beat/issues/106 defaults = { 'clocked': schedule, 'task': 'announcements.tasks.publish_announcement', 'queue': 'default', 'kwargs': json.dumps({ # beat needs json serializable args, so make sure they are 'user_id': sending_user.id, 'announcement_id': instance.id, 'absolute_url': instance.get_absolute_url(), }), 'one_off': True, 'enabled': True, } try: task = PeriodicTask.objects.get(name=task_name) for key, value in defaults.items(): setattr(task, key, value) task.save() except PeriodicTask.DoesNotExist: new_values = {'name': task_name} new_values.update(defaults) task = PeriodicTask(**new_values) task.save() else: # There shouldn't be a task so delete if it exists try: task = PeriodicTask.objects.get(name=task_name) task.delete() except PeriodicTask.DoesNotExist: pass
def _notify_comment(comment_id, site, subject, template, action): if settings.ST_TASK_MANAGER is None: return djconfig.reload_maybe() Comment = apps.get_model('spirit_comment.Comment') Notification = apps.get_model( 'spirit_topic_notification.TopicNotification') UserProfile = apps.get_model('spirit_user.UserProfile') Notify = UserProfile.Notify comment = (Comment.objects.select_related('user__st', 'topic').get(pk=comment_id)) actions = {'mention': Notification.MENTION, 'reply': Notification.COMMENT} notify = {'mention': Notify.MENTION, 'reply': Notify.REPLY} notifications = (Notification.objects.exclude( user_id=comment.user_id).filter( topic_id=comment.topic_id, comment_id=comment_id, is_read=False, is_active=True, action=actions[action], user__st__notify__in=[ Notify.IMMEDIATELY | notify[action], Notify.IMMEDIATELY | Notify.MENTION | Notify.REPLY ]).order_by('-pk').only('user_id', 'user__email')) # Since this is a task, the default language will # be used; we don't know what language each user prefers # XXX auto save user prefer/browser language in some field subject = subject.format(user=comment.user.st.nickname, topic=comment.topic.title) with mail.get_connection() as connection: for n in notifications.iterator(chunk_size=2000): unsub_token = tokens.unsub_token(n.user_id) message = render_to_string( template, { 'site': site, 'site_name': djconfig.config.site_name, 'comment_id': comment_id, 'user_id': n.user_id, 'unsub_token': unsub_token }) unsub = ''.join((site, reverse('spirit:user:unsubscribe', kwargs={ 'pk': n.user_id, 'token': unsub_token }))) try: _send_email(subject, message, to=n.user.email, unsub=unsub, conn=connection) except OSError as err: logger.exception(err) return # bail out
def test_config_form_auto_populate(self): """ config form, populate initial data, load the config if it's not loaded """ ConfigModel.objects.create(key="char", value="foo2") djconfig.register(BarForm) djconfig.reload_maybe() form = BarForm() self.assertEqual(form.initial['char'], 'foo2')
def test_config_form_allow_initial_overwrite(self): """ config form, allow user to pass initial data """ djconfig.register(BarForm) djconfig.reload_maybe() config._set("char", "foo2") form = BarForm(initial={'char': 'bar', 'email': '*****@*****.**'}) self.assertEqual(form.initial['char'], 'foo2') self.assertEqual(form.initial['email'], '*****@*****.**')
def test_config_load_from_database(self): """ Load configuration into the cache """ model_choice = ChoiceModel.objects.create(name='A') model_choice_b = ChoiceModel.objects.create(name='B') data = [ ConfigModel(key='boolean', value=False), ConfigModel(key='boolean_false', value=True), ConfigModel(key='float_number', value=2.1), ConfigModel(key='char', value="foo2"), ConfigModel(key='email', value="*****@*****.**"), ConfigModel(key='integer', value=321), ConfigModel(key='url', value="foo2.com/"), ConfigModel(key='choices', value='1'), ConfigModel(key='model_choices', value=model_choice.pk), ConfigModel(key='model_m_choices', value=utils.serialize( ChoiceModel.objects.filter(pk=model_choice_b.pk), forms.ModelMultipleChoiceField(None))), ConfigModel(key='image', value='path/image.gif'), ConfigModel(key='file', value='path/file.zip') ] ConfigModel.objects.bulk_create(data) djconfig.register(FooForm) djconfig.reload_maybe() keys = ['boolean', 'boolean_false', 'char', 'email', 'float_number', 'integer', 'url', 'choices', 'model_choices', 'model_m_choices', 'image', 'file'] values = {k: getattr(config, k) for k in keys} self.assertDictEqual( values, { 'boolean': False, 'boolean_false': True, 'float_number': 2.1, 'char': "foo2", 'email': "*****@*****.**", 'integer': 321, 'url': "http://foo2.com/", 'choices': '1', 'model_choices': model_choice, 'model_m_choices': [model_choice_b], 'image': 'path/image.gif', 'file': 'path/file.zip' } ) # use initial if the field is not found in the db ConfigModel.objects.get(key='char').delete() config._reset() djconfig.register(FooForm) djconfig.reload_maybe() self.assertEqual(config.char, "foo")
def test_image_save_form_conf(self): """ Should save the path after storing the image """ djconfig.register(ImageForm) djconfig.reload_maybe() self.assertFalse(ConfigModel.objects.filter(key="image").exists()) form = ImageForm(files={'image': make_dummy_image()}) self.assertTrue(form.is_valid()) form.save_image() form.save() qs = ConfigModel.objects.get(key="image") self.assertEqual(qs.value, "foo_saved.gif")
def send_notifications(user_id, announcement_id): djconfig.reload_maybe() # needed for automated user: hs_hackerspace_ai announcement = get_object_or_404(Announcement, pk=announcement_id) sending_user = User.objects.get(id=user_id) affected_users = CourseStudent.objects.all_users_for_active_semester() notify.send( sending_user, # action=new_announcement, target=announcement, recipient=sending_user, affected_users=affected_users, icon="<i class='fa fa-lg fa-fw fa-newspaper-o text-info'></i>", verb='posted')
def send_sms(phone, message): reload_maybe() sms_client = None if config.sw_sms_provider == 'sms_uslugi': sms_login = getattr(settings, 'SMS_USLUGI_LOGIN', None) sms_password = getattr(settings, 'SMS_USLUGI_PASSWORD', None) sms_client = sms_uslugi.Client(sms_login, sms_password) if config.sw_sms_provider == 'smsru': smsru_key = getattr(settings, 'SMSRU_KEY', None) sms_client = smsru.Client(smsru_key) if sms_client is None: raise ImproperlyConfigured("Required setting SMS_PROVIDER should be one of ('sms_uslugi', 'smsru')") return sms_client.send(phone, message)
def test_config_load_updated_at(self): """ Load updated_at """ djconfig.register(FooForm) djconfig.reload_maybe() self.assertIsNone(config._updated_at) ConfigModel.objects.create(key="_updated_at", value="string") config._reset() djconfig.register(FooForm) djconfig.reload_maybe() self.assertEqual(config._updated_at, "string")
def setUp(self): djconfig.reload_maybe( ) # https://github.com/nitely/django-djconfig/issues/31#issuecomment-451587942 User = get_user_model() self.teacher = Recipe(User, is_staff=True).make( ) # need a teacher or student creation will fail. self.student = mommy.make(User) self.assertion = mommy.make(BadgeAssertion) self.badge = Recipe(Badge, xp=20).make() self.badge_assertion_recipe = Recipe(BadgeAssertion, user=self.student, badge=self.badge)
def print_document(self, request, id): if not request.user.is_staff: raise PermissionDenied reload_maybe() context = self.admin_site.each_context(request) context['opts'] = self.model._meta context['is_popup'] = request.GET.get('_popup', 0) context['act'] = Act.objects.get(pk=id) context['owner_info'] = getattr(settings, 'SHOP_OWNER_INFO', {}) context['beru_delivery'] = config.sw_beru_delivery return TemplateResponse(request, 'shop/act/document.html', context)
def setUp(self): djconfig.reload_maybe() # https://github.com/nitely/django-djconfig/issues/31#issuecomment-451587942 User = get_user_model() # need a teacher and a student with known password so tests can log in as each, or could use force_login()? self.test_password = "******" # need a teacher before students can be created or the profile creation will fail when trying to notify self.test_teacher = User.objects.create_user('test_teacher', password=self.test_password, is_staff=True) self.test_student1 = User.objects.create_user('test_student', password=self.test_password) self.test_student2 = mommy.make(User) self.test_notification = mommy.make(Notification)
def notify_weekly(): from django.contrib.auth import get_user_model djconfig.reload_maybe() Notification = apps.get_model( 'spirit_topic_notification.TopicNotification') UserProfile = apps.get_model('spirit_user.UserProfile') Notify = UserProfile.Notify User = get_user_model() users = (User.objects.filter( Q(st__notify__in=[ Notify.WEEKLY | Notify.MENTION, Notify.WEEKLY | Notify.MENTION | Notify.REPLY ], st_topic_notifications__action=Notification.MENTION) | Q(st__notify__in=[ Notify.WEEKLY | Notify.REPLY, Notify.WEEKLY | Notify.MENTION | Notify.REPLY ], st_topic_notifications__action=Notification.COMMENT), st_topic_notifications__is_read=False, st_topic_notifications__is_active=True).order_by('-pk').only( 'pk', 'email').distinct()) subject = _('New notifications') site = site_url() with mail.get_connection() as connection: for u in users.iterator(chunk_size=2000): unsub_token = tokens.unsub_token(u.pk) message = render_to_string( 'spirit/topic/notification/email_notification_weekly.html', { 'site': site, 'site_name': djconfig.config.site_name, 'user_id': u.pk, 'unsub_token': unsub_token }) unsub = ''.join((site, reverse('spirit:user:unsubscribe', kwargs={ 'pk': u.pk, 'token': unsub_token }))) try: _send_email(subject, message, to=u.email, unsub=unsub, conn=connection) except OSError as err: logger.exception(err) return # bail out
def test_file_form_conf(self): """ Should save the file path """ djconfig.register(FileForm) djconfig.reload_maybe() self.assertFalse(ConfigModel.objects.filter(key="file").exists()) form = FileForm(files={'file': make_dummy_image()}) self.assertTrue(form.is_valid()) form.save() qs = ConfigModel.objects.get(key="file") self.assertEqual(qs.value, "image.gif") form = FileForm(files={'file': None}) self.assertTrue(form.is_valid()) qs = ConfigModel.objects.get(key="file") self.assertEqual(qs.value, "image.gif")
def setUp(self): djconfig.reload_maybe() # https://github.com/nitely/django-djconfig/issues/31#issuecomment-451587942 User = get_user_model() # need a teacher and a student with known password so tests can log in as each, or could use force_login()? self.test_password = "******" # need a teacher before students can be created or the profile creation will fail when trying to notify self.test_teacher = User.objects.create_user('test_teacher', password=self.test_password, is_staff=True) self.test_student1 = User.objects.create_user('test_student', password=self.test_password) self.test_student2 = mommy.make(User) # create semester with pk of default semester # this seems backward, but no semesters should exist yet in the test, so their shouldn't be any conflicts. self.active_sem = mommy.make(Semester, pk=djconfig.config.hs_active_semester)