Commits

Luke Plant committed f3e05d1

Fixed bug with ForeignKeyFilter and query params representing missing objects

Comments (0)

Files changed (2)

django_easyfilters/filters.py

 
     def get_choices_remove(self, qs):
         chosen = self.chosen
-        return [FilterChoice(self.display_choice(choice),
-                             None, # Don't need count for removing
-                             self.build_params(remove=[choice]),
-                             FILTER_REMOVE)
-                for choice in chosen]
+        choices = []
+        for choice in chosen:
+            display = self.display_choice(choice)
+            if display is not None:
+                choices.append(FilterChoice(display,
+                                            None, # Don't need count for removing
+                                            self.build_params(remove=[choice]),
+                                            FILTER_REMOVE))
+        return choices
 
 
 class ValuesFilter(SingleValueFilterMixin, Filter):
 
     def display_choice(self, choice):
         lookup = {self.rel_field.name: choice}
-        return unicode(self.rel_model.objects.get(**lookup))
+        try:
+            obj = self.rel_model.objects.get(**lookup)
+        except self.rel_model.DoesNotExist:
+            return None
+        return unicode(None)
 
     def get_choices_add(self, qs):
         count_dict = self.get_values_counts(qs)

django_easyfilters/tests/filterset.py

 
     def do_invalid_query_param_test(self, make_filter, params):
         """
-        Utility to test filters with invalid query paramters.
+        Utility to test filters with invalid query parameters.
 
         make_filter should a callable that accepts MultiValueDict
         and returns a filter.
         self.assertEqual(list(f.get_choices(qs)),
                          list(f_empty.get_choices(qs)))
 
+    def do_missing_related_object_test(self, make_filter, params):
+        """
+        Utility to test filters with query strings representing objects
+        not in the database.
+
+        make_filter should a callable that accepts MultiValueDict
+        and returns a filter.
+        """
+        f = make_filter(params)
+        qs = f.model.objects.all()
+
+        # choices should render without error, and with no
+        # 'remove' links.
+        qs_filtered = f.apply_filter(qs)
+        choices = list(f.get_choices(qs))
+        self.assertFalse(any(c.link_type == FILTER_REMOVE
+                             for c in choices))
+
     def test_foreignkey_filters_produced(self):
         """
         A ForeignKey should produce a list of the possible related objects,
         self.do_invalid_query_param_test(lambda params:
                                              ForeignKeyFilter('genre', Book, params),
                                          MultiValueDict({'genre':['xxx']}))
+        self.do_missing_related_object_test(lambda params:
+                                                ForeignKeyFilter('genre', Book, params),
+                                            MultiValueDict({'genre':['1000']}))
 
     def test_values_filter(self):
         """