def area_acres_roods_perches_textual(self): acres, roods, perches = self.area_acres_roods_perches return ", ".join([ (ungettext("%d acre", "%d acres", acres) % acres), (ungettext("%d rood", "%d roods", roods) % roods), (ungettext("%d perch", "%d perches", perches) % perches), ])
def filesizeformat(bytes): """ Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102 bytes, etc.). """ try: bytes = float(bytes) except (TypeError, ValueError, UnicodeDecodeError): value = ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0} return avoid_wrapping(value) filesize_number_format = lambda value: formats.number_format(round(value, 1), 1) KB = 1 << 10 MB = 1 << 20 GB = 1 << 30 TB = 1 << 40 PB = 1 << 50 if bytes < KB: value = ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes} elif bytes < MB: value = ugettext("%s KB") % filesize_number_format(bytes / KB) elif bytes < GB: value = ugettext("%s MB") % filesize_number_format(bytes / MB) elif bytes < TB: value = ugettext("%s GB") % filesize_number_format(bytes / GB) elif bytes < PB: value = ugettext("%s TB") % filesize_number_format(bytes / TB) else: value = ugettext("%s PB") % filesize_number_format(bytes / PB) return avoid_wrapping(value)
def _get_problem_progress(self): """ Returns a statement of progress for the XBlock, which depends on the user's current score """ if self.weight == 0: result = '' elif self.score == 0.0: result = "({})".format( ungettext( '{weight} point possible', '{weight} points possible', self.weight, ).format( weight=self.weight, ) ) else: score_string = '{0:g}'.format(self.score) result = "({})".format( ungettext( score_string + '/' + "{weight} point", score_string + '/' + "{weight} points", self.weight, ).format( weight=self.weight, ) ) return result
def get_household_summary(person, today=None, adult_age=None): """Return a string which expresses the household composition in a few words. See :ref:`welfare.specs.households` for some examples. Note that members without `birth_date` are considered as children. """ if adult_age is None: adult_age = dd.plugins.households.adult_age ar = SiblingsByPerson.request(master_instance=person) if ar.get_total_count() == 0: return ar.no_data_text if today is None: today = dd.today() adults = children = 0 for m in ar: if m.birth_date is not None and ( m.get_age(today) >= adult_age): adults += 1 else: children += 1 l = [] if adults: l.append( ungettext( "%(count)d adult", "%(count)d adults", adults) % dict( count=adults)) if children: l.append( ungettext( "%(count)d child", "%(count)d children", children) % dict( count=children)) return _(" and ").join(l)
def diff_date(date, limen=2): if not date: return _('unknown') now = datetime.datetime.now() diff = now - date days = diff.days hours = int(diff.seconds/3600) minutes = int(diff.seconds/60) if date.year != now.year: return dateformat.format(date, 'd M \'y, H:i') elif days > 2 or (limen == 0): return dateformat.format(date, 'd M, H:i') elif days == 2: return _('2 days ago') elif days == 1: return _('yesterday') elif minutes >= 60: return ungettext('%(hr)d ' + _("hour ago"), '%(hr)d ' + _("hours ago"), hours) % {'hr':hours} elif diff.seconds >= 60: return ungettext('%(min)d ' + _("min ago"), '%(min)d ' + _("mins ago"), minutes) % {'min':minutes} else: return ungettext('%(sec)d ' + _("sec ago"), '%(sec)d ' + _("secs ago"), diff.seconds) % {'sec':diff.seconds}
def natural_time(value, time_range="86400"): """ For date and time values in time_range shows how many seconds, minutes or hours ago compared to current timestamp returns representing string. """ if not isinstance(value, datetime.date): # datetime is a subclass of date return value now = datetime.datetime.now() delta_time = now + datetime.timedelta(seconds=-int(time_range)) if value > delta_time and value < now: delta = now - value if delta.days != 0: return pgettext("naturaltime", "%(delta)s ago") % {"delta": defaultfilters.timesince(value)} elif delta.seconds == 0: return _(u"now") elif delta.seconds < 60: return ungettext(u"a second ago", u"%(count)s seconds ago", delta.seconds) % {"count": delta.seconds} elif delta.seconds // 60 < 60: count = delta.seconds // 60 return ungettext(u"a minute ago", u"%(count)s minutes ago", count) % {"count": count} else: count = delta.seconds // 60 // 60 return ungettext(u"an hour ago", u"%(count)s hours ago", count) % {"count": count} else: if value.year == now.year: return datetime.datetime.strftime(value, "%m月%d日 %H:%M") else: return datetime.datetime.strftime(value, "%Y年%m月%d日 %H:%M")
def timedelta(date): """Returns a human-readable time delta, similar to Django's ``timesince`` template filter but allowing proper localizability. Adapted from http://djangosnippets.org/snippets/2275/ """ delta = timezone.now() - date num_years = delta.days / 365 if (num_years > 0): return ungettext(u"%d year ago", u"%d years ago", num_years) % num_years num_weeks = delta.days / 7 if (num_weeks > 0): return ungettext(u"%d week ago", u"%d weeks ago", num_weeks) % num_weeks if (delta.days > 0): return ungettext(u"%d day ago", u"%d days ago", delta.days) % delta.days num_hours = delta.seconds / 3600 if (num_hours > 0): return ungettext(u"%d hour ago", u"%d hours ago", num_hours) % num_hours num_minutes = delta.seconds / 60 if (num_minutes > 0): return ungettext(u"%d minute ago", u"%d minutes ago", num_minutes) % num_minutes return _(u"Few seconds ago")
def message_user(self, request, message, *args, **kwargs): # This is ugly but we do not want to touch the changelist_view() code. opts = self.model._meta conflicts = self._get_conflicts(request) if conflicts: names = force_text(opts.verbose_name), force_text(opts.verbose_name_plural) pattern = r"(?P<num>\d+) ({0}|{1})".format(*names) rex = re.compile(pattern) m = rex.match(message) concurrency_errros = len(conflicts) if m: updated_record = int(m.group('num')) - concurrency_errros ids = ",".join(map(str, conflicts)) messages.error(request, ungettext("Record with pk `{0}` has been modified and was not updated", "Records `{0}` have been modified and were not updated", concurrency_errros).format(ids)) if updated_record == 1: name = force_text(opts.verbose_name) else: name = force_text(opts.verbose_name_plural) message = None if updated_record > 0: message = ungettext("%(count)s %(name)s was changed successfully.", "%(count)s %(name)s were changed successfully.", updated_record) % {'count': updated_record, 'name': name} return super(ConcurrencyListEditableMixin, self).message_user(request, message, *args, **kwargs)
def humanize_timesince(date): if not date: return u'' if isinstance(date, basestring): # convert the date to a datetime object date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S") delta = datetime.datetime.now() - date num_years = delta.days / 365 if (num_years > 0): return ungettext(u"%d year ago", u"%d years ago", num_years) % num_years num_weeks = delta.days / 7 if (num_weeks > 0): return ungettext(u"%d week ago", u"%d weeks ago", num_weeks) % num_weeks if (delta.days > 0): return ungettext(u"%d day ago", u"%d days ago", delta.days) % delta.days num_hours = delta.seconds / 3600 if (num_hours > 0): return ungettext(u"%d hour ago", u"%d hours ago", num_hours) % num_hours num_minutes = delta.seconds / 60 if (num_minutes > 0): return ungettext(u"%d minute ago", u"%d minutes ago", num_minutes) % num_minutes return ugettext(u"just a few seconds ago")
def full_clean(self): """ Cleans all of self.data and populates self._errors and self._non_form_errors. """ self._errors = [] self._non_form_errors = self.error_class() if not self.is_bound: # Stop further processing. return for i in range(0, self.total_form_count()): form = self.forms[i] self._errors.append(form.errors) try: if (self.validate_max and self.total_form_count() - len(self.deleted_forms) > self.max_num) or \ self.management_form.cleaned_data[TOTAL_FORM_COUNT] > self.absolute_max: raise ValidationError(ungettext( "Please submit %d or fewer forms.", "Please submit %d or fewer forms.", self.max_num) % self.max_num, code='too_many_forms', ) if (self.validate_min and self.total_form_count() - len(self.deleted_forms) < self.min_num): raise ValidationError(ungettext( "Please submit %d or more forms.", "Please submit %d or more forms.", self.min_num) % self.min_num, code='too_few_forms') # Give self.clean() a chance to do cross-form validation. self.clean() except ValidationError as e: self._non_form_errors = self.error_class(e.error_list)
def recalculate_statistics_for_problem(problem): problem_statistics, created = ProblemStatistics.objects \ .select_for_update().get_or_create(problem=problem) problem_submissions = Submission.objects \ .filter(problem_instance__problem=problem) print(ungettext("\t%(count)d submission", "\t%(count)d submissions", len(problem_submissions)) % { 'count': len(problem_submissions) }) # Index this problem's submissions by users user_submissions = {} for submission in problem_submissions: if submission.user: if submission.user not in user_submissions: user_submissions[submission.user] = [] user_submissions[submission.user].append(submission) print(ungettext("\tfrom %(count)d user", "\tfrom %(count)d users", len(user_submissions)) % {'count': len(user_submissions)}) # Go over each user's submissions for this problem for user, submissions in user_submissions.items(): user_statistics, created = UserStatistics.objects \ .select_for_update() \ .get_or_create(user=user, problem_statistics=problem_statistics) for submission in submissions: submission.problem_instance.controller \ .update_problem_statistics(problem_statistics, user_statistics, submission) user_statistics.save() problem_statistics.save()
def do_commit(request, submits, user, repo_user, repo_pass, message=''): if deferredhandler.deferred_enabled: deferredhandler.add_submits(submits, user, repo_user, repo_pass, message) msg = ungettext('File added to the queue for further processing.', 'Files added to the queue for further processing.', len(submits)) messages.info(request, message=msg) else: args = {'files': submits, 'current_user': user, 'user': repo_user, 'pword': repo_pass, 'message': message} if getattr(settings, 'SUBMIT_OFFLINE', False) is True: t = threading.Thread(target=__perform_commit, name="commit_%s" % user.username, kwargs=args) t.start() msg = ungettext("The file is being processed. You'll be notified once completed.", "The files are being processed. You'll be notified once completed.", len(submits)) messages.info(request, message=msg) else: args['request'] = request return __perform_commit(args) return True
def diff_date(date, limen=2): if not date: return _('unknown') now = datetime.datetime.now() diff = now - date days = diff.days hours = int(diff.seconds/3600) minutes = int(diff.seconds/60) if days > 2: if date.year == now.year: return date.strftime(_("%b %d at %H:%M").encode()) else: return date.strftime(_("%b %d '%y at %H:%M").encode()) elif days == 2: return _('2 days ago') elif days == 1: return _('yesterday') elif minutes >= 60: return 'vor ' + ungettext('%(hr)d ' + _("hour ago"), '%(hr)d ' + _("hours ago"), hours) % {'hr':hours} elif diff.seconds >= 60: return 'vor ' + ungettext('%(min)d ' + _("min ago"), '%(min)d ' + _("mins ago"), minutes) % {'min':minutes} else: return 'vor ' + ungettext('%(sec)d ' + _("sec ago"), '%(sec)d ' + _("secs ago"), diff.seconds) % {'sec':diff.seconds}
def changelist_view(self, request, extra_context=None): if not self.has_change_permission(request, None): raise PermissionDenied if not SEARCH_VAR in request.GET: # Do the usual song and dance. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # Do a search of just this model and populate a Changelist with the # returned bits. if not self.model in site.get_indexed_models(): # Oops. That model isn't being indexed. Return the usual # behavior instead. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # So. Much. Boilerplate. # Why copy-paste a few lines when you can copy-paste TONS of lines? list_display = list(self.list_display) changelist = SearchChangeList(request, self.model, list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) formset = changelist.formset = None media = self.media # Build the action form and populate it with available actions. # Check actions to see if any are available on this changelist actions = self.get_actions(request) if actions: action_form = self.action_form(auto_id=None) action_form.fields['action'].choices = self.get_action_choices(request) else: action_form = None selection_note = ungettext('0 of %(count)d selected', 'of %(count)d selected', len(changelist.result_list)) selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', changelist.result_count) context = { 'module_name': force_unicode(self.model._meta.verbose_name_plural), 'selection_note': selection_note % {'count': len(changelist.result_list)}, 'selection_note_all': selection_note_all % {'total_count': changelist.result_count}, 'title': changelist.title, 'is_popup': changelist.is_popup, 'cl': changelist, 'media': media, 'has_add_permission': self.has_add_permission(request), 'root_path': self.admin_site.root_path, 'app_label': self.model._meta.app_label, 'action_form': action_form, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': getattr(self, 'actions_selection_counter', 0), } context.update(extra_context or {}) context_instance = template.RequestContext(request, current_app=self.admin_site.name) return render_to_response(self.change_list_template or [ 'admin/%s/%s/change_list.html' % (self.model._meta.app_label, self.model._meta.object_name.lower()), 'admin/%s/change_list.html' % self.model._meta.app_label, 'admin/change_list.html' ], context, context_instance=context_instance)
def stats_descriptions(quick_stats): """Provides a dictionary with two textual descriptions of the work outstanding. """ total_words = quick_stats["total"]["words"] untranslated = quick_stats["untranslated"]["words"] fuzzy = quick_stats["fuzzy"]["words"] todo_words = untranslated + fuzzy todo_text = ungettext("%d word needs attention", "%d words need attention", todo_words, todo_words) untranslated_tooltip = ungettext("%d word untranslated", "%d words untranslated", untranslated, untranslated) fuzzy_tooltip = ungettext("%d word needs review", "%d words need review", fuzzy, fuzzy) todo_tooltip = u"<br>".join([untranslated_tooltip, fuzzy_tooltip]) return { 'total_words': total_words, 'todo_words': todo_words, 'todo_text': todo_text, 'todo_tooltip': todo_tooltip, }
def diff_date(date, use_on_prefix=False): now = timezone.now() # datetime(*time.localtime()[0:6])#??? diff = now - date days = diff.days hours = int(diff.seconds/3600) minutes = int(diff.seconds/60) if days > 2: if date.year == now.year: date_token = date.strftime("%b %d") else: date_token = date.strftime("%b %d '%y") if use_on_prefix: return _('on %(date)s') % {'date': date_token} else: return date_token elif days == 2: return _('2 days ago') elif days == 1: return _('yesterday') elif minutes >= 60: return ungettext( '%(hr)d hour ago', '%(hr)d hours ago', hours ) % {'hr': hours} else: return ungettext( '%(min)d min ago', '%(min)d mins ago', minutes ) % {'min': minutes}
def date_diff(timestamp, to=None): if not timestamp: return "" compare_with = to or datetime.date.today() delta = timestamp - compare_with if delta.days == 0: return u"today" elif delta.days == -1: return u"yesterday" elif delta.days == 1: return u"tomorrow" chunks = ( (365.0, lambda n: ungettext("year", "years", n)), (30.0, lambda n: ungettext("month", "months", n)), (7.0, lambda n: ungettext("week", "weeks", n)), (1.0, lambda n: ungettext("day", "days", n)), ) for i, (chunk, name) in enumerate(chunks): if abs(delta.days) >= chunk: count = abs(round(delta.days / chunk, 0)) break date_str = ugettext("%(number)d %(type)s") % {"number": count, "type": name(count)} if delta.days > 0: return "in " + date_str else: return date_str + " ago"
def unit_description(self): if self.rate.monthly_limit == UNLIMITED_FEATURE_USAGE: return ungettext( "%(num_sms)d SMS Message", "%(num_sms)d SMS Messages", self.num_sms ) % { 'num_sms': self.num_sms, } elif self.is_within_monthly_limit: return _( "%(num_sms)d of %(monthly_limit)d included SMS messages" ) % { 'num_sms': self.num_sms, 'monthly_limit': self.rate.monthly_limit, } else: assert self.rate.monthly_limit != UNLIMITED_FEATURE_USAGE assert self.rate.monthly_limit < self.num_sms num_extra = self.num_sms - self.rate.monthly_limit assert num_extra > 0 return ungettext( "%(num_extra_sms)d SMS Message beyond %(monthly_limit)d messages included.", "%(num_extra_sms)d SMS Messages beyond %(monthly_limit)d messages included.", num_extra ) % { 'num_extra_sms': num_extra, 'monthly_limit': self.rate.monthly_limit, }
def clean(self, value): value = super(TagNamesField, self).clean(value) data = value.strip() if len(data) < 1: raise forms.ValidationError(_('tags are required')) split_re = re.compile(const.TAG_SPLIT_REGEX) tag_strings = split_re.split(data) out_tag_list = [] tag_count = len(tag_strings) if tag_count > askbot_settings.MAX_TAGS_PER_POST: max_tags = askbot_settings.MAX_TAGS_PER_POST msg = ungettext( 'please use %(tag_count)d tag or less', 'please use %(tag_count)d tags or less', tag_count) % {'tag_count':max_tags} raise forms.ValidationError(msg) for tag in tag_strings: tag_length = len(tag) if tag_length > askbot_settings.MAX_TAG_LENGTH: #singular form is odd in english, but required for pluralization #in other languages msg = ungettext('each tag must be shorter than %(max_chars)d character',#odd but added for completeness 'each tag must be shorter than %(max_chars)d characters', tag_length) % {'max_chars':tag_length} raise forms.ValidationError(msg) #todo - this needs to come from settings tagname_re = re.compile(const.TAG_REGEX, re.UNICODE) if not tagname_re.search(tag): raise forms.ValidationError(_('use-these-chars-in-tags')) #only keep unique tags if tag not in out_tag_list: out_tag_list.append(tag) return u' '.join(out_tag_list)
def validate_title(title): title_len = len(title) if not title_len: raise ValidationError(_("Enter thread title.")) if title_len < settings.thread_title_length_min: message = ungettext( "Thread title should be at least %(limit)s character long.", "Thread title should be at least %(limit)s characters long.", settings.thread_title_length_min) message = message % {'limit': settings.thread_title_length_min} raise ValidationError(message) if title_len > settings.thread_title_length_max: message = ungettext( "Thread title can't be longer than %(limit)s character.", "Thread title can't be longer than %(limit)s characters.", settings.thread_title_length_max,) message = message % {'limit': settings.thread_title_length_max} raise ValidationError(message) error_not_sluggable = _("Thread title should contain " "alpha-numeric characters.") error_slug_too_long = _("Thread title is too long.") slug_validator = validate_sluggable(error_not_sluggable, error_slug_too_long) slug_validator(title) return title
def form_valid(self, form): results = form.cleaned_data['importer'].import_persons() created = results['created'] refreshed = results['refreshed'] if created or refreshed: messages.add_message( self.request, messages.SUCCESS if created else messages.INFO, ' '.join(( ungettext( "%(created)d speaker created.", "%(created)d speakers created.", created, ) % {'created': created}, ungettext( "%(refreshed)d speaker refreshed.", "%(refreshed)d speakers refreshed.", refreshed, ) % {'refreshed': refreshed}, )) ) else: messages.add_message( self.request, messages.WARNING, _('No speakers found.'), ) return super(PopoloImportView, self).form_valid(form)
def validate_password_security(password, user): """ Check password reuse and similar operational security policy considerations. """ # Check reuse if not PasswordHistory.is_allowable_password_reuse(user, password): if user.is_staff: num_distinct = settings.ADVANCED_SECURITY_CONFIG['MIN_DIFFERENT_STAFF_PASSWORDS_BEFORE_REUSE'] else: num_distinct = settings.ADVANCED_SECURITY_CONFIG['MIN_DIFFERENT_STUDENT_PASSWORDS_BEFORE_REUSE'] raise SecurityPolicyError(ungettext( "You are re-using a password that you have used recently. " "You must have {num} distinct password before reusing a previous password.", "You are re-using a password that you have used recently. " "You must have {num} distinct passwords before reusing a previous password.", num_distinct ).format(num=num_distinct)) # Check reset frequency if PasswordHistory.is_password_reset_too_soon(user): num_days = settings.ADVANCED_SECURITY_CONFIG['MIN_TIME_IN_DAYS_BETWEEN_ALLOWED_RESETS'] raise SecurityPolicyError(ungettext( "You are resetting passwords too frequently. Due to security policies, " "{num} day must elapse between password resets.", "You are resetting passwords too frequently. Due to security policies, " "{num} days must elapse between password resets.", num_days ).format(num=num_days))
def get_diff_date(date): now = datetime.now() diff = now - date days = diff.days hours = int(diff.seconds / 3600) minutes = int(diff.seconds / 60) if days > 2: if date.year == now.year: return _(u'%(month)s %(day)s') % {'month': _(date.strftime('%B')), 'day': date.strftime('%d')} else: return _(u"%(month)s %(day)s '%(year)s") % {'month': _(date.strftime('%B')), 'day': date.strftime('%d'), 'year': date.strftime('%y')} elif days == 2: return _('2 days ago') elif days == 1: return _('yesterday') elif minutes >= 60: return ungettext('%(hr)d hour ago', '%(hr)d hours ago', hours) % {'hr': hours} elif diff.seconds >= 60: return ungettext('%(min)d min ago', '%(min)d mins ago', minutes) % {'min': minutes} else: return _('just now')
def format_timedelta(delta): days = delta.days hours, rem = divmod(delta.seconds, 3600) minutes, _seconds = divmod(rem, 60) # Get translated strings for days/hours/minutes if days: days = ungettext('one day', '%(count)d days', days) % {'count': days} if hours: hours = ungettext('one hour', '%(count)d hours', hours) % {'count': hours} if minutes: # just minutes minutes = ungettext('one minute', '%(count)d minutes', minutes) % {'count': minutes} # Assemble a string based on what we have if days and hours and minutes: return _('%(days)s, %(hours)s and %(minutes)s') % { 'days': days, 'hours': hours, 'minutes': minutes, } elif days and hours: return _('%(days)s and %(hours)s') % {'days': days, 'hours': hours, } elif days and minutes: return _('%(days)s and %(minutes)s') % {'days': days, 'minutes': minutes, } elif days: return days elif hours and minutes: return _('%(hours)s and %(minutes)s') % {'hours': hours, 'minutes': minutes, } elif hours: return hours elif minutes: return minutes else: return _('Now')
def humanize_timesince(date): """ http://djangosnippets.org/snippets/2275/ Humanized and localized version of built-in timesince template filter. Based on Joey Bratton's idea. """ delta = datetime.datetime.utcnow().replace(tzinfo=utc) - date num_years = delta.days / 365 if (num_years > 0): return ungettext(u"%d year ago", u"%d years ago", num_years) % num_years num_weeks = delta.days / 7 if (num_weeks > 0): return ungettext(u"%d week ago", u"%d weeks ago", num_weeks) % num_weeks if (delta.days > 0): return ungettext(u"%d day ago", u"%d days ago", delta.days) % delta.days num_hours = delta.seconds / 3600 if (num_hours > 0): return ungettext(u"%d hour ago", u"%d hours ago", num_hours) % num_hours num_minutes = delta.seconds / 60 if (num_minutes > 0): return ungettext(u"%d minute ago", u"%d minutes ago", num_minutes) % num_minutes return ugettext(u"just a few seconds ago")
def naturaltime(value, arg=None): """ For date and time values shows how many seconds, minutes or hours ago compared to current timestamp returns representing string. Otherwise, returns a string formatted according to settings.DATE_FORMAT """ try: value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) except AttributeError: return value except ValueError: return value delta = datetime.now() - value if delta.days != 0: value = date(value.year, value.month, value.day) return naturalday(value, arg) elif delta.seconds == 0: return _(u"now") elif delta.seconds < 60: return ungettext(u"%s seconds ago", u"%s seconds ago", delta.seconds) elif delta.seconds / 60 < 60: return ungettext(u"a minute ago", u"%s minutes ago", delta.seconds / 60) elif delta.seconds / 60 / 60 < 24: return ungettext(u"an hour ago", u"%s hours ago", delta.seconds / 60 / 60) return naturalday(value, arg)
def allow_delete_user(user, target): newer_than = user.acl['can_delete_users_newer_than'] less_posts_than = user.acl['can_delete_users_with_less_posts_than'] if not (newer_than or less_posts_than): raise PermissionDenied(_("You can't delete users.")) if user.pk == target.pk: raise PermissionDenied(_("You can't delete yourself.")) if target.is_staff or target.is_superuser: raise PermissionDenied(_("You can't delete administrators.")) if newer_than: if target.joined_on < timezone.now() - timedelta(days=newer_than): message = ungettext("You can't delete users that are " "members for more than %(days)s day.", "You can't delete users that are " "members for more than %(days)s days.", newer_than) % {'days': newer_than} raise PermissionDenied(message) if less_posts_than: if target.posts > less_posts_than: message = ungettext( "You can't delete users that made more than %(posts)s post.", "You can't delete users that made more than %(posts)s posts.", less_posts_than) % {'posts': less_posts_than} raise PermissionDenied(message)
def validate_username(value): value = unicode(value).strip() if len(value) < settings.username_length_min: raise ValidationError(ungettext( 'Username must be at least one character long.', 'Username must be at least %(count)d characters long.', settings.username_length_min ) % { 'count': settings.username_length_min, }) if len(value) > settings.username_length_max: raise ValidationError(ungettext( 'Username cannot be longer than one characters.', 'Username cannot be longer than %(count)d characters.', settings.username_length_max ) % { 'count': settings.username_length_max, }) if settings.UNICODE_USERNAMES: if not re.search('^[^\W_]+$', value, re.UNICODE): raise ValidationError(_("Username can only contain letters and digits.")) else: if not re.search('^[^\W_]+$', value): raise ValidationError(_("Username can only contain latin alphabet letters and digits.")) if Ban.objects.check_ban(username=value): raise ValidationError(_("This username is forbidden."))
def pybb_user_time(context_time, user): delta = tznow() - context_time today = tznow().replace(hour=0, minute=0, second=0) yesterday = today - timedelta(days=1) tomorrow = today + timedelta(days=1) if delta.days == 0: if delta.seconds < 60: msg = ungettext('%d second ago', '%d seconds ago', delta.seconds) return msg % delta.seconds elif delta.seconds < 3600: minutes = int(delta.seconds / 60) msg = ungettext('%d minute ago', '%d minutes ago', minutes) return msg % minutes if is_authenticated(user): if time.daylight: # pragma: no cover tz1 = time.altzone else: # pragma: no cover tz1 = time.timezone tz = tz1 + util.get_pybb_profile(user).time_zone * 60 * 60 context_time = context_time + timedelta(seconds=tz) if today < context_time < tomorrow: return _('today, %s') % context_time.strftime('%H:%M') elif yesterday < context_time < today: return _('yesterday, %s') % context_time.strftime('%H:%M') else: return dateformat.format(context_time, 'd M, Y H:i')
def process_transactions(modeladmin, request, queryset): processes = [] if queryset.exclude(state=Transaction.WAITTING_PROCESSING).exists(): msg = _("Selected transactions must be on '{state}' state") messages.error(request, msg.format(state=Transaction.WAITTING_PROCESSING)) return for method, transactions in queryset.group_by('source__method').items(): if method is not None: method = PaymentMethod.get(method) procs = method.process(transactions) processes += procs for trans in transactions: modeladmin.log_change(request, trans, _("Processed")) if not processes: return opts = modeladmin.model._meta num = len(queryset) context = { 'title': ungettext( _("Selected transaction has been processed."), _("%s Selected transactions have been processed.") % num, num), 'content_message': ungettext( _("The following transaction process has been generated, " "you may want to save it on your computer now."), _("The following %s transaction processes have been generated, " "you may want to save it on your computer now.") % len(processes), len(processes)), 'action_name': _("Process"), 'processes': processes, 'opts': opts, 'app_label': opts.app_label, } return render(request, 'admin/payments/transaction/get_processes.html', context)
def post_controls(post, user): controls = [] menu = [] if user.is_authenticated(): post_type = post.node_type if post_type == "answer": controls.append( post_control(_('permanent link'), post.get_absolute_url(), title=_("answer permanent link"))) edit_url = reverse('edit_' + post_type, kwargs={'id': post.id}) if user.can_edit_post(post): controls.append(post_control(_('edit'), edit_url)) elif post_type == 'question' and user.can_retag_questions(): controls.append(post_control(_('retag'), edit_url)) if post_type == 'question': if post.nis.closed and user.can_reopen_question(post): controls.append( post_control(_('reopen'), reverse('reopen', kwargs={'id': post.id}), command=True)) elif not post.nis.closed and user.can_close_question(post): controls.append( post_control(_('close'), reverse('close', kwargs={'id': post.id}), command=True, withprompt=True)) if user.can_flag_offensive(post): label = _('report') if user.can_view_offensive_flags(post): label = "%s (%d)" % (label, post.flag_count) controls.append( post_control( label, reverse('flag_post', kwargs={'id': post.id}), command=True, withprompt=True, title= _("report as offensive (i.e containing spam, advertising, malicious text, etc.)" ))) if user.can_delete_post(post): if post.nis.deleted: controls.append( post_control(_('undelete'), reverse('delete_post', kwargs={'id': post.id}), command=True, confirm=True)) else: controls.append( post_control(_('delete'), reverse('delete_post', kwargs={'id': post.id}), command=True, confirm=True)) if user.can_delete_post(post): menu.append( post_control(_('see revisions'), reverse('revisions', kwargs={'id': post.id}), command=False, confirm=False)) if settings.WIKI_ON: if (not post.nis.wiki) and user.can_wikify(post): menu.append( post_control(_('mark as community wiki'), reverse('wikify', kwargs={'id': post.id}), command=True, confirm=True)) elif post.nis.wiki and user.can_cancel_wiki(post): menu.append( post_control(_('cancel community wiki'), reverse('wikify', kwargs={'id': post.id}), command=True, confirm=True)) if post.node_type == "answer" and user.can_convert_to_comment(post): menu.append( post_control(_('convert to comment'), reverse('convert_to_comment', kwargs={'id': post.id}), command=True, withprompt=True)) if post.node_type == "answer" and user.can_convert_to_question(post): menu.append( post_control(_('convert to question'), reverse('convert_to_question', kwargs={'id': post.id}), command=True, withprompt=True)) if user.is_superuser or user.is_staff: plain_text = strip_tags(post.html) char_count = len(plain_text) fullStr = plain_text + " " left_trimmedStr = re.sub(re.compile(r"^[^\w]+", re.IGNORECASE), "", fullStr) cleanedStr = re.sub(re.compile(r"[^\w]+", re.IGNORECASE), " ", left_trimmedStr) splitString = cleanedStr.split(" ") word_count = len(splitString) - 1 metrics = mark_safe( "<b>%s %s / %s %s</b>" % (char_count, ungettext('character', 'characters', char_count), word_count, ungettext('word', 'words', word_count))) menu.append( post_control(metrics, "#", command=False, withprompt=False)) return {'controls': controls, 'menu': menu, 'post': post, 'user': user}
def message_remove(request, undo=False): """ A ``POST`` to remove messages. :param undo: A Boolean that if ``True`` unremoves messages. POST can have the following keys: ``message_pks`` List of message id's that should be deleted. ``next`` String containing the URI which to redirect to after the keys are removed. Redirect defaults to the inbox view. The ``next`` value can also be supplied in the URI with ``?next=<value>``. """ message_pks = request.POST.getlist('message_pks') redirect_to = request.REQUEST.get('next', False) if message_pks: # Check that all values are integers. valid_message_pk_list = set() for pk in message_pks: try: valid_pk = int(pk) except (TypeError, ValueError): pass else: valid_message_pk_list.add(valid_pk) # Delete all the messages, if they belong to the user. now = get_datetime_now() changed_message_list = set() for pk in valid_message_pk_list: message = get_object_or_404(Message, pk=pk) # Check if the user is the owner if message.sender == request.user: if undo: message.sender_deleted_at = None else: message.sender_deleted_at = now message.save() changed_message_list.add(message.pk) # Check if the user is a recipient of the message if request.user in message.recipients.all(): mr = message.messagerecipient_set.get(user=request.user, message=message) if undo: mr.deleted_at = None else: mr.deleted_at = now mr.save() changed_message_list.add(message.pk) # Send messages if (len(changed_message_list) > 0) and userena_settings.USERENA_USE_MESSAGES: if undo: message = ungettext('Message is succesfully restored.', 'Messages are succesfully restored.', len(changed_message_list)) else: message = ungettext('Message is successfully removed.', 'Messages are successfully removed.', len(changed_message_list)) messages.success(request, message, fail_silently=True) if redirect_to: return redirect(redirect_to) else: return redirect(reverse('userena_umessages_list'))
def changelist_view(self, request, extra_context=None): # # This implementation is all copied from the parent, and only modified # for a few lines where marked to add a map to the change list. # "The 'change list' admin view for this model." from django.contrib.admin.views.main import ERROR_FLAG opts = self.model._meta app_label = opts.app_label if not self.has_change_permission(request, None): raise PermissionDenied # Check actions to see if any are available on this changelist actions = self.get_actions(request) # Remove action checkboxes if there aren't any actions available. list_display = list(self.list_display) if not actions: try: list_display.remove('action_checkbox') except ValueError: pass ChangeList = self.get_changelist(request) try: cl = ChangeList(request, self.model, list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) except IncorrectLookupParameters: # Wacky lookup parameters were given, so redirect to the main # changelist page, without parameters, and pass an 'invalid=1' # parameter via the query string. If wacky parameters were given and # the 'invalid=1' parameter was already in the query string, something # is screwed up with the database, so display an error page. if ERROR_FLAG in request.GET.keys(): return render_to_response('admin/invalid_setup.html', {'title': _('Database error')}) return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') # If the request was POSTed, this might be a bulk action or a bulk edit. # Try to look up an action or confirmation first, but if this isn't an # action the POST will fall through to the bulk edit check, below. if actions and request.method == 'POST' and ( helpers.ACTION_CHECKBOX_NAME in request.POST or 'index' in request.POST): response = self.response_action(request, queryset=cl.get_query_set()) if response: return response # If we're allowing changelist editing, we need to construct a formset # for the changelist given all the fields to be edited. Then we'll # use the formset to validate/process POSTed data. formset = cl.formset = None # Handle POSTed bulk-edit data. if request.method == "POST" and self.list_editable: FormSet = self.get_changelist_formset(request) formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list) if formset.is_valid(): changecount = 0 for form in formset.forms: if form.has_changed(): obj = self.save_form(request, form, change=True) self.save_model(request, obj, form, change=True) form.save_m2m() change_msg = self.construct_change_message( request, form, None) self.log_change(request, obj, change_msg) changecount += 1 if changecount: if changecount == 1: name = force_unicode(opts.verbose_name) else: name = force_unicode(opts.verbose_name_plural) msg = ungettext( "%(count)s %(name)s was changed successfully.", "%(count)s %(name)s were changed successfully.", changecount) % { 'count': changecount, 'name': name, 'obj': force_unicode(obj) } self.message_user(request, msg) return HttpResponseRedirect(request.get_full_path()) # Handle GET -- construct a formset for display. elif self.list_editable: FormSet = self.get_changelist_formset(request) formset = cl.formset = FormSet(queryset=cl.result_list) # Build the list of media to be used by the formset. if formset: media = self.media + formset.media else: media = self.media # Build the action form and populate it with available actions. if actions: action_form = self.action_form(auto_id=None) action_form.fields['action'].choices = self.get_action_choices( request) else: action_form = None selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) context = { 'module_name': force_unicode(opts.verbose_name_plural), 'selection_note': _('0 of %(cnt)s selected') % { 'cnt': len(cl.result_list) }, 'selection_note_all': selection_note_all % { 'total_count': cl.result_count }, 'title': cl.title, 'is_popup': cl.is_popup, 'cl': cl, 'media': media, 'has_add_permission': self.has_add_permission(request), 'root_path': self.admin_site.root_path, 'app_label': app_label, 'action_form': action_form, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': self.actions_selection_counter, } context.update(extra_context or {}) # MODIFICATION map_ = self.get_changelist_map(cl) if map_: context['media'] += map_.media context['map'] = map_ # END MODIFICATION context_instance = template.RequestContext( request, current_app=self.admin_site.name) return render_to_response(self.change_list_template or [ 'admin/%s/%s/change_list.html' % (app_label, opts.object_name.lower()), 'admin/%s/change_list.html' % app_label, 'admin/change_list.html' ], context, context_instance=context_instance)
def get_success_message(self, count): return ungettext(self.success_message, self.success_message_plural, count) % { 'count': count, }
def nav_subtitle(self): num_used = self.num_used return ungettext("%(num_used)s file used", "%(num_used)s files used", num_used) % { "num_used": num_used }
def filenode_admin_action(modeladmin, request, queryset, form_class, extra_context, success_messages, form_initial=None, is_recursive=True): """ """ execute = request.POST.get('execute') current_node = None if execute: if not issubclass(form_class, FileNodeActionsWithUserForm): form = form_class(queryset, request.POST) else: form = form_class(queryset, request.user, request.POST) if form.is_valid(): form.save() redirect_node = form.cleaned_data.get('target_node', None) if not redirect_node: redirect_node = get_current_node(form) messages.success( request, message=ungettext(success_messages[0], success_messages[1], form.success_count) % { 'count': form.success_count, 'verbose_name': FileNode._meta.verbose_name, 'verbose_name_plural': FileNode._meta.verbose_name_plural }) return HttpResponseRedirect( reverse('admin:media_tree_filenode_changelist')) #return HttpResponseRedirect(reverse('admin:media_tree_filenode_folder_expand', args=(redirect_node.pk,))) #return HttpResponseRedirect(redirect_node.get_admin_url()) if not execute: if not issubclass(form_class, FileNodeActionsWithUserForm): form = form_class(queryset, initial=form_initial) else: form = form_class(queryset, request.user, initial=form_initial) context = get_actions_context(modeladmin) context.update(extra_context) context.update({ 'breadcrumbs_title': context['title'], 'form': form, 'node': get_current_node(form) }) if not 'node_list' in context: if is_recursive: max_depth = None else: max_depth = 1 context['node_list'] = get_nested_filenode_list( form.selected_nodes, processors=[FileNode.get_admin_link], max_depth=max_depth) return render_to_response('admin/media_tree/filenode/actions_form.html', context, context_instance=RequestContext(request))
def delaccount(request, pk): User.objects.get(pk=pk).delete() return render_to_json_response( ungettext("Account deleted", "Accounts deleted", 1))
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ search_state = SearchState(user_logged_in=request.user.is_authenticated(), **kwargs) qs, meta_data = Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) paginator = Paginator(qs, search_state.page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # FIXME: evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names', [])) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': # force cloud to sort by name related_tags = sorted(related_tags, key=operator.attrgetter('name')) contributors = Thread.objects.get_thread_contributors(thread_list=page.object_list).\ only('id', 'username', 'gravatar') paginator_context = { 'is_paginated': (paginator.count > search_state.page_size), 'pages': paginator.num_pages, 'current_page_number': search_state.page, 'page_object': page, 'base_url': search_state.query_string(), 'page_size': search_state.page_size, } # get url for the rss feed context_feed_url = reverse('latest_questions_feed') # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist('tags', search_state.tags) context_feed_url += '?' + rss_query_dict.urlencode() reset_method_count = len( tuple( filter(None, [ search_state.query, search_state.tags, meta_data.get('author_name', None) ]))) if request.is_ajax(): q_count = paginator.count # TODO: words question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % { 'q_num': humanize.intcomma(q_count) } if q_count > search_state.page_size: paginator_html = render_to_string( 'main_page/paginator.jinja', { 'context': paginator_context, 'questions_count': q_count, 'page_size': search_state.page_size, 'search_state': search_state, }, request) else: paginator_html = '' questions_html = render_to_string( 'main_page/questions_loop.jinja', { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request, }, request) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [], # [extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size': search_state.page_size, 'questions': questions_html.replace('\n', ''), 'non_existing_tags': meta_data['non_existing_tags'], } related_tags_data = { 'tags': related_tags, 'tag_list_type': tag_list_type, 'query_string': search_state.query_string(), 'search_state': search_state, 'language_code': translation.get_language(), } if tag_list_type == 'cloud': related_tags_data['font_size'] = extra_tags.get_tag_font_size( related_tags) ajax_data['related_tags_html'] = render_to_string( 'widgets/related_tags.jinja', related_tags_data, request) # here we add and then delete some items to allow extra context processor to work ajax_data['tags'] = related_tags ajax_data['interesting_tag_names'] = None ajax_data['threads'] = page extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, ajax_data) del ajax_data['tags'] del ajax_data['interesting_tag_names'] del ajax_data['threads'] ajax_data.update(extra_context) return JsonResponse(ajax_data) else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name': meta_data.get('author_name', None), 'contributors': contributors, 'context': paginator_context, 'is_unanswered': False, # remove this from template 'interesting_tag_names': meta_data.get('interesting_tag_names', None), 'ignored_tag_names': meta_data.get('ignored_tag_names', None), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user': get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': search_state.page_size, 'query': search_state.query, 'threads': page, 'questions_count': paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags': search_state.tags, 'sort': search_state.sort, 'tab_id': search_state.sort, 'tags': related_tags, 'tag_list_type': tag_list_type, 'font_size': extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url } extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, template_data) template_data.update(extra_context) template_data.update(context.get_for_tag_editor()) # and one more thing:) give admin user heads up about # setting the domain name if they have not done that yet # TODO: move this out to a separate middleware if request.user.is_authenticated() and request.user.is_administrator(): if domain_is_bad(): url = askbot_settings.get_setting_url( ('QA_SITE_SETTINGS', 'APP_URL')) msg = _( 'Please go to Settings -> %s ' 'and set the base url for your site to function properly' ) % url # request.user.message_set.create(message=msg) django_messages.info(request, msg) return render(request, 'main_page.jinja', template_data)
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ #before = datetime.datetime.now() if request.method != 'GET': return HttpResponseNotAllowed(['GET']) search_state = SearchState(user_logged_in=request.user.is_authenticated(), **kwargs) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) paginator = Paginator(qs, search_state.page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names', [])) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key=operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list).only('id', 'username', 'gravatar')) paginator_context = { 'is_paginated': (paginator.count > search_state.page_size), 'pages': paginator.num_pages, 'current_page_number': search_state.page, 'page_object': page, 'base_url': search_state.query_string(), 'page_size': search_state.page_size, } # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist("tags", search_state.tags) context_feed_url = '/%sfeeds/rss/?%s' % ( django_settings.ASKBOT_URL, rss_query_dict.urlencode() ) # Format the url with the QueryDict reset_method_count = len( filter(None, [ search_state.query, search_state.tags, meta_data.get('author_name', None) ])) if request.is_ajax(): q_count = paginator.count #todo: words question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % { 'q_num': humanize.intcomma(q_count), } if q_count > search_state.page_size: paginator_tpl = get_template('main_page/paginator.html') paginator_html = paginator_tpl.render( RequestContext( request, { 'context': paginator_context, 'questions_count': q_count, 'page_size': search_state.page_size, 'search_state': search_state, })) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html') questions_html = questions_tpl.render( RequestContext( request, { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request })) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [], #[extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size': search_state.page_size, 'questions': questions_html.replace('\n', ''), 'non_existing_tags': meta_data['non_existing_tags'], } ajax_data['related_tags'] = [{ 'name': escape(tag.name), 'used_count': humanize.intcomma(tag.local_used_count) } for tag in related_tags] #here we add and then delete some items #to allow extra context processor to work ajax_data['tags'] = related_tags ajax_data['interesting_tag_names'] = None ajax_data['threads'] = page extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, ajax_data) del ajax_data['tags'] del ajax_data['interesting_tag_names'] del ajax_data['threads'] ajax_data.update(extra_context) return HttpResponse(simplejson.dumps(ajax_data), mimetype='application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name': meta_data.get('author_name', None), 'contributors': contributors, 'context': paginator_context, 'is_unanswered': False, #remove this from template 'interesting_tag_names': meta_data.get('interesting_tag_names', None), 'ignored_tag_names': meta_data.get('ignored_tag_names', None), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user': models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': search_state.page_size, 'query': search_state.query, 'threads': page, 'questions_count': paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags': search_state.tags, 'sort': search_state.sort, 'tab_id': search_state.sort, 'tags': related_tags, 'tag_list_type': tag_list_type, 'font_size': extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), 'update_avatar_data': schedules.should_update_avatar_data(request), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url, } extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, template_data) template_data.update(extra_context) template_data.update(context.get_for_tag_editor()) #and one more thing:) give admin user heads up about #setting the domain name if they have not done that yet #todo: move this out to a separate middleware if request.user.is_authenticated() and request.user.is_administrator(): if domain_is_bad(): url = reverse('group_settings', kwargs={'group': 'QA_SITE_SETTINGS'}) url = url + '#id_QA_SITE_SETTINGS__APP_URL' msg = _( 'Please go to ' '<a href="%s">"settings->URLs, keywords and greetings"</a> ' 'and set the base url for your site to function properly' ) % url request.user.message_set.create(message=msg) return render(request, 'main_page.html', template_data)
def append_to_pdf(self, story): imgpath = os.path.join(settings.SITE_ROOT, 'static/img/circle.png') circle = "<img src='%s' width='15' height='15'/> " % imgpath cell = [] cell.append(Spacer(0, 0.8 * cm)) cell.append(Paragraph( _("Election") + ": " + self.poll.assignment.name, stylesheet['Ballot_title'])) cell.append(Paragraph( self.poll.assignment.polldescription, stylesheet['Ballot_subtitle'])) options = self.poll.get_options() ballot_string = _("%d. ballot") % self.poll.get_ballot() candidate_string = ungettext( "%d candidate", "%d candidates", len(options)) % len(options) available_posts_string = ungettext( "%d available post", "%d available posts", self.poll.assignment.posts) % self.poll.assignment.posts cell.append(Paragraph( "%s, %s, %s" % (ballot_string, candidate_string, available_posts_string), stylesheet['Ballot_description'])) cell.append(Spacer(0, 0.4 * cm)) data = [] # get ballot papers config values ballot_papers_selection = config["assignment_pdf_ballot_papers_selection"] ballot_papers_number = config["assignment_pdf_ballot_papers_number"] # set number of ballot papers if ballot_papers_selection == "NUMBER_OF_DELEGATES": try: if Group.objects.get(pk=3): number = User.objects.filter(groups__pk=3).count() except Group.DoesNotExist: number = 0 elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS": number = int(User.objects.count()) else: # ballot_papers_selection == "CUSTOM_NUMBER" number = int(ballot_papers_number) number = max(1, number) # Choose kind of ballot paper if self.poll.yesnoabstain: for option in options: candidate = option.candidate cell.append(Paragraph( candidate.clean_name, stylesheet['Ballot_option_name'])) if candidate.name_suffix: cell.append(Paragraph( "(%s)" % candidate.name_suffix, stylesheet['Ballot_option_group'])) else: cell.append(Paragraph( " ", stylesheet['Ballot_option_group'])) cell.append(Paragraph( circle + _("Yes") + " " * 3 + circle + _("No") + " " * 3 + circle + _("Abstention"), stylesheet['Ballot_option_YNA'])) # print ballot papers for user in xrange(number / 2): data.append([cell, cell]) rest = number % 2 if rest: data.append([cell, '']) if len(options) <= 2: t = Table(data, 10.5 * cm, 7.42 * cm) elif len(options) <= 5: t = Table(data, 10.5 * cm, 14.84 * cm) else: t = Table(data, 10.5 * cm, 29.7 * cm) else: for option in options: candidate = option.candidate cell.append(Paragraph( circle + candidate.clean_name, stylesheet['Ballot_option_name'])) if candidate.name_suffix: cell.append(Paragraph( "(%s)" % candidate.name_suffix, stylesheet['Ballot_option_group_right'])) else: cell.append(Paragraph( " ", stylesheet['Ballot_option_group_right'])) # print ballot papers for user in xrange(number / 2): data.append([cell, cell]) rest = number % 2 if rest: data.append([cell, '']) if len(options) <= 4: t = Table(data, 10.5 * cm, 7.42 * cm) elif len(options) <= 8: t = Table(data, 10.5 * cm, 14.84 * cm) else: t = Table(data, 10.5 * cm, 29.7 * cm) t.setStyle(TableStyle([ ('GRID', (0, 0), (-1, -1), 0.25, colors.grey), ('VALIGN', (0, 0), (-1, -1), 'TOP')])) story.append(t)
def uncompleted_payments(self, patron): count = patron.payments.filter(completed=False).count() return format_html( '{}', ungettext("%d payment", "%d payments", count) % count)
def extract_email_features(email_task): """ From the given task, extract email content information Expects that the given task has the following attributes: * task_input (dict containing email_id and to_option) * task_output (optional, dict containing total emails sent) * requester, the user who executed the task With this information, gets the corresponding email object from the bulk emails table, and loads up a dict containing the following: * created, the time the email was sent displayed in default time display * sent_to, the group the email was delivered to * email, dict containing the subject, id, and html_message of an email * number_sent, int number of emails sent * requester, the user who sent the emails If task_input cannot be loaded, then the email cannot be loaded and None is returned for these fields. """ # Load the task input info to get email id try: task_input_information = json.loads(email_task.task_input) except ValueError: log.error("Could not parse task input as valid json; task input: %s", email_task.task_input) return email_error_information() email = CourseEmail.objects.get(id=task_input_information['email_id']) email_feature_dict = { 'created': get_default_time_display(email.created), 'sent_to': [target.get_target_type_display() for target in email.targets.all()], 'requester': str(email_task.requester), } features = ['subject', 'html_message', 'id'] email_info = {feature: unicode(getattr(email, feature)) for feature in features} # Pass along email as an object with the information we desire email_feature_dict['email'] = email_info # Translators: number sent refers to the number of emails sent number_sent = _('0 sent') if hasattr(email_task, 'task_output') and email_task.task_output is not None: try: task_output = json.loads(email_task.task_output) except ValueError: log.error("Could not parse task output as valid json; task output: %s", email_task.task_output) else: if 'succeeded' in task_output and task_output['succeeded'] > 0: num_emails = task_output['succeeded'] number_sent = ungettext( "{num_emails} sent", "{num_emails} sent", num_emails ).format(num_emails=num_emails) if 'failed' in task_output and task_output['failed'] > 0: num_emails = task_output['failed'] number_sent += ", " number_sent += ungettext( "{num_emails} failed", "{num_emails} failed", num_emails ).format(num_emails=num_emails) email_feature_dict['number_sent'] = number_sent return email_feature_dict
def response_mobile_worker_creation(self): """ Get the allowed number of mobile workers based on plan version. """ from corehq.apps.accounting.models import FeatureType, FeatureRate, UNLIMITED_FEATURE_USAGE num_users = CommCareUser.total_by_domain(self.domain.name, is_active=True) try: user_rate = self.new_plan_version.feature_rates.filter( feature__feature_type=FeatureType.USER).latest('date_created') if user_rate.monthly_limit == UNLIMITED_FEATURE_USAGE: return num_allowed = user_rate.monthly_limit num_extra = num_users - num_allowed if num_extra > 0: from corehq.apps.accounting.models import DefaultProductPlan if self.new_plan_version != DefaultProductPlan.get_default_plan_version( ): return _fmt_alert( ungettext( "You have %(num_extra)d Mobile Worker over the monthly " "limit of %(monthly_limit)d for this new plan. There " "will be an additional monthly charge of USD " "%(excess_fee)s per Mobile Worker, totalling USD " "%(monthly_total)s per month, if you select this plan.", "You have %(num_extra)d Mobile Workers over the " "monthly limit of %(monthly_limit)d for this new plan. " "There will be an additional monthly charge " "of USD %(excess_fee)s per Mobile Worker, totalling " "USD %(monthly_total)s per month, if you " "select this plan.", num_extra) % { 'num_extra': num_extra, 'monthly_limit': user_rate.monthly_limit, 'excess_fee': user_rate.per_excess_fee, 'monthly_total': user_rate.per_excess_fee * num_extra, }) else: return _fmt_alert( ungettext( "Community plans include %(monthly_limit)s Mobile Workers by default. " "Because you have %(num_extra)d extra Mobile Worker, " "all your project's Mobile Workers will be deactivated. " "You can re-activate these manually after downgrade. " "Each active Mobile Worker over %(monthly_limit)s will result " "in an additional charge of USD %(excess_fee)s, totalling " "USD %(monthly_total)s per month.", "Community plans include %(monthly_limit)s Mobile Workers by default. " "Because you have %(num_extra)d extra Mobile Workers, " "all your project's Mobile Workers will be deactivated. " "You can re-activate these manually after downgrade. " "Each active Mobile Worker over %(monthly_limit)s will result " "in an additional charge of USD %(excess_fee)s, totalling " "USD %(monthly_total)s per month.", num_extra) % { 'num_extra': num_extra, 'monthly_limit': user_rate.monthly_limit, 'excess_fee': user_rate.per_excess_fee, 'monthly_total': user_rate.per_excess_fee * num_extra, }) except FeatureRate.DoesNotExist: log_accounting_error( "It seems that the plan %s did not have rate for Mobile " "Workers. This is problematic." % self.new_plan_version.plan.name)
def mark_completed(self, request, queryset): updated = queryset.complete() msg = ungettext("Marked %d payment as completed", "Marked %d payments as completed", updated) messages.success(request, msg % updated)
def emulate_users(self, request): """ The list view """ def display_as_link(obj): try: identifier = getattr(user_model_admin, list_display_link)(obj) except AttributeError: identifier = admin.utils.lookup_field(list_display_link, obj, model_admin=self)[2] emulate_user_id = request.session.get('emulate_user_id') if emulate_user_id == obj.id: return format_html('<strong>{}</strong>', identifier) fmtargs = { 'href': reverse('admin:emulate-user', kwargs={'user_id': obj.id}), 'identifier': identifier, } return format_html('<a href="{href}" class="emulate-user">{identifier}</a>', **fmtargs) opts = self.UserModel._meta app_label = opts.app_label user_model_admin = self.admin_site._registry[self.UserModel] request._lookup_model = self.UserModel list_display_links = user_model_admin.get_list_display_links(request, user_model_admin.list_display) # replace first entry in list_display_links by customized method display_as_link list_display_link = list_display_links[0] try: list_display = list(user_model_admin.segmentation_list_display) except AttributeError: list_display = list(user_model_admin.list_display) list_display.remove(list_display_link) list_display.insert(0, 'display_as_link') display_as_link.allow_tags = True # TODO: presumably not required anymore since Django-1.9 try: display_as_link.short_description = user_model_admin.identifier.short_description except AttributeError: display_as_link.short_description = admin.utils.label_for_field(list_display_link, self.UserModel) self.display_as_link = display_as_link ChangeList = self.get_changelist(request) if DJANGO_VERSION < (2, 1): cl = ChangeList(request, self.UserModel, list_display, (None,), # disable list_display_links in ChangeList, instead override that field user_model_admin.list_filter, user_model_admin.date_hierarchy, user_model_admin.search_fields, user_model_admin.list_select_related, user_model_admin.list_per_page, user_model_admin.list_max_show_all, (), # disable list_editable self) else: cl = ChangeList(request, self.UserModel, list_display, (None,), # disable list_display_links in ChangeList, instead override that field user_model_admin.list_filter, user_model_admin.date_hierarchy, user_model_admin.search_fields, user_model_admin.list_select_related, user_model_admin.list_per_page, user_model_admin.list_max_show_all, (), # disable list_editable self, None) cl.formset = None selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) context = { 'module_name': str(opts.verbose_name_plural), 'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)}, 'selection_note_all': selection_note_all % {'total_count': cl.result_count}, 'title': _("Select %(user_model)s to emulate") % {'user_model': opts.verbose_name}, 'is_popup': cl.is_popup, 'cl': cl, 'media': self.media, 'has_add_permission': False, 'opts': cl.opts, 'app_label': app_label, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': self.actions_selection_counter, 'preserved_filters': self.get_preserved_filters(request), } return TemplateResponse(request, self.change_list_template or [ 'admin/%s/%s/change_list.html' % (app_label, opts.model_name), 'admin/%s/change_list.html' % app_label, 'admin/change_list.html' ], context)
def changelist_view(self, request, extra_context=None): """ The 'change list' admin view for this model. """ from django.contrib.admin.views.main import ERROR_FLAG opts = self.model._meta app_label = opts.app_label if not self.has_view_permission( request, None) and not self.has_change_permission( request, None): raise PermissionDenied list_display = self.get_list_display(request) if self.has_change_permission(request, None): list_display_links = self.get_list_display_links( request, list_display) else: list_display_links = (None, ) list_filter = self.get_list_filter(request) # Check actions to see if any are available on this changelist actions = self.get_actions(request) if actions: # Add the action checkboxes if there are any actions available. list_display = ['action_checkbox'] + list(list_display) ChangeList = self.get_changelist(request) try: cl = ChangeList(request, self.model, list_display, list_display_links, list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_max_show_all, self.list_editable, self) except IncorrectLookupParameters: # Wacky lookup parameters were given, so redirect to the main # changelist page, without parameters, and pass an 'invalid=1' # parameter via the query string. If wacky parameters were given # and the 'invalid=1' parameter was already in the query string, # something is screwed up with the database, so display an error # page. if ERROR_FLAG in request.GET.keys(): return SimpleTemplateResponse('admin/invalid_setup.html', { 'title': _('Database error'), }) return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') # If the request was POSTed, this might be a bulk action or a bulk # edit. Try to look up an action or confirmation first, but if this # isn't an action the POST will fall through to the bulk edit check, # below. action_failed = False selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) # Actions with no confirmation if (actions and request.method == 'POST' and 'index' in request.POST and '_save' not in request.POST): if selected: response = self.response_action( request, queryset=cl.get_queryset(request)) if response: return response else: action_failed = True else: msg = _("Items must be selected in order to perform " "actions on them. No items have been changed.") self.message_user(request, msg, messages.WARNING) action_failed = True # Actions with confirmation if (actions and request.method == 'POST' and helpers.ACTION_CHECKBOX_NAME in request.POST and 'index' not in request.POST and '_save' not in request.POST): if selected: response = self.response_action( request, queryset=cl.get_queryset(request)) if response: return response else: action_failed = True # If we're allowing changelist editing, we need to construct a formset # for the changelist given all the fields to be edited. Then we'll # use the formset to validate/process POSTed data. formset = cl.formset = None # Handle POSTed bulk-edit data. if (request.method == "POST" and cl.list_editable and '_save' in request.POST and not action_failed): FormSet = self.get_changelist_formset(request) formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list) if formset.is_valid(): changecount = 0 for form in formset.forms: if form.has_changed(): obj = self.save_form(request, form, change=True) self.save_model(request, obj, form, change=True) self.save_related(request, form, formsets=[], change=True) change_msg = self.construct_change_message( request, form, None) self.log_change(request, obj, change_msg) changecount += 1 if changecount: if changecount == 1: name = force_text(opts.verbose_name) else: name = force_text(opts.verbose_name_plural) msg = ungettext( "%(count)s %(name)s was changed successfully.", "%(count)s %(name)s were changed successfully.", changecount) % { 'count': changecount, 'name': name, 'obj': force_text(obj) } self.message_user(request, msg, messages.SUCCESS) return HttpResponseRedirect(request.get_full_path()) # Handle GET -- construct a formset for display. elif cl.list_editable: FormSet = self.get_changelist_formset(request) formset = cl.formset = FormSet(queryset=cl.result_list) # Build the list of media to be used by the formset. if formset: media = self.media + formset.media else: media = self.media # Build the action form and populate it with available actions. if actions: action_form = self.action_form(auto_id=None) action_form.fields['action'].choices = self.get_action_choices( request) else: action_form = None selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', cl.result_count) context = { 'module_name': force_text(opts.verbose_name_plural), 'selection_note': _('0 of %(cnt)s selected') % { 'cnt': len(cl.result_list) }, 'selection_note_all': selection_note_all % { 'total_count': cl.result_count }, 'title': cl.title, 'is_popup': cl.is_popup, 'cl': cl, 'media': media, 'has_add_permission': self.has_add_permission(request), 'opts': cl.opts, 'app_label': app_label, 'action_form': action_form, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': self.actions_selection_counter, 'preserved_filters': self.get_preserved_filters(request), } context.update(extra_context or {}) return TemplateResponse( request, self.change_list_template or [ 'admin/%s/%s/change_list.html' % (app_label, opts.model_name), 'admin/%s/change_list.html' % app_label, 'admin/change_list.html' ], context, current_app=self.admin_site.name)
def remove_comments(self, request, queryset): self._bulk_flag(request, queryset, perform_delete, lambda n: ungettext('removed', 'removed', n))
def test_ungettext(self): for i in [1, 2]: out = Text(ungettext(u"1 & {}", u"2 & {}", i)).format(HTML(u"<>")) self.assertEqual(out, u"{} & <>".format(i))
def flag_comments(self, request, queryset): self._bulk_flag(request, queryset, perform_flag, lambda n: ungettext('flagged', 'flagged', n))
def changelist_view(self, request, extra_context=None): if not self.has_change_permission(request, None): raise PermissionDenied if not SEARCH_VAR in request.GET: # Do the usual song and dance. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # Do a search of just this model and populate a Changelist with the # returned bits. if not self.model in connections['default'].get_unified_index( ).get_indexed_models(): # Oops. That model isn't being indexed. Return the usual # behavior instead. return super(SearchModelAdmin, self).changelist_view(request, extra_context) # So. Much. Boilerplate. # Why copy-paste a few lines when you can copy-paste TONS of lines? list_display = list(self.list_display) kwargs = { 'request': request, 'model': self.model, 'list_display': list_display, 'list_display_links': self.list_display_links, 'list_filter': self.list_filter, 'date_hierarchy': self.date_hierarchy, 'search_fields': self.search_fields, 'list_select_related': self.list_select_related, 'list_per_page': self.list_per_page, 'list_editable': self.list_editable, 'model_admin': self } # Django 1.4 compatibility. if hasattr(self, 'list_max_show_all'): kwargs['list_max_show_all'] = self.list_max_show_all changelist = SearchChangeList(**kwargs) formset = changelist.formset = None media = self.media # Build the action form and populate it with available actions. # Check actions to see if any are available on this changelist actions = self.get_actions(request) if actions: action_form = self.action_form(auto_id=None) action_form.fields['action'].choices = self.get_action_choices( request) else: action_form = None selection_note = ungettext('0 of %(count)d selected', 'of %(count)d selected', len(changelist.result_list)) selection_note_all = ungettext('%(total_count)s selected', 'All %(total_count)s selected', changelist.result_count) context = { 'module_name': force_text(self.model._meta.verbose_name_plural), 'selection_note': selection_note % { 'count': len(changelist.result_list) }, 'selection_note_all': selection_note_all % { 'total_count': changelist.result_count }, 'title': changelist.title, 'is_popup': changelist.is_popup, 'cl': changelist, 'media': media, 'has_add_permission': self.has_add_permission(request), # More Django 1.4 compatibility 'root_path': getattr(self.admin_site, 'root_path', None), 'app_label': self.model._meta.app_label, 'action_form': action_form, 'actions_on_top': self.actions_on_top, 'actions_on_bottom': self.actions_on_bottom, 'actions_selection_counter': getattr(self, 'actions_selection_counter', 0), } context.update(extra_context or {}) context_instance = template.RequestContext( request, current_app=self.admin_site.name) return render_to_response(self.change_list_template or [ 'admin/%s/%s/change_list.html' % (self.model._meta.app_label, self.model._meta.object_name.lower()), 'admin/%s/change_list.html' % self.model._meta.app_label, 'admin/change_list.html' ], context, context_instance=context_instance)
def do_action(self): # check before start if not work_weixin_notifications_check(): self.log_error('work weixin notifications settings check failed') return access_token = get_work_weixin_access_token() if not access_token: self.log_error('can not get access_token') self.work_weixin_notifications_url = WORK_WEIXIN_NOTIFICATIONS_URL + '?access_token=' + access_token self.detail_url = get_site_scheme_and_netloc().rstrip('/') + reverse('user_notification_list') site_name = get_site_name() # start now = datetime.now() today = datetime.now().replace(hour=0).replace(minute=0).replace( second=0).replace(microsecond=0) # 1. get all users who are connected work weixin socials = SocialAuthUser.objects.filter(provider=WORK_WEIXIN_PROVIDER, uid__contains=WORK_WEIXIN_UID_PREFIX) users = [(x.username, x.uid[len(WORK_WEIXIN_UID_PREFIX):]) for x in socials] self.log_info('Found %d users' % len(users)) if not users: return user_uid_map = {} for username, uid in users: user_uid_map[username] = uid # 2. get previous time that command last runs try: cmd_last_check = CommandsLastCheck.objects.get(command_type=self.label) self.log_debug('Last check time is %s' % cmd_last_check.last_check) last_check_dt = cmd_last_check.last_check cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: last_check_dt = today self.log_debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() # 3. get all unseen notices for those users qs = UserNotification.objects.filter( timestamp__gt=last_check_dt ).filter(seen=False).filter( to_user__in=user_uid_map.keys() ) self.log_info('Found %d notices' % qs.count()) if qs.count() == 0: return user_notices = {} for q in qs: if q.to_user not in user_notices: user_notices[q.to_user] = [q] else: user_notices[q.to_user].append(q) # save current language cur_language = translation.get_language() # active zh-cn translation.activate('zh-cn') self.log_info('the language is set to zh-cn') # 4. send msg to users for username, uid in users: notices = user_notices.get(username, []) count = len(notices) if count == 0: continue title = ungettext( "\n" "You've got 1 new notice on %(site_name)s:\n", "\n" "You've got %(num)s new notices on %(site_name)s:\n", count ) % {'num': count, 'site_name': site_name, } content = ''.join([wrap_div(x.format_msg()) for x in notices]) self.send_work_weixin_msg(uid, title, content) # reset language translation.activate(cur_language) self.log_info('reset language success')
def approve_comments(self, request, queryset): self._bulk_flag(request, queryset, perform_approve, lambda n: ungettext('approved', 'approved', n))
def naturaltime_future(value, now): """Handling of future dates for naturaltime.""" # this function is huge # pylint: disable=too-many-branches,too-many-return-statements delta = value - now if delta.days >= 365: count = delta.days // 365 if count == 1: return ugettext("a year from now") return ungettext("%(count)s year from now", "%(count)s years from now", count) % { "count": count } if delta.days >= 30: count = delta.days // 30 if count == 1: return ugettext("a month from now") return ungettext("%(count)s month from now", "%(count)s months from now", count) % { "count": count } if delta.days >= 14: count = delta.days // 7 return ungettext("%(count)s week from now", "%(count)s weeks from now", count) % { "count": count } if delta.days > 0: if delta.days == 1: return ugettext("tomorrow") if delta.days == 7: return ugettext("a week from now") return ungettext("%(count)s day from now", "%(count)s days from now", delta.days) % { "count": delta.days } if delta.seconds == 0: return ugettext("now") if delta.seconds < 60: if delta.seconds == 1: return ugettext("a second from now") return ungettext("%(count)s second from now", "%(count)s seconds from now", delta.seconds) % { "count": delta.seconds } if delta.seconds // 60 < 60: count = delta.seconds // 60 if count == 1: return ugettext("a minute from now") return ungettext("%(count)s minute from now", "%(count)s minutes from now", count) % { "count": count } count = delta.seconds // 60 // 60 if count == 1: return ugettext("an hour from now") return ungettext("%(count)s hour from now", "%(count)s hours from now", count) % { "count": count }
def mktg_course_about(request, course_id): """This is the button that gets put into an iframe on the Drupal site.""" course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) try: permission_name = microsite.get_value( 'COURSE_ABOUT_VISIBILITY_PERMISSION', settings.COURSE_ABOUT_VISIBILITY_PERMISSION) course = get_course_with_access(request.user, permission_name, course_key) except (ValueError, Http404): # If a course does not exist yet, display a "Coming Soon" button return render_to_response( 'courseware/mktg_coming_soon.html', {'course_id': course_key.to_deprecated_string()}) registered = registered_for_course(course, request.user) if has_access(request.user, 'load', course): course_target = reverse('info', args=[course.id.to_deprecated_string()]) else: course_target = reverse('about_course', args=[course.id.to_deprecated_string()]) allow_registration = has_access(request.user, 'enroll', course) show_courseware_link = (has_access(request.user, 'load', course) or settings.FEATURES.get('ENABLE_LMS_MIGRATION')) course_modes = CourseMode.modes_for_course_dict(course.id) context = { 'course': course, 'registered': registered, 'allow_registration': allow_registration, 'course_target': course_target, 'show_courseware_link': show_courseware_link, 'course_modes': course_modes, } if settings.FEATURES.get('ENABLE_MKTG_EMAIL_OPT_IN'): # Drupal will pass organization names using a GET parameter, as follows: # ?org=Harvard # ?org=Harvard,MIT # If no full names are provided, the marketing iframe won't show the # email opt-in checkbox. org = request.GET.get('org') if org: org_list = org.split(',') # HTML-escape the provided organization names org_list = [cgi.escape(org) for org in org_list] if len(org_list) > 1: if len(org_list) > 2: # Translators: The join of three or more institution names (e.g., Harvard, MIT, and Dartmouth). org_name_string = _( "{first_institutions}, and {last_institution}").format( first_institutions=u", ".join(org_list[:-1]), last_institution=org_list[-1]) else: # Translators: The join of two institution names (e.g., Harvard and MIT). org_name_string = _( "{first_institution} and {second_institution}").format( first_institution=org_list[0], second_institution=org_list[1]) else: org_name_string = org_list[0] context['checkbox_label'] = ungettext( "I would like to receive email from {institution_series} and learn about its other programs.", "I would like to receive email from {institution_series} and learn about their other programs.", len(org_list)).format(institution_series=org_name_string) # The edx.org marketing site currently displays only in English. # To avoid displaying a different language in the register / access button, # we force the language to English. # However, OpenEdX installations with a different marketing front-end # may want to respect the language specified by the user or the site settings. force_english = settings.FEATURES.get('IS_EDX_DOMAIN', False) if force_english: translation.activate('en-us') try: return render_to_response('courseware/mktg_course_about.html', context) finally: # Just to be safe, reset the language if we forced it to be English. if force_english: translation.deactivate()
def timesince(d, now=None): """Take two datetime objects and return the time between d and now as a nicely formatted string, e.g. "10 minutes". If d is None or occurs after now, return ''. Units used are years, months, weeks, days, hours, and minutes. Seconds and microseconds are ignored. Just one unit is displayed. For example, "2 weeks" and "1 year" are possible outputs, but "2 weeks, 3 days" and "1 year, 5 months" are not. Adapted from django.utils.timesince to have better i18n (not assuming commas as list separators and including "ago" so order of words isn't assumed), show only one time unit, and include seconds. """ if d is None: return u"" chunks = [ ( 60 * 60 * 24 * 365, lambda n: ungettext("%(number)d year ago", "%(number)d years ago", n), ), ( 60 * 60 * 24 * 30, lambda n: ungettext("%(number)d month ago", "%(number)d months ago", n), ), ( 60 * 60 * 24 * 7, lambda n: ungettext("%(number)d week ago", "%(number)d weeks ago", n), ), ( 60 * 60 * 24, lambda n: ungettext("%(number)d day ago", "%(number)d days ago", n ), ), ( 60 * 60, lambda n: ungettext("%(number)d hour ago", "%(number)d hours ago", n), ), (60, lambda n: ungettext("%(number)d minute ago", "%(number)d minutes ago", n)), (1, lambda n: ungettext("%(number)d second ago", "%(number)d seconds ago", n)), ] if not now: if d.tzinfo: # TODO: is this correct? # https://docs.djangoproject.com/en/1.8/_modules/django/utils/tzinfo/#LocalTimezone # https://docs.djangoproject.com/en/1.9/_modules/django/utils/timezone/#get_default_timezone now = datetime.datetime.now(get_default_timezone()) else: now = datetime.datetime.now() # Ignore microsecond part of 'd' since we removed it from 'now' delta = now - (d - datetime.timedelta(0, 0, d.microsecond)) since = delta.days * 24 * 60 * 60 + delta.seconds if since <= 0: # d is in the future compared to now, stop processing. return u"" for i, (seconds, name) in enumerate(chunks): count = since // seconds if count != 0: break return name(count) % {"number": count}
def verbose_value(self, value): """Render the integer as the number of sessions.""" return ungettext("%(count)d session", "%(count)d sessions", value) % { 'count': value }
def unhide_comment(self, request, queryset): count = queryset.update(hidden=False) self.message_user(request, ungettext('%d comment successfully unhidden.', '%d comments successfully unhidden.', count) % count)
def naturaltime_past(value, now): """Handling of past dates for naturaltime.""" # this function is huge # pylint: disable=too-many-branches,too-many-return-statements delta = now - value if delta.days >= 365: count = delta.days // 365 if count == 1: return ugettext("a year ago") return ungettext("%(count)s year ago", "%(count)s years ago", count) % { "count": count } if delta.days >= 30: count = delta.days // 30 if count == 1: return ugettext("a month ago") return ungettext("%(count)s month ago", "%(count)s months ago", count) % { "count": count } if delta.days >= 14: count = delta.days // 7 return ungettext("%(count)s week ago", "%(count)s weeks ago", count) % { "count": count } if delta.days > 0: if delta.days == 7: return ugettext("a week ago") if delta.days == 1: return ugettext("yesterday") return ungettext("%(count)s day ago", "%(count)s days ago", delta.days) % { "count": delta.days } if delta.seconds == 0: return ugettext("now") if delta.seconds < 60: if delta.seconds == 1: return ugettext("a second ago") return ungettext("%(count)s second ago", "%(count)s seconds ago", delta.seconds) % { "count": delta.seconds } if delta.seconds // 60 < 60: count = delta.seconds // 60 if count == 1: return ugettext("a minute ago") return ungettext("%(count)s minute ago", "%(count)s minutes ago", count) % { "count": count } count = delta.seconds // 60 // 60 if count == 1: return ugettext("an hour ago") return ungettext("%(count)s hour ago", "%(count)s hours ago", count) % { "count": count }
def make_private(self, request, queryset): count = queryset.update(is_public=False) self._update_points_many(queryset.values_list('id', flat=True), '-') self.message_user(request, ungettext('%d problem successfully marked as private.', '%d problems successfully marked as private.', count) % count)
def make_private(self, request, queryset): count = queryset.update(is_public=False) self.message_user(request, ungettext('%d contest successfully marked as private.', '%d contests successfully marked as private.', count) % count)