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),
     ])
Beispiel #2
0
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
Beispiel #4
0
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)
Beispiel #5
0
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}
Beispiel #6
0
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")
Beispiel #7
0
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")
Beispiel #8
0
    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)
Beispiel #9
0
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")
Beispiel #10
0
    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()
Beispiel #12
0
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
Beispiel #13
0
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}
Beispiel #14
0
 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)
Beispiel #15
0
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,
    }
Beispiel #16
0
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}
Beispiel #17
0
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"
Beispiel #18
0
 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,
         }
Beispiel #19
0
    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)
Beispiel #20
0
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
Beispiel #21
0
    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))
Beispiel #23
0
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')
Beispiel #24
0
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")
Beispiel #26
0
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)
Beispiel #27
0
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)
Beispiel #28
0
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."))
Beispiel #29
0
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')
Beispiel #30
0
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)
Beispiel #31
0
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}
Beispiel #32
0
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'))
Beispiel #33
0
    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)
Beispiel #34
0
 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
                      }
Beispiel #36
0
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))
Beispiel #37
0
def delaccount(request, pk):
    User.objects.get(pk=pk).delete()
    return render_to_json_response(
        ungettext("Account deleted", "Accounts deleted", 1))
Beispiel #38
0
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)
Beispiel #39
0
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)
Beispiel #40
0
    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'/>&nbsp;&nbsp;" % 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(
                        "&nbsp;", stylesheet['Ballot_option_group']))
                cell.append(Paragraph(
                    circle + _("Yes") + "&nbsp; " * 3 + circle
                    + _("No") + "&nbsp; " * 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(
                        "&nbsp;", 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)
Beispiel #41
0
 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)
Beispiel #44
0
 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)
Beispiel #45
0
    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)
Beispiel #47
0
 def remove_comments(self, request, queryset):
     self._bulk_flag(request, queryset, perform_delete,
                     lambda n: ungettext('removed', 'removed', n))
Beispiel #48
0
 def test_ungettext(self):
     for i in [1, 2]:
         out = Text(ungettext(u"1 & {}", u"2 & {}", i)).format(HTML(u"<>"))
         self.assertEqual(out, u"{} &amp; <>".format(i))
Beispiel #49
0
 def flag_comments(self, request, queryset):
     self._bulk_flag(request, queryset, perform_flag,
                     lambda n: ungettext('flagged', 'flagged', n))
Beispiel #50
0
    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)
Beispiel #51
0
    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')
Beispiel #52
0
 def approve_comments(self, request, queryset):
     self._bulk_flag(request, queryset, perform_approve,
                     lambda n: ungettext('approved', 'approved', n))
Beispiel #53
0
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
                     }
Beispiel #54
0
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()
Beispiel #55
0
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}
Beispiel #56
0
 def verbose_value(self, value):
     """Render the integer as the number of sessions."""
     return ungettext("%(count)d session", "%(count)d sessions", value) % {
         'count': value
     }
Beispiel #57
0
 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)
Beispiel #58
0
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
    }
Beispiel #59
0
 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)
Beispiel #60
0
 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)