Repository: pretix/pretix

Issue:
Sorting of filtered order list
When you select some filter on the orders list, only the orders matching the filter are displayed. However if you then click the sorting icons on any of the columns, the result list switches to display *all* orders (sorted).
Sorting of filtered order list
When you select some filter on the orders list, only the orders matching the filter are displayed. However if you then click the sorting icons on any of the columns, the result list switches to display *all* orders (sorted).


Discussion:
Hey, 

I'd like to give this a try. I'll let you know when I've come up with something or need help :)) 
Hey, 

I think I found out what happens, but I'm not super sure… Here goes: 

Both ordering and filtering requests of the orders-list are handled by an EventOrderFilterForm. 
This has an "ordering"-field inherited by FilterForm and defined in [the filter-forms](https://github.com/pretix/pretix/blob/master/src/pretix/control/forms/filter.py#L24). The choices of this field are set to an empty tuple, since the orders-variable of a FilterForm is an empty dict. 
Thus, validating the Form fails when an ordering is present, leading to the orders not being filtered in [the orders-view](https://github.com/pretix/pretix/blob/master/src/pretix/control/views/orders.py#L70).

To solve this, I think that either orders has to be set for an EventOrderFilterForm or an OrderFilterForm, though I don't know to what, or the "ordering"-field should be set to contain valid choices for an ordering. Assuming that one of these propositions is the way to go, in both cases I have no clue on how to go forward.

Could you give some feedback whether I'm on the right track and how I should proceed?
Thanks in advance,
koebi
> I think I found out what happens, but I'm not super sure… Here goes:
> Both ordering and filtering requests of the orders-list are handled by an EventOrderFilterForm.
This has an "ordering"-field inherited by FilterForm and defined in the filter-forms. The choices of this field are set to an empty tuple, since the orders-variable of a FilterForm is an empty dict.
> Thus, validating the Form fails when an ordering is present, leading to the orders not being filtered in the orders-view.

That sounds correct. Thanks for the good analysis! To understand where it comes from: Previously, all filtering and ordering has been done in the views. Do save duplicate code, I recently introduced the FilterForms that can be re-used in multiple places and share logic. When I did this, I apparently only moved the filtering part to a form, not the sorting part.

> To solve this, I think that either orders has to be set for an EventOrderFilterForm or an OrderFilterForm, though I don't know to what, or the "ordering"-field should be set to contain valid choices for an ordering. Assuming that one of these propositions is the way to go, in both cases I have no clue on how to go forward.

Yep, the first one is the way to go. EventOrderFilterForm should get an "order" attribute to the list of valid fields to sort by (taken from the view):
```
    orders = {'code': 'code', 'email': 'email', 'total': 'total', 'datetime': 'datetime', 'status': 'status', 'pcnt': 'pcnt')
```
And then drop the whole
```
        if self.request.GET.get("ordering", "") != "":
            p = self.request.GET.get("ordering", "")
            p_admissable = ('-code', 'code', '-email', 'email', '-total', 'total', '-datetime',
                            'datetime', '-status', 'status', 'pcnt', '-pcnt')
            if p in p_admissable:
                qs = qs.order_by(p)
```
block from the view, it should now work automatically.
Hey, 

I'd like to give this a try. I'll let you know when I've come up with something or need help :)) 
Hey, 

I think I found out what happens, but I'm not super sure… Here goes: 

Both ordering and filtering requests of the orders-list are handled by an EventOrderFilterForm. 
This has an "ordering"-field inherited by FilterForm and defined in [the filter-forms](https://github.com/pretix/pretix/blob/master/src/pretix/control/forms/filter.py#L24). The choices of this field are set to an empty tuple, since the orders-variable of a FilterForm is an empty dict. 
Thus, validating the Form fails when an ordering is present, leading to the orders not being filtered in [the orders-view](https://github.com/pretix/pretix/blob/master/src/pretix/control/views/orders.py#L70).

To solve this, I think that either orders has to be set for an EventOrderFilterForm or an OrderFilterForm, though I don't know to what, or the "ordering"-field should be set to contain valid choices for an ordering. Assuming that one of these propositions is the way to go, in both cases I have no clue on how to go forward.

Could you give some feedback whether I'm on the right track and how I should proceed?
Thanks in advance,
koebi
> I think I found out what happens, but I'm not super sure… Here goes:
> Both ordering and filtering requests of the orders-list are handled by an EventOrderFilterForm.
This has an "ordering"-field inherited by FilterForm and defined in the filter-forms. The choices of this field are set to an empty tuple, since the orders-variable of a FilterForm is an empty dict.
> Thus, validating the Form fails when an ordering is present, leading to the orders not being filtered in the orders-view.

That sounds correct. Thanks for the good analysis! To understand where it comes from: Previously, all filtering and ordering has been done in the views. Do save duplicate code, I recently introduced the FilterForms that can be re-used in multiple places and share logic. When I did this, I apparently only moved the filtering part to a form, not the sorting part.

> To solve this, I think that either orders has to be set for an EventOrderFilterForm or an OrderFilterForm, though I don't know to what, or the "ordering"-field should be set to contain valid choices for an ordering. Assuming that one of these propositions is the way to go, in both cases I have no clue on how to go forward.

Yep, the first one is the way to go. EventOrderFilterForm should get an "order" attribute to the list of valid fields to sort by (taken from the view):
```
    orders = {'code': 'code', 'email': 'email', 'total': 'total', 'datetime': 'datetime', 'status': 'status', 'pcnt': 'pcnt')
```
And then drop the whole
```
        if self.request.GET.get("ordering", "") != "":
            p = self.request.GET.get("ordering", "")
            p_admissable = ('-code', 'code', '-email', 'email', '-total', 'total', '-datetime',
                            'datetime', '-status', 'status', 'pcnt', '-pcnt')
            if p in p_admissable:
                qs = qs.order_by(p)
```
block from the view, it should now work automatically.

Resolving patch:
diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py
--- a/src/pretix/control/forms/filter.py
+++ b/src/pretix/control/forms/filter.py
@@ -93,10 +93,16 @@ def filter_qs(self, qs):
             else:
                 qs = qs.filter(status=s)
 
+        if fdata.get('ordering'):
+            qs = qs.order_by(dict(self.fields['ordering'].choices)[fdata.get('ordering')])
+
         return qs
 
 
 class EventOrderFilterForm(OrderFilterForm):
+    orders = {'code': 'code', 'email': 'email', 'total': 'total',
+              'datetime': 'datetime', 'status': 'status', 'pcnt': 'pcnt'}
+
     item = forms.ModelChoiceField(
         label=_('Products'),
         queryset=Item.objects.none(),
@@ -157,6 +163,10 @@ def filter_qs(self, qs):
 
 
 class OrderSearchFilterForm(OrderFilterForm):
+    orders = {'code': 'code', 'email': 'email', 'total': 'total',
+              'datetime': 'datetime', 'status': 'status', 'pcnt': 'pcnt',
+              'event': 'event'}
+
     organizer = forms.ModelChoiceField(
         label=_('Organizer'),
         queryset=Organizer.objects.none(),
diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py
--- a/src/pretix/control/views/orders.py
+++ b/src/pretix/control/views/orders.py
@@ -70,13 +70,6 @@ def get_queryset(self):
         if self.filter_form.is_valid():
             qs = self.filter_form.filter_qs(qs)
 
-        if self.request.GET.get("ordering", "") != "":
-            p = self.request.GET.get("ordering", "")
-            p_admissable = ('-code', 'code', '-email', 'email', '-total', 'total', '-datetime',
-                            'datetime', '-status', 'status', 'pcnt', '-pcnt')
-            if p in p_admissable:
-                qs = qs.order_by(p)
-
         return qs.distinct()
 
     def get_context_data(self, **kwargs):


Test patch: