diff --git a/django_tables2/utils.py b/django_tables2/utils.py index 789834a1..33efabc9 100644 --- a/django_tables2/utils.py +++ b/django_tables2/utils.py @@ -303,7 +303,12 @@ class Accessor(str): "Failed lookup for key [{key}] in {context}, when resolving the accessor {accessor}" ) - def __new__(cls, value): + def __init__(self, value, callable_args=None, callable_kwargs=None): + self.callable_args = callable_args or getattr(value, "callable_args", None) or [] + self.callable_kwargs = callable_kwargs or getattr(value, "callable_kwargs", None) or {} + super().__init__() + + def __new__(cls, value, callable_args=None, callable_kwargs=None): instance = super().__new__(cls, value) if cls.LEGACY_SEPARATOR in value: instance.SEPARATOR = cls.LEGACY_SEPARATOR @@ -394,7 +399,7 @@ def resolve(self, context, safe=True, quiet=False): if safe and getattr(current, "alters_data", False): raise ValueError(self.ALTERS_DATA_ERROR_FMT.format(method=current.__name__)) if not getattr(current, "do_not_call_in_templates", False): - current = current() + current = current(*self.callable_args, **self.callable_kwargs) # Important that we break in None case, or a relationship # spanning across a null-key will raise an exception in the # next iteration, instead of defaulting. diff --git a/tests/test_utils.py b/tests/test_utils.py index 0507c344..977ad548 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -130,6 +130,17 @@ def test_short_circuit_dict(self): self.assertEqual(Accessor("occupation__name").resolve(context), "Carpenter") + def test_callable_args_kwargs(self): + class MyClass: + def method(self, *args, **kwargs): + return args, kwargs + + callable_args = ("arg1", "arg2") + callable_kwargs = {"kwarg1": "val1", "kwarg2": "val2"} + obj = MyClass() + result = Accessor("method", callable_args, callable_kwargs).resolve(obj) + self.assertEqual(result, (callable_args, callable_kwargs)) + class AccessorTestModel(models.Model): foo = models.CharField(max_length=20)