def get_activity_data(request, user, month): [start, end] = get_date_interval(month) json = {} user_dict = ( { "id": user.id, "username": user.username, "formatted_name": user.formatted_name, "currency": user.currency if user.currency else CURRENCIES[0][0], "rate": user.rate, "review_rate": user.review_rate, "hourly_rate": user.hourly_rate, } if user != "" else user ) now = make_aware(datetime.now()) json["meta"] = { "user": user_dict, "month": month, "now": now.strftime("%Y-%m-%d %H:%M:%S"), "start": start.strftime("%Y-%m-%d"), "end": end.strftime("%Y-%m-%d"), "utc_offset": start.strftime("%z"), "admin_permalink": request.build_absolute_uri(reverse("pootle-reports")), } if user != "": scores = ScoreLog.objects.for_user_in_range(user, start, end) scores = list(scores.order_by("submission__translation_project")) json["grouped"] = get_grouped_word_stats(scores, user, month) scores.sort(key=lambda x: x.creation_time) json["daily"] = get_daily_activity(user, scores, start, end) json["summary"] = get_summary(scores, start, end) tasks = get_paid_tasks(user, start, end) for task in tasks: if settings.USE_TZ: task["datetime"] = timezone.localtime(task["datetime"]) task["datetime"] = task["datetime"].strftime("%Y-%m-%d %H:%M:%S") json["paid_tasks"] = tasks return json
def get_activity_data(request, user, month): [start, end] = get_date_interval(month) json = {} user_dict = { 'id': user.id, 'username': user.username, 'formatted_name': user.formatted_name, 'currency': user.currency if user.currency else CURRENCIES[0][0], 'rate': user.rate, 'review_rate': user.review_rate, 'hourly_rate': user.hourly_rate, } if user != '' else user now = datetime.now() if settings.USE_TZ: tz = timezone.get_default_timezone() now = timezone.make_aware(now, tz) json['meta'] = { 'user': user_dict, 'month': month, 'now': now.strftime('%Y-%m-%d %H:%M:%S'), 'start': start.strftime('%Y-%m-%d'), 'end': end.strftime('%Y-%m-%d'), 'utc_offset': start.strftime("%z"), 'admin_permalink': request.build_absolute_uri(reverse('evernote-reports')), } if user != '': scores = get_scores(user, start, end) scores = list(scores.order_by(SCORE_TRANSLATION_PROJECT)) json['grouped'] = get_grouped_paid_words(scores, user, month) scores.sort(key=lambda x: x.creation_time) json['daily'] = get_daily_activity(scores, start, end) json['summary'] = get_summary(scores, start, end) tasks = get_paid_tasks(user, start, end) for task in tasks: if settings.USE_TZ: task['datetime'] = timezone.localtime(task['datetime'], tz) task['datetime'] = task['datetime'].strftime('%Y-%m-%d %H:%M:%S') json['paid_tasks'] = tasks return json
def get_activity_data(request, user, month): [start, end] = get_date_interval(month) json = {} user_dict = { 'id': user.id, 'username': user.username, 'formatted_name': user.formatted_name, 'currency': user.currency if user.currency else CURRENCIES[0][0], 'rate': user.rate, 'review_rate': user.review_rate, 'hourly_rate': user.hourly_rate, } if user != '' else user now = make_aware(datetime.now()) json['meta'] = { 'user': user_dict, 'month': month, 'now': now.strftime('%Y-%m-%d %H:%M:%S'), 'start': start.strftime('%Y-%m-%d'), 'end': end.strftime('%Y-%m-%d'), 'utc_offset': start.strftime("%z"), 'admin_permalink': request.build_absolute_uri( reverse('pootle-reports')), } if user != '': scores = get_scores(user, start, end) scores = list(scores.order_by(SCORE_TRANSLATION_PROJECT)) json['grouped'] = get_grouped_word_stats(scores, user, month) scores.sort(key=lambda x: x.creation_time) json['daily'] = get_daily_activity(user, scores, start, end) json['summary'] = get_summary(scores, start, end) tasks = get_paid_tasks(user, start, end) for task in tasks: if settings.USE_TZ: task['datetime'] = timezone.localtime(task['datetime']) task['datetime'] = task['datetime'].strftime('%Y-%m-%d %H:%M:%S') json['paid_tasks'] = tasks return json
def get_activity_data(request, user, month): [start, end] = get_date_interval(month) json = {} user_dict = { 'id': user.id, 'username': user.username, 'formatted_name': user.formatted_name, 'currency': user.currency if user.currency else CURRENCIES[0][0], 'rate': user.rate, 'review_rate': user.review_rate, 'hourly_rate': user.hourly_rate, } if user != '' else user now = make_aware(datetime.now()) json['meta'] = { 'user': user_dict, 'month': month, 'now': now.strftime('%Y-%m-%d %H:%M:%S'), 'start': start.strftime('%Y-%m-%d'), 'end': end.strftime('%Y-%m-%d'), 'utc_offset': start.strftime("%z"), 'admin_permalink': request.build_absolute_uri(reverse('pootle-reports')), } if user != '': scores = ScoreLog.objects.for_user_in_range(user, start, end) scores = list(scores.order_by('submission__translation_project')) json['grouped'] = get_grouped_word_stats(scores, user, month) scores.sort(key=lambda x: x.creation_time) json['daily'] = get_daily_activity(user, scores, start, end) json['summary'] = get_summary(scores, start, end) tasks = get_paid_tasks(user, start, end) for task in tasks: if settings.USE_TZ: task['datetime'] = timezone.localtime(task['datetime']) task['datetime'] = task['datetime'].strftime('%Y-%m-%d %H:%M:%S') json['paid_tasks'] = tasks return json
def __init__(self, user, config, month=None, subcontractors=None, add_correction=False): self.user = user self.conf = config self.subcontractors = [] if subcontractors is None else subcontractors self.add_correction = add_correction self.month = get_previous_month() if month is None else month (month_start, month_end) = get_date_interval(self.month_string) self.month_start = month_start self.month_end = month_end self.now = timezone.now() # Calculated invoice amounts self._amounts = None # Holds a list of tuples with generated file paths and their media types self.files = [] self.generators = ( Mod() for Mod in GENERATOR_MODULES if Mod.is_configured() )
def get_detailed_report_context(user, month): [start, end] = get_date_interval(month) totals = {'translated': {}, 'reviewed': {}, 'suggested': 0, 'paid_tasks': {}, 'all': 0} items = [] if user and start and end: scores = ScoreLog.objects \ .select_related('submission__unit__store') \ .filter(user=user, creation_time__gte=start, creation_time__lte=end) \ .order_by('creation_time') tasks = PaidTask.objects.filter(user=user, datetime__gte=start, datetime__lte=end).order_by('datetime') items = [] for score in scores.iterator(): action = None subtotal = None wordcount = None translated, reviewed = score.get_paid_wordcounts() translated_details = {} if translated is not None: action = ReportActionTypes.TRANSLATION subtotal = score.rate * translated wordcount = translated translated_details['raw_rate'] = score.rate - score.review_rate translated_details['raw_translated_wordcount'] = \ score.wordcount * (1 - score.get_similarity()) translated_details['raw_subtotal'] = \ (translated_details['raw_translated_wordcount'] * translated_details['raw_rate']) translated_details['review_subtotal'] = \ score.wordcount * score.review_rate if score.rate in totals['translated']: totals['translated'][score.rate]['words'] += translated else: totals['translated'][score.rate] = {'words': translated} elif reviewed is not None: action = ReportActionTypes.REVIEW subtotal = score.review_rate * reviewed wordcount = reviewed if score.review_rate in totals['reviewed']: totals['reviewed'][score.review_rate]['words'] += reviewed else: totals['reviewed'][score.review_rate] = {'words': reviewed} suggested = score.get_suggested_wordcount() if suggested is not None: action = ReportActionTypes.SUGGESTION wordcount = suggested totals['suggested'] += suggested if action is not None: items.append({ 'score': score, 'action': action, 'action_name': ReportActionTypes.NAMES_MAP[action], 'similarity': score.get_similarity() * 100, 'subtotal': subtotal, 'wordcount': wordcount, 'source_wordcount': score.wordcount, 'translated_details': translated_details, 'creation_time': score.creation_time, }) paid_tasks = totals['paid_tasks'] for task in tasks.iterator(): subtotal = task.amount * task.rate items.append({ 'action': task.task_type, 'action_name': PaidTask.get_task_type_title(task.task_type), 'subtotal': subtotal, 'task': task, 'creation_time': task.datetime, }) totals['all'] += subtotal if task.task_type not in paid_tasks: paid_tasks[task.task_type] = { 'rates': {}, 'action': PaidTask.get_task_type_title(task.task_type), } if task.rate in paid_tasks[task.task_type]['rates']: current = paid_tasks[task.task_type]['rates'][task.rate] current['amount'] += task.amount current['subtotal'] += subtotal else: paid_tasks[task.task_type]['rates'][task.rate] = { 'amount': task.amount, 'subtotal': subtotal, } for rate, words in totals['translated'].items(): totals['translated'][rate]['rounded_words'] = \ int(round(totals['translated'][rate]['words'])) totals['translated'][rate]['subtotal'] = \ rate * totals['translated'][rate]['rounded_words'] totals['all'] += totals['translated'][rate]['subtotal'] for rate, words in totals['reviewed'].items(): totals['reviewed'][rate]['subtotal'] = ( rate * totals['reviewed'][rate]['words']) totals['all'] += totals['reviewed'][rate]['subtotal'] totals['all'] = round(totals['all'], 2) + 0 items = sorted(items, key=lambda x: x['creation_time']) if user != '' and user.currency is None: user.currency = CURRENCIES[0][0] return { 'items': items, 'object': user, 'start': start, 'end': end, 'next': start.replace(day=1) + timedelta(days=31), 'previous': start.replace(day=1) - timedelta(days=1), 'totals': totals, 'utc_offset': start.strftime("%z"), 'action_types': ReportActionTypes, }
def get_step_query(request, units_queryset): """Narrows down unit query to units matching conditions in GET.""" if "filter" in request.GET: unit_filter = request.GET["filter"] username = request.GET.get("user", None) modified_since = request.GET.get("modified-since", None) month = request.GET.get("month", None) sort_by_param = request.GET.get("sort", None) sort_on = "units" user = request.profile if username is not None: User = get_user_model() try: user = User.objects.get(username=username) except User.DoesNotExist: pass if unit_filter: match_queryset = units_queryset.none() if unit_filter == "all": match_queryset = units_queryset elif unit_filter == "translated": match_queryset = units_queryset.filter(state=TRANSLATED) elif unit_filter == "untranslated": match_queryset = units_queryset.filter(state=UNTRANSLATED) elif unit_filter == "fuzzy": match_queryset = units_queryset.filter(state=FUZZY) elif unit_filter == "incomplete": match_queryset = units_queryset.filter(Q(state=UNTRANSLATED) | Q(state=FUZZY)) elif unit_filter == "suggestions": match_queryset = units_queryset.filter(suggestion__state=SuggestionStates.PENDING).distinct() elif unit_filter in ("my-suggestions", "user-suggestions"): match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING, suggestion__user=user ).distinct() sort_on = "suggestions" elif unit_filter == "user-suggestions-accepted": match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.ACCEPTED, suggestion__user=user ).distinct() elif unit_filter == "user-suggestions-rejected": match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.REJECTED, suggestion__user=user ).distinct() elif unit_filter in ("my-submissions", "user-submissions"): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES ).distinct() sort_on = "submissions" elif unit_filter in ("my-submissions-overwritten", "user-submissions-overwritten"): match_queryset = ( units_queryset.filter(submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES) .exclude(submitted_by=user) .distinct() ) elif unit_filter == "checks": if "checks" in request.GET: checks = request.GET["checks"].split(",") if checks: match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__name__in=checks ).distinct() elif "category" in request.GET: category_name = request.GET["category"] try: category = get_category_id(category_name) except KeyError: raise Http404 match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__category=category ).distinct() if modified_since is not None: datetime_obj = parse_datetime(modified_since) if datetime_obj is not None: match_queryset = match_queryset.filter(submitted_on__gt=datetime_obj).distinct() if month is not None: [start, end] = get_date_interval(month) match_queryset = match_queryset.filter(submitted_on__gte=start, submitted_on__lte=end).distinct() sort_by = ALLOWED_SORTS[sort_on].get(sort_by_param, None) if sort_by is not None: if sort_on in SIMPLY_SORTED: if sort_by == "priority": # TODO: Replace the following extra() with Coalesce # https://docs.djangoproject.com/en/1.8/ref/models/database-functions/#coalesce # once we drop support for Django<1.8.x: # .annotate( # sort_by_field=Coalesce( # Max("vfolders__priority"), # Value(1) # ) # ).order_by("-sort_by_field") match_queryset = match_queryset.extra( select={ "sort_by_field": """ SELECT COALESCE(MAX(virtualfolder_virtualfolder.priority), 1) FROM virtualfolder_virtualfolder INNER JOIN virtualfolder_virtualfolder_units ON virtualfolder_virtualfolder.id = virtualfolder_virtualfolder_units.virtualfolder_id WHERE virtualfolder_virtualfolder_units.unit_id = pootle_store_unit.id """ } ).extra(order_by=["-sort_by_field"]) else: match_queryset = match_queryset.order_by(sort_by) else: # Omit leading `-` sign if sort_by[0] == "-": max_field = sort_by[1:] sort_order = "-sort_by_field" else: max_field = sort_by sort_order = "sort_by_field" # It's necessary to use `Max()` here because we can't # use `distinct()` and `order_by()` at the same time # (unless PostreSQL is used and `distinct(field_name)`) match_queryset = match_queryset.annotate(sort_by_field=Max(max_field)).order_by(sort_order) units_queryset = match_queryset if "search" in request.GET and "sfields" in request.GET: # Accept `sfields` to be a comma-separated string of fields (#46) GET = request.GET.copy() sfields = GET["sfields"] if isinstance(sfields, unicode) and u"," in sfields: GET.setlist("sfields", sfields.split(u",")) # use the search form for validation only search_form = make_search_form(GET) if search_form.is_valid(): units_queryset = get_search_step_query(search_form, units_queryset) return units_queryset
def get_detailed_report_context(user, month): [start, end] = get_date_interval(month) totals = {'translated': {}, 'reviewed': {}, 'suggested': 0, 'paid_tasks': {}, 'all': 0} items = [] if user and start and end: scores = ScoreLog.objects \ .select_related('submission__unit__store') \ .filter(user=user, creation_time__gte=start, creation_time__lte=end) \ .order_by('creation_time') tasks = PaidTask.objects.filter(user=user, datetime__gte=start, datetime__lte=end).order_by('datetime') items = [] for score in scores.iterator(): action = None subtotal = None wordcount = None translated, reviewed = score.get_paid_wordcounts() translated_details = {} if translated is not None: action = ReportActionTypes.TRANSLATION subtotal = score.rate * translated wordcount = translated translated_details['raw_rate'] = score.rate - score.review_rate translated_details['raw_translated_wordcount'] = \ score.wordcount * (1 - score.get_similarity()) translated_details['raw_subtotal'] = \ (translated_details['raw_translated_wordcount'] * translated_details['raw_rate']) translated_details['review_subtotal'] = \ score.wordcount * score.review_rate if score.rate in totals['translated']: totals['translated'][score.rate]['words'] += translated else: totals['translated'][score.rate] = {'words': translated} elif reviewed is not None: action = ReportActionTypes.REVIEW subtotal = score.review_rate * reviewed wordcount = reviewed if score.review_rate in totals['reviewed']: totals['reviewed'][score.review_rate]['words'] += reviewed else: totals['reviewed'][score.review_rate] = {'words': reviewed} suggested = score.get_suggested_wordcount() if suggested is not None: action = ReportActionTypes.SUGGESTION wordcount = suggested totals['suggested'] += suggested if action is not None: items.append({ 'score': score, 'action': action, 'action_name': ReportActionTypes.NAMES_MAP[action], 'similarity': score.get_similarity() * 100, 'subtotal': subtotal, 'wordcount': wordcount, 'source_wordcount': score.wordcount, 'translated_details': translated_details, 'creation_time': score.creation_time, }) paid_tasks = totals['paid_tasks'] for task in tasks.iterator(): subtotal = task.amount * task.rate items.append({ 'action': task.task_type, 'action_name': PaidTask.get_task_type_title(task.task_type), 'subtotal': subtotal, 'task': task, 'creation_time': task.datetime, }) totals['all'] += subtotal if task.task_type not in paid_tasks: paid_tasks[task.task_type] = { 'rates': {}, 'action': PaidTask.get_task_type_title(task.task_type), } if task.rate in paid_tasks[task.task_type]['rates']: current = paid_tasks[task.task_type]['rates'][task.rate] current['amount'] += task.amount current['subtotal'] += subtotal else: paid_tasks[task.task_type]['rates'][task.rate] = { 'amount': task.amount, 'subtotal': subtotal, } for rate in totals['translated']: totals['translated'][rate]['rounded_words'] = \ int(round(totals['translated'][rate]['words'])) totals['translated'][rate]['subtotal'] = \ rate * totals['translated'][rate]['rounded_words'] totals['all'] += totals['translated'][rate]['subtotal'] for rate in totals['reviewed']: totals['reviewed'][rate]['subtotal'] = ( rate * totals['reviewed'][rate]['words']) totals['all'] += totals['reviewed'][rate]['subtotal'] totals['all'] = round(totals['all'], 2) + 0 items = sorted(items, key=lambda x: x['creation_time']) if user != '' and user.currency is None: user.currency = CURRENCIES[0][0] return { 'items': items, 'object': user, 'start': start, 'end': end, 'next': start.replace(day=1) + timedelta(days=31), 'previous': start.replace(day=1) - timedelta(days=1), 'totals': totals, 'utc_offset': start.strftime("%z"), 'action_types': ReportActionTypes, }
def clean_month(self): if self.cleaned_data["month"]: return get_date_interval( self.cleaned_data["month"].strftime("%Y-%m"))
def calculate_search_results(kwargs, user): pootle_path = kwargs["pootle_path"] category = kwargs.get("category") checks = kwargs.get("checks") offset = kwargs.get("offset", 0) limit = kwargs.get("count", 9) modified_since = kwargs.get("modified-since") month = kwargs.get("month") search = kwargs.get("search") sfields = kwargs.get("sfields") soptions = kwargs.get("soptions", []) sort = kwargs.get("sort", None) vfolder = kwargs.get("vfolder", None) language_code, project_code, dir_path_, filename = (split_pootle_path( kwargs["pootle_path"])) uids = [int(x) for x in kwargs.get("uids", "").split(",") if x] unit_filter = kwargs.get("filter") if modified_since: modified_since = parse_datetime(modified_since) if month: month = get_date_interval(month) path_kwargs = { k: v for k, v in resolve(pootle_path).kwargs.items() if k in ["language_code", "project_code", "dir_path", "filename"] } qs = (Unit.objects.get_translatable(user=user, **path_kwargs).order_by( "store", "index")) if vfolder is not None: qs = qs.filter(store__vfolders=vfolder) # if "filter" is present in request vars... if unit_filter: # filter the results accordingly qs = UnitSearchFilter().filter(qs, unit_filter, user=user, checks=checks, category=get_category_id(category)) # filter by modified if modified_since: qs = qs.filter(submitted_on__gt=modified_since).distinct() if month is not None: qs = qs.filter(submitted_on__gte=month[0], submitted_on__lte=month[1]).distinct() # sort results if unit_filter in ["my-suggestions", "user-suggestions"]: sort_on = "suggestions" elif unit_filter in ["my-submissions", "user-submissions"]: sort_on = "submissions" else: sort_on = "units" sort_by = ALLOWED_SORTS[sort_on].get(sort, None) if sort_by is not None: # filtered sort if sort_on in SIMPLY_SORTED: qs = qs.order_by(sort_by, "store__pootle_path", "index") else: max_field, sort_order = get_max_and_order_fields(sort_by) qs = (qs.annotate(sort_by_field=Max(max_field)).order_by( sort_order, "store__pootle_path", "index")) # text search if search and sfields: qs = UnitTextSearch(qs).search(search, [sfields], "exact" in soptions) find_unit = (not offset and language_code and project_code and filename and uids) start = offset total = qs.count() if find_unit: # find the uid in the Store uid_list = list(qs.values_list("pk", flat=True)) unit_index = uid_list.index(uids[0]) start = int(unit_index / (2 * limit)) * (2 * limit) end = min(start + (2 * limit), total) unit_groups = [] units_by_path = groupby( qs.values(*GroupedResults.select_fields)[start:end], lambda x: x["store__pootle_path"]) for pootle_path, units in units_by_path: unit_groups.append({pootle_path: StoreResults(units).data}) total = qs.count() return total, start, min(end, total), unit_groups
def get_detailed_report_context(user, month): [start, end] = get_date_interval(month) totals = { "translated": {}, "reviewed": {}, "suggested": 0, "paid_tasks": {}, "all": 0, } items = [] if user and start and end: scores = ( ScoreLog.objects.select_related("submission__unit__store") .filter(user=user, creation_time__gte=start, creation_time__lte=end) .order_by("creation_time") ) tasks = PaidTask.objects.filter( user=user, datetime__gte=start, datetime__lte=end ).order_by("datetime") items = [] for score in scores.iterator(): action = None subtotal = None wordcount = None translated, reviewed = score.get_paid_wordcounts() translated_details = {} if translated is not None: action = ReportActionTypes.TRANSLATION subtotal = score.rate * translated wordcount = translated translated_details["raw_rate"] = score.rate - score.review_rate translated_details["raw_translated_wordcount"] = score.wordcount * ( 1 - score.get_similarity() ) translated_details["raw_subtotal"] = ( translated_details["raw_translated_wordcount"] * translated_details["raw_rate"] ) translated_details["review_subtotal"] = ( score.wordcount * score.review_rate ) if score.rate in totals["translated"]: totals["translated"][score.rate]["words"] += translated else: totals["translated"][score.rate] = {"words": translated} elif reviewed is not None: action = ReportActionTypes.REVIEW subtotal = score.review_rate * reviewed wordcount = reviewed if score.review_rate in totals["reviewed"]: totals["reviewed"][score.review_rate]["words"] += reviewed else: totals["reviewed"][score.review_rate] = {"words": reviewed} suggested = score.get_suggested_wordcount() if suggested is not None: action = ReportActionTypes.SUGGESTION wordcount = suggested totals["suggested"] += suggested if action is not None: items.append( { "score": score, "action": action, "action_name": ReportActionTypes.NAMES_MAP[action], "similarity": score.get_similarity() * 100, "subtotal": subtotal, "wordcount": wordcount, "source_wordcount": score.wordcount, "translated_details": translated_details, "creation_time": score.creation_time, } ) paid_tasks = totals["paid_tasks"] for task in tasks.iterator(): subtotal = task.amount * task.rate items.append( { "action": task.task_type, "action_name": PaidTask.get_task_type_title(task.task_type), "subtotal": subtotal, "task": task, "creation_time": task.datetime, } ) totals["all"] += subtotal if task.task_type not in paid_tasks: paid_tasks[task.task_type] = { "rates": {}, "action": PaidTask.get_task_type_title(task.task_type), } if task.rate in paid_tasks[task.task_type]["rates"]: current = paid_tasks[task.task_type]["rates"][task.rate] current["amount"] += task.amount current["subtotal"] += subtotal else: paid_tasks[task.task_type]["rates"][task.rate] = { "amount": task.amount, "subtotal": subtotal, } for rate in totals["translated"]: totals["translated"][rate]["rounded_words"] = int( round(totals["translated"][rate]["words"]) ) totals["translated"][rate]["subtotal"] = ( rate * totals["translated"][rate]["rounded_words"] ) totals["all"] += totals["translated"][rate]["subtotal"] for rate in totals["reviewed"]: totals["reviewed"][rate]["subtotal"] = ( rate * totals["reviewed"][rate]["words"] ) totals["all"] += totals["reviewed"][rate]["subtotal"] totals["all"] = round(totals["all"], 2) + 0 items = sorted(items, key=lambda x: x["creation_time"]) if user != "" and user.currency is None: user.currency = CURRENCIES[0][0] return { "items": items, "object": user, "start": start, "end": end, "next": start.replace(day=1) + timedelta(days=31), "previous": start.replace(day=1) - timedelta(days=1), "totals": totals, "utc_offset": start.strftime("%z"), "action_types": ReportActionTypes, }
def get_detailed_report_context(user, month): [start, end] = get_date_interval(month) totals = { 'translated': {}, 'reviewed': {}, 'total': 0, 'paid_tasks': {}, 'all': 0 } if user and start and end: scores = ScoreLog.objects \ .select_related('submission__unit__store') \ .filter(user=user, creation_time__gte=start, creation_time__lte=end) \ .order_by('creation_time') tasks = PaidTask.objects \ .filter(user=user, datetime__gte=start, datetime__lte=end) \ .order_by('datetime') scores = list(scores) tasks = list(tasks) for score in scores: translated, reviewed = score.get_paid_words() if translated is not None: score.action = PaidTask.get_task_type_title( PaidTaskTypes.TRANSLATION) score.subtotal = score.rate * translated score.words = translated if score.rate in totals['translated']: totals['translated'][score.rate]['words'] += translated else: totals['translated'][score.rate] = {'words': translated} elif reviewed is not None: score.action = PaidTask.get_task_type_title( PaidTaskTypes.REVIEW) score.subtotal = score.review_rate * reviewed score.words = score.wordcount if score.review_rate in totals['reviewed']: totals['reviewed'][score.review_rate]['words'] += reviewed else: totals['reviewed'][score.review_rate] = {'words': reviewed} score.similarity = score.get_similarity() * 100 paid_tasks = totals['paid_tasks'] for task in tasks: task.action = PaidTask.get_task_type_title(task.task_type) task.subtotal = task.amount * task.rate totals['all'] += task.subtotal if task.task_type not in paid_tasks: paid_tasks[task.task_type] = { 'rates': {}, 'action': task.action } if task.rate in paid_tasks[task.task_type]['rates']: current = paid_tasks[task.task_type]['rates'][task.rate] current['amount'] += task.amount current['subtotal'] += task.subtotal else: paid_tasks[task.task_type]['rates'][task.rate] = { 'amount': task.amount, 'subtotal': task.subtotal, } for rate, words in totals['translated'].items(): totals['translated'][rate]['words'] = totals['translated'][rate][ 'words'] totals['translated'][rate][ 'subtotal'] = rate * totals['translated'][rate]['words'] totals['all'] += totals['translated'][rate]['subtotal'] for rate, words in totals['reviewed'].items(): totals['reviewed'][rate]['words'] = totals['reviewed'][rate][ 'words'] totals['reviewed'][rate][ 'subtotal'] = rate * totals['reviewed'][rate]['words'] totals['all'] += totals['reviewed'][rate]['subtotal'] totals['all'] = totals['all'] items = [{'score': x, 'creation_time': x.creation_time} for x in scores] + \ [{'task': x, 'creation_time': x.datetime} for x in tasks] items = sorted(items, key=lambda x: x['creation_time']) if user != '' and user.currency is None: user.currency = CURRENCIES[0][0] return { 'items': items, 'object': user, 'start': start, 'end': end, 'next': start.replace(day=1) + timedelta(days=31), 'previous': start.replace(day=1) - timedelta(days=1), 'totals': totals, 'utc_offset': start.strftime("%z"), }
def get_step_query(request, units_queryset): """Narrows down unit query to units matching conditions in GET.""" if 'filter' in request.GET: unit_filter = request.GET['filter'] username = request.GET.get('user', None) modified_since = request.GET.get('modified-since', None) month = request.GET.get('month', None) sort_by_param = request.GET.get('sort', None) sort_on = 'units' user = request.profile if username is not None: User = get_user_model() try: user = User.objects.get(username=username) except User.DoesNotExist: pass if unit_filter: match_queryset = units_queryset.none() if unit_filter == 'all': match_queryset = units_queryset elif unit_filter == 'translated': match_queryset = units_queryset.filter(state=TRANSLATED) elif unit_filter == 'untranslated': match_queryset = units_queryset.filter(state=UNTRANSLATED) elif unit_filter == 'fuzzy': match_queryset = units_queryset.filter(state=FUZZY) elif unit_filter == 'incomplete': match_queryset = units_queryset.filter( Q(state=UNTRANSLATED) | Q(state=FUZZY), ) elif unit_filter == 'suggestions': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING).distinct() elif unit_filter in ('my-suggestions', 'user-suggestions'): match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING, suggestion__user=user, ).distinct() sort_on = 'suggestions' elif unit_filter == 'user-suggestions-accepted': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.ACCEPTED, suggestion__user=user, ).distinct() elif unit_filter == 'user-suggestions-rejected': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.REJECTED, suggestion__user=user, ).distinct() elif unit_filter in ('my-submissions', 'user-submissions'): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).distinct() sort_on = 'submissions' elif (unit_filter in ('my-submissions-overwritten', 'user-submissions-overwritten')): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).exclude(submitted_by=user).distinct() elif unit_filter == 'checks': if 'checks' in request.GET: checks = request.GET['checks'].split(',') if checks: match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__name__in=checks, ).distinct() elif 'category' in request.GET: category_name = request.GET['category'] try: category = get_category_id(category_name) except KeyError: raise Http404 match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__category=category, ).distinct() if modified_since is not None: datetime_obj = parse_datetime(modified_since) if datetime_obj is not None: match_queryset = match_queryset.filter( submitted_on__gt=datetime_obj, ).distinct() if month is not None: [start, end] = get_date_interval(month) match_queryset = match_queryset.filter( submitted_on__gte=start, submitted_on__lte=end, ).distinct() sort_by = ALLOWED_SORTS[sort_on].get(sort_by_param, None) if sort_by is not None: if sort_on in SIMPLY_SORTED: match_queryset = match_queryset.order_by(sort_by) else: # Omit leading `-` sign if sort_by[0] == '-': max_field = sort_by[1:] sort_order = '-sort_by_field' else: max_field = sort_by sort_order = 'sort_by_field' # It's necessary to use `Max()` here because we can't # use `distinct()` and `order_by()` at the same time # (unless PostreSQL is used and `distinct(field_name)`) match_queryset = match_queryset \ .annotate(sort_by_field=Max(max_field)) \ .order_by(sort_order) units_queryset = match_queryset if 'search' in request.GET and 'sfields' in request.GET: # Accept `sfields` to be a comma-separated string of fields (#46) GET = request.GET.copy() sfields = GET['sfields'] if isinstance(sfields, unicode) and u',' in sfields: GET.setlist('sfields', sfields.split(u',')) # use the search form for validation only search_form = make_search_form(GET) if search_form.is_valid(): units_queryset = get_search_step_query(search_form, units_queryset) return units_queryset
def get_step_query(request, units_queryset): """Narrows down unit query to units matching conditions in GET.""" if 'filter' in request.GET: unit_filter = request.GET['filter'] username = request.GET.get('user', None) modified_since = request.GET.get('modified-since', None) month = request.GET.get('month', None) sort_by_param = request.GET.get('sort', None) sort_on = 'units' user = request.profile if username is not None: User = get_user_model() try: user = User.objects.get(username=username) except User.DoesNotExist: pass if unit_filter: match_queryset = units_queryset.none() if unit_filter == 'all': match_queryset = units_queryset elif unit_filter == 'translated': match_queryset = units_queryset.filter(state=TRANSLATED) elif unit_filter == 'untranslated': match_queryset = units_queryset.filter(state=UNTRANSLATED) elif unit_filter == 'fuzzy': match_queryset = units_queryset.filter(state=FUZZY) elif unit_filter == 'incomplete': match_queryset = units_queryset.filter( Q(state=UNTRANSLATED) | Q(state=FUZZY), ) elif unit_filter == 'suggestions': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING ).distinct() elif unit_filter in ('my-suggestions', 'user-suggestions'): match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING, suggestion__user=user, ).distinct() sort_on = 'suggestions' elif unit_filter == 'user-suggestions-accepted': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.ACCEPTED, suggestion__user=user, ).distinct() elif unit_filter == 'user-suggestions-rejected': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.REJECTED, suggestion__user=user, ).distinct() elif unit_filter in ('my-submissions', 'user-submissions'): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).distinct() sort_on = 'submissions' elif (unit_filter in ('my-submissions-overwritten', 'user-submissions-overwritten')): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).exclude(submitted_by=user).distinct() elif unit_filter == 'checks' and 'checks' in request.GET: checks = request.GET['checks'].split(',') if checks: match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__name__in=checks, ).distinct() if modified_since is not None: datetime_obj = parse_datetime(modified_since) if datetime_obj is not None: match_queryset = match_queryset.filter( submitted_on__gt=datetime_obj, ).distinct() if month is not None: [start, end] = get_date_interval(month) match_queryset = match_queryset.filter( submitted_on__gte=start, submitted_on__lte=end, ).distinct() sort_by = ALLOWED_SORTS[sort_on].get(sort_by_param, None) if sort_by is not None: if sort_on in SIMPLY_SORTED: if sort_by == 'priority': # TODO: Replace the following extra() with Coalesce # https://docs.djangoproject.com/en/1.8/ref/models/database-functions/#coalesce # once we drop support for Django<1.8.x: # .annotate( # sort_by_field=Coalesce( # Max("vfolders__priority"), # Value(1) # ) # ).order_by("-sort_by_field") match_queryset = match_queryset.extra(select={'sort_by_field': """ SELECT COALESCE(MAX(virtualfolder_virtualfolder.priority), 1) FROM virtualfolder_virtualfolder INNER JOIN virtualfolder_virtualfolder_units ON virtualfolder_virtualfolder.id = virtualfolder_virtualfolder_units.virtualfolder_id WHERE virtualfolder_virtualfolder_units.unit_id = pootle_store_unit.id """}).extra(order_by=['-sort_by_field']) else: match_queryset = match_queryset.order_by(sort_by) else: # Omit leading `-` sign if sort_by[0] == '-': max_field = sort_by[1:] sort_order = '-sort_by_field' else: max_field = sort_by sort_order = 'sort_by_field' # It's necessary to use `Max()` here because we can't # use `distinct()` and `order_by()` at the same time # (unless PostreSQL is used and `distinct(field_name)`) match_queryset = match_queryset \ .annotate(sort_by_field=Max(max_field)) \ .order_by(sort_order) units_queryset = match_queryset if 'search' in request.GET and 'sfields' in request.GET: # Accept `sfields` to be a comma-separated string of fields (#46) GET = request.GET.copy() sfields = GET['sfields'] if isinstance(sfields, unicode) and u',' in sfields: GET.setlist('sfields', sfields.split(u',')) # use the search form for validation only search_form = make_search_form(GET) if search_form.is_valid(): units_queryset = get_search_step_query(search_form, units_queryset) return units_queryset
def get_step_query(request, units_queryset): """Narrows down unit query to units matching conditions in GET.""" if 'filter' in request.GET: unit_filter = request.GET['filter'] username = request.GET.get('user', None) modified_since = request.GET.get('modified-since', None) month = request.GET.get('month', None) sort_by_param = request.GET.get('sort', None) sort_on = 'units' user = request.profile if username is not None: User = get_user_model() try: user = User.objects.get(username=username) except User.DoesNotExist: pass if unit_filter: match_queryset = units_queryset.none() if unit_filter == 'all': match_queryset = units_queryset elif unit_filter == 'translated': match_queryset = units_queryset.filter(state=TRANSLATED) elif unit_filter == 'untranslated': match_queryset = units_queryset.filter(state=UNTRANSLATED) elif unit_filter == 'fuzzy': match_queryset = units_queryset.filter(state=FUZZY) elif unit_filter == 'incomplete': match_queryset = units_queryset.filter( Q(state=UNTRANSLATED) | Q(state=FUZZY), ) elif unit_filter == 'suggestions': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING).distinct() elif unit_filter in ('my-suggestions', 'user-suggestions'): match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING, suggestion__user=user, ).distinct() sort_on = 'suggestions' elif unit_filter == 'user-suggestions-accepted': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.ACCEPTED, suggestion__user=user, ).distinct() elif unit_filter == 'user-suggestions-rejected': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.REJECTED, suggestion__user=user, ).distinct() elif unit_filter in ('my-submissions', 'user-submissions'): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).distinct() sort_on = 'submissions' elif (unit_filter in ('my-submissions-overwritten', 'user-submissions-overwritten')): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).exclude(submitted_by=user).distinct() elif unit_filter == 'checks' and 'checks' in request.GET: checks = request.GET['checks'].split(',') if checks: match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__name__in=checks, ).distinct() if modified_since is not None: datetime_obj = parse_datetime(modified_since) if datetime_obj is not None: match_queryset = match_queryset.filter( submitted_on__gt=datetime_obj, ).distinct() if month is not None: [start, end] = get_date_interval(month) match_queryset = match_queryset.filter( submitted_on__gte=start, submitted_on__lte=end, ).distinct() sort_by = ALLOWED_SORTS[sort_on].get(sort_by_param, None) if sort_by is not None: if sort_on in SIMPLY_SORTED: if sort_by == 'priority': # TODO: Replace the following extra() with Coalesce # https://docs.djangoproject.com/en/1.8/ref/models/database-functions/#coalesce # once we drop support for Django<1.8.x: # .annotate( # sort_by_field=Coalesce( # Max("vfolders__priority"), # Value(1) # ) # ).order_by("-sort_by_field") match_queryset = match_queryset.extra( select={ 'sort_by_field': """ SELECT COALESCE(MAX(virtualfolder_virtualfolder.priority), 1) FROM virtualfolder_virtualfolder INNER JOIN virtualfolder_virtualfolder_units ON virtualfolder_virtualfolder.id = virtualfolder_virtualfolder_units.virtualfolder_id WHERE virtualfolder_virtualfolder_units.unit_id = pootle_store_unit.id """ }).extra(order_by=['-sort_by_field']) else: match_queryset = match_queryset.order_by(sort_by) else: # Omit leading `-` sign if sort_by[0] == '-': max_field = sort_by[1:] sort_order = '-sort_by_field' else: max_field = sort_by sort_order = 'sort_by_field' # It's necessary to use `Max()` here because we can't # use `distinct()` and `order_by()` at the same time # (unless PostreSQL is used and `distinct(field_name)`) match_queryset = match_queryset \ .annotate(sort_by_field=Max(max_field)) \ .order_by(sort_order) units_queryset = match_queryset if 'search' in request.GET and 'sfields' in request.GET: # Accept `sfields` to be a comma-separated string of fields (#46) GET = request.GET.copy() sfields = GET['sfields'] if isinstance(sfields, unicode) and u',' in sfields: GET.setlist('sfields', sfields.split(u',')) # use the search form for validation only search_form = make_search_form(GET) if search_form.is_valid(): units_queryset = get_search_step_query(search_form, units_queryset) return units_queryset
def clean_month(self): if self.cleaned_data["month"]: return get_date_interval(self.cleaned_data["month"].strftime("%Y-%m"))
def calculate_search_results(kwargs, user): pootle_path = kwargs["pootle_path"] category = kwargs.get("category") checks = kwargs.get("checks") offset = kwargs.get("offset", 0) limit = kwargs.get("count", 9) modified_since = kwargs.get("modified-since") month = kwargs.get("month") search = kwargs.get("search") sfields = kwargs.get("sfields") soptions = kwargs.get("soptions", []) sort = kwargs.get("sort", None) vfolder = kwargs.get("vfolder", None) language_code, project_code, dir_path_, filename = ( split_pootle_path(kwargs["pootle_path"])) uids = [ int(x) for x in kwargs.get("uids", "").split(",") if x] unit_filter = kwargs.get("filter") if modified_since: modified_since = parse_datetime(modified_since) if month: month = get_date_interval(month) path_kwargs = { k: v for k, v in resolve(pootle_path).kwargs.items() if k in [ "language_code", "project_code", "dir_path", "filename"]} qs = ( Unit.objects.get_translatable(user=user, **path_kwargs) .order_by("store", "index")) if vfolder is not None: qs = qs.filter(store__vfolders=vfolder) # if "filter" is present in request vars... if unit_filter: # filter the results accordingly qs = UnitSearchFilter().filter( qs, unit_filter, user=user, checks=checks, category=get_category_id(category)) # filter by modified if modified_since: qs = qs.filter(change__submitted_on__gt=modified_since).distinct() if month is not None: qs = qs.filter( change__submitted_on__gte=month[0], change__submitted_on__lte=month[1]).distinct() # sort results if unit_filter in ["my-suggestions", "user-suggestions"]: sort_on = "suggestions" elif unit_filter in ["my-submissions", "user-submissions"]: sort_on = "submissions" else: sort_on = "units" sort_by = ALLOWED_SORTS[sort_on].get(sort, None) if sort_by is not None: # filtered sort if sort_on in SIMPLY_SORTED: qs = qs.order_by(sort_by, "store__pootle_path", "index") else: max_field, sort_order = get_max_and_order_fields(sort_by) qs = ( qs.annotate(sort_by_field=Max(max_field)) .order_by(sort_order, "store__pootle_path", "index")) # text search if search and sfields: qs = UnitTextSearch(qs).search( search, [sfields], "exact" in soptions) find_unit = ( not offset and language_code and project_code and filename and uids) start = offset total = qs.count() if find_unit: # find the uid in the Store uid_list = list(qs.values_list("pk", flat=True)) unit_index = uid_list.index(uids[0]) start = int(unit_index / (2 * limit)) * (2 * limit) end = min(start + (2 * limit), total) unit_groups = [] units_by_path = groupby( qs.values(*GroupedResults.select_fields)[start:end], lambda x: x["store__pootle_path"]) for pootle_path, units in units_by_path: unit_groups.append( {pootle_path: StoreResults(units).data}) total = qs.count() return total, start, min(end, total), unit_groups
def get_detailed_report_context(user, month): [start, end] = get_date_interval(month) totals = {'translated': {}, 'reviewed': {}, 'total': 0, 'paid_tasks': {}, 'all': 0} if user and start and end: scores = ScoreLog.objects \ .select_related('submission__unit__store') \ .filter(user=user, creation_time__gte=start, creation_time__lte=end) \ .order_by('creation_time') tasks = PaidTask.objects \ .filter(user=user, datetime__gte=start, datetime__lte=end) \ .order_by('datetime') scores = list(scores) tasks = list(tasks) for score in scores: translated, reviewed = score.get_paid_words() if translated is not None: score.action = PaidTask.get_task_type_title(PaidTaskTypes.TRANSLATION) score.subtotal = score.rate * translated score.words = translated if score.rate in totals['translated']: totals['translated'][score.rate]['words'] += translated else: totals['translated'][score.rate] = {'words': translated} elif reviewed is not None: score.action = PaidTask.get_task_type_title(PaidTaskTypes.REVIEW) score.subtotal = score.review_rate * reviewed score.words = score.wordcount if score.review_rate in totals['reviewed']: totals['reviewed'][score.review_rate]['words'] += reviewed else: totals['reviewed'][score.review_rate] = {'words': reviewed} score.similarity = score.get_similarity() * 100 paid_tasks = totals['paid_tasks'] for task in tasks: task.action = PaidTask.get_task_type_title(task.task_type) task.subtotal = task.amount * task.rate totals['all'] += task.subtotal if task.task_type not in paid_tasks: paid_tasks[task.task_type] = { 'rates': {}, 'action': task.action } if task.rate in paid_tasks[task.task_type]['rates']: current = paid_tasks[task.task_type]['rates'][task.rate] current['amount'] += task.amount current['subtotal'] += task.subtotal else: paid_tasks[task.task_type]['rates'][task.rate] = { 'amount': task.amount, 'subtotal': task.subtotal, } for rate, words in totals['translated'].items(): totals['translated'][rate]['words'] = totals['translated'][rate]['words'] totals['translated'][rate]['subtotal'] = rate * totals['translated'][rate]['words'] totals['all'] += totals['translated'][rate]['subtotal'] for rate, words in totals['reviewed'].items(): totals['reviewed'][rate]['words'] = totals['reviewed'][rate]['words'] totals['reviewed'][rate]['subtotal'] = rate * totals['reviewed'][rate]['words'] totals['all'] += totals['reviewed'][rate]['subtotal'] totals['all'] = totals['all'] items = [{'score': x, 'creation_time': x.creation_time} for x in scores] + \ [{'task': x, 'creation_time': x.datetime} for x in tasks] items = sorted(items, key=lambda x: x['creation_time']) if user != '' and user.currency is None: user.currency = CURRENCIES[0][0] return { 'items': items, 'object': user, 'start': start, 'end': end, 'next': start.replace(day=1) + timedelta(days=31), 'previous': start.replace(day=1) - timedelta(days=1), 'totals': totals, 'utc_offset': start.strftime("%z"), }
def get_step_query(request, units_queryset): """Narrows down unit query to units matching conditions in GET.""" if 'filter' in request.GET: unit_filter = request.GET['filter'] username = request.GET.get('user', None) modified_since = request.GET.get('modified-since', None) month = request.GET.get('month', None) sort_by_param = request.GET.get('sort', None) sort_on = 'units' user = request.profile if username is not None: User = get_user_model() try: user = User.objects.get(username=username) except User.DoesNotExist: pass if unit_filter: match_queryset = units_queryset.none() if unit_filter == 'all': match_queryset = units_queryset elif unit_filter == 'translated': match_queryset = units_queryset.filter(state=TRANSLATED) elif unit_filter == 'untranslated': match_queryset = units_queryset.filter(state=UNTRANSLATED) elif unit_filter == 'fuzzy': match_queryset = units_queryset.filter(state=FUZZY) elif unit_filter == 'incomplete': match_queryset = units_queryset.filter( Q(state=UNTRANSLATED) | Q(state=FUZZY), ) elif unit_filter == 'suggestions': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING).distinct() elif unit_filter in ('my-suggestions', 'user-suggestions'): match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.PENDING, suggestion__user=user, ).distinct() sort_on = 'suggestions' elif unit_filter == 'user-suggestions-accepted': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.ACCEPTED, suggestion__user=user, ).distinct() elif unit_filter == 'user-suggestions-rejected': match_queryset = units_queryset.filter( suggestion__state=SuggestionStates.REJECTED, suggestion__user=user, ).distinct() elif unit_filter in ('my-submissions', 'user-submissions'): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).distinct() sort_on = 'submissions' elif (unit_filter in ('my-submissions-overwritten', 'user-submissions-overwritten')): match_queryset = units_queryset.filter( submission__submitter=user, submission__type__in=SubmissionTypes.EDIT_TYPES, ).exclude(submitted_by=user).distinct() elif unit_filter == 'checks' and 'checks' in request.GET: checks = request.GET['checks'].split(',') if checks: match_queryset = units_queryset.filter( qualitycheck__false_positive=False, qualitycheck__name__in=checks, ).distinct() if modified_since is not None: datetime_obj = parse_datetime(modified_since) if datetime_obj is not None: match_queryset = match_queryset.filter( submitted_on__gt=datetime_obj, ).distinct() if month is not None: [start, end] = get_date_interval(month) match_queryset = match_queryset.filter( submitted_on__gte=start, submitted_on__lte=end, ).distinct() sort_by = ALLOWED_SORTS[sort_on].get(sort_by_param, None) if sort_by is not None: if sort_on in SIMPLY_SORTED: match_queryset = match_queryset.order_by(sort_by) else: # Omit leading `-` sign if sort_by[0] == '-': max_field = sort_by[1:] sort_order = '-sort_by_field' else: max_field = sort_by sort_order = 'sort_by_field' # It's necessary to use `Max()` here because we can't # use `distinct()` and `order_by()` at the same time # (unless PostreSQL is used and `distinct(field_name)`) match_queryset = match_queryset \ .annotate(sort_by_field=Max(max_field)) \ .order_by(sort_order) units_queryset = match_queryset if 'search' in request.GET and 'sfields' in request.GET: # Accept `sfields` to be a comma-separated string of fields (#46) GET = request.GET.copy() sfields = GET['sfields'] if isinstance(sfields, unicode) and u',' in sfields: GET.setlist('sfields', sfields.split(u',')) # use the search form for validation only search_form = make_search_form(GET) if search_form.is_valid(): units_queryset = get_search_step_query(search_form, units_queryset) return units_queryset