US #50: Neighbor taking into account issues ordering

remotes/origin/enhancement/email-actions
ikame 2014-02-28 14:59:12 +01:00
parent 9315e7b562
commit 778fce6257
3 changed files with 200 additions and 33 deletions

View File

@ -22,27 +22,32 @@ class NeighborsMixin:
"""
if queryset is None:
queryset = type(self).objects.get_queryset()
if not self._get_queryset_order_by(queryset):
queryset = queryset.order_by(*self._get_order_by())
queryset = queryset.order_by(*self._get_order_by(queryset))
queryset = queryset.filter(~Q(id=self.id))
return self._get_previous_neighbor(queryset), self._get_next_neighbor(queryset)
def _get_queryset_order_by(self, queryset):
return queryset.query.order_by or []
return queryset.query.order_by
def _get_order_by(self):
return self._meta.ordering
def _get_order_by(self, queryset):
return self._get_queryset_order_by(queryset) or self._meta.ordering
def _field(self, field):
return getattr(self, field.lstrip("-"))
def _get_order_field_value(self, field):
field = field.lstrip("-")
obj = self
for attr in field.split("__"):
value = getattr(obj, attr, None)
if value is None:
break
obj = value
def _filter(self, field, inc, desc):
return value
def _transform_order_field_into_lookup(self, field, operator, operator_if_order_desc):
if field.startswith("-"):
field = field[1:]
operator = desc
else:
operator = inc
operator = operator_if_order_desc
return field, operator
def _format(self, value):
@ -51,30 +56,39 @@ class NeighborsMixin:
return value
def _or(self, conditions):
condition = conditions[0]
result = Q(**{key: self._format(condition[key]) for key in condition})
for condition in conditions[1:]:
result = result | Q(**{key: self._format(condition[key]) for key in condition})
result = Q()
for condition in conditions:
result |= Q(**{key: self._format(condition[key]) for key in condition})
return result
def _get_prev_neighbor_filters(self, queryset):
conds = [{"{}__{}".format(*self._filter(field, "lt", "gt")): self._field(field)}
for field in self._get_queryset_order_by(queryset)]
return self._or(conds)
def _get_neighbor_filters(self, queryset, operator, operator_if_order_desc):
conds = []
for field in self._get_queryset_order_by(queryset):
value = self._get_order_field_value(field)
if value is None:
continue
lookup_field, operator = self._transform_order_field_into_lookup(
field, operator, operator_if_order_desc)
lookup = "{}__{}".format(lookup_field, operator)
conds.append({lookup: value})
return conds
def _get_previous_neighbor(self, queryset):
try:
return queryset.filter(self._get_prev_neighbor_filters(queryset)).reverse()[0]
except IndexError:
return None
def _get_prev_neighbor_filters(self, queryset):
return self._get_neighbor_filters(queryset, "lte", "gte")
def _get_next_neighbor_filters(self, queryset):
conds = [{"{}__{}".format(*self._filter(field, "gt", "lt")): self._field(field)}
for field in self._get_queryset_order_by(queryset)]
return self._or(conds)
return self._get_neighbor_filters(queryset, "gte", "lte")
def _get_next_neighbor(self, queryset):
def _get_previous_neighbor(self, queryset):
queryset = queryset.filter(self._or(self._get_prev_neighbor_filters(queryset)))
try:
return queryset.filter(self._get_next_neighbor_filters(queryset))[0]
return queryset.reverse()[0]
except IndexError:
return None
def _get_next_neighbor(self, queryset):
queryset = queryset.filter(self._or(self._get_next_neighbor_filters(queryset)))
try:
return queryset[0]
except IndexError:
return None

View File

@ -81,6 +81,157 @@ class Issue(NeighborsMixin, WatchedMixin, BlockedMixin):
def __str__(self):
return "({1}) {0}".format(self.ref, self.subject)
def _get_order_by(self, queryset):
ordering = self._get_queryset_order_by(queryset)
if ordering:
main_order = ordering[0]
need_extra_ordering = ("severity", "-severity", "owner__first_name",
"-owner__first_name", "status", "-status", "priority",
"-priority", "assigned_to__first_name",
"-assigned_to__first_name")
if main_order in need_extra_ordering:
ordering += self._meta.ordering
return ordering
def _get_prev_neighbor_filters(self, queryset):
conds = super()._get_prev_neighbor_filters(queryset)
main_order = queryset.query.order_by[0]
if main_order == "severity":
conds = [{"severity__order__lt": self.severity.order},
{"severity__order": self.severity.order,
"created_date__lt": self.created_date}]
elif main_order == "-severity":
conds = [{"severity__order__gt": self.severity.order},
{"severity__order": self.severity.order,
"created_date__lt": self.created_date}]
elif main_order == "status":
conds = [{"status__order__lt": self.status.order},
{"status__order": self.status.order,
"created_date__lt": self.created_date}]
elif main_order == "-status":
conds = [{"status__order__gt": self.status.order},
{"status__order": self.status.order,
"created_date__lt": self.created_date}]
elif main_order == "priority":
conds = [{"priority__order__lt": self.priority.order},
{"priority__order": self.priority.order,
"created_date__lt": self.created_date}]
elif main_order == "-priority":
conds = [{"priority__order__gt": self.priority.order},
{"priority__order": self.priority.order,
"created_date__lt": self.created_date}]
elif main_order == "owner__first_name":
conds = [{"owner__first_name": self.owner.first_name,
"owner__last_name": self.owner.last_name,
"created_date__lt": self.created_date},
{"owner__first_name": self.owner.first_name,
"owner__last_name__lt": self.owner.last_name},
{"owner__first_name__lt": self.owner.first_name}]
elif main_order == "-owner__first_name":
conds = [{"owner__first_name": self.owner.first_name,
"owner__last_name": self.owner.last_name,
"created_date__lt": self.created_date},
{"owner__first_name": self.owner.first_name,
"owner__last_name__gt": self.owner.last_name},
{"owner__first_name__gt": self.owner.first_name}]
elif main_order == "assigned_to__first_name":
if self.assigned_to:
conds = [{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name": self.assigned_to.last_name,
"created_date__lt": self.created_date},
{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name__lt": self.assigned_to.last_name},
{"assigned_to__first_name__lt": self.assigned_to.first_name}]
else:
conds = [{"assigned_to__isnull": True,
"created_date__lt": self.created_date},
{"assigned_to__isnull": False}]
elif main_order == "-assigned_to__first_name":
if self.assigned_to:
conds = [{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name": self.assigned_to.last_name,
"created_date__lt": self.created_date},
{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name__gt": self.assigned_to.last_name},
{"assigned_to__first_name__gt": self.assigned_to.first_name},
{"assigned_to__isnull": True}]
else:
conds = [{"assigned_to__isnull": True,
"created_date__lt": self.created_date},
{"assigned_to__isnull": False}]
return conds
def _get_next_neighbor_filters(self, queryset):
conds = super()._get_next_neighbor_filters(queryset)
ordering = queryset.query.order_by
main_order = ordering[0]
if main_order == "severity":
conds = [{"severity__order__gt": self.severity.order},
{"severity__order": self.severity.order,
"created_date__gt": self.created_date}]
elif main_order == "-severity":
conds = [{"severity__order__lt": self.severity.order},
{"severity__order": self.severity.order,
"created_date__gt": self.created_date}]
elif main_order == "status":
conds = [{"status__order__gt": self.status.order},
{"status__order": self.status.order,
"created_date__gt": self.created_date}]
elif main_order == "-status":
conds = [{"status__order__lt": self.status.order},
{"status__order": self.status.order,
"created_date__gt": self.created_date}]
elif main_order == "priority":
conds = [{"priority__order__gt": self.priority.order},
{"priority__order": self.priority.order,
"created_date__gt": self.created_date}]
elif main_order == "-priority":
conds = [{"priority__order__lt": self.priority.order},
{"priority__order": self.priority.order,
"created_date__gt": self.created_date}]
elif main_order == "owner__first_name":
conds = [{"owner__first_name": self.owner.first_name,
"owner__last_name": self.owner.last_name,
"created_date__gt": self.created_date},
{"owner__first_name": self.owner.first_name,
"owner__last_name__gt": self.owner.last_name},
{"owner__first_name__gt": self.owner.first_name}]
elif main_order == "-owner__first_name":
conds = [{"owner__first_name": self.owner.first_name,
"owner__last_name": self.owner.last_name,
"created_date__gt": self.created_date},
{"owner__first_name": self.owner.first_name,
"owner__last_name__lt": self.owner.last_name},
{"owner__first_name__lt": self.owner.first_name}]
elif main_order == "assigned_to__first_name":
if self.assigned_to:
conds = [{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name": self.assigned_to.last_name,
"created_date__gt": self.created_date},
{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name__gt": self.assigned_to.last_name},
{"assigned_to__first_name__gt": self.assigned_to.first_name},
{"assigned_to__isnull": True}]
else:
conds = [{"assigned_to__isnull": True,
"created_date__gt": self.created_date}]
elif main_order == "-assigned_to__first_name":
if self.assigned_to:
conds = [{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name": self.assigned_to.last_name,
"created_date__gt": self.created_date},
{"assigned_to__first_name": self.assigned_to.first_name,
"assigned_to__last_name__lt": self.assigned_to.last_name},
{"assigned_to__first_name__lt": self.assigned_to.first_name}]
else:
conds = [{"assigned_to__isnull": True,
"created_date__gt": self.created_date},
{"assigned_to__isnull": False}]
return conds
@property
def is_closed(self):
return self.status.is_closed

View File

@ -113,12 +113,14 @@ class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model):
return "<UserStory %s>" % (self.id)
def _get_prev_neighbor_filters(self, queryset):
return self._or([{"order__lt": "{obj.order}"},
{"order__lte": "{obj.order}", "ref__lt": "{obj.ref}"}])
conds = [{"order__lt": "{obj.order}"},
{"order__lte": "{obj.order}", "ref__lt": "{obj.ref}"}]
return conds
def _get_next_neighbor_filters(self, queryset):
return self._or([{"order__gt": "{obj.order}"},
{"order__gte": "{obj.order}", "ref__gt": "{obj.ref}"}])
conds = [{"order__gt": "{obj.order}"},
{"order__gte": "{obj.order}", "ref__gt": "{obj.ref}"}]
return conds
def get_role_points(self):
return self.role_points