Один из способов сделать это - написать собственный декоратор. Я проверил это в одном из моих проектов, и это сработало.
Сначала кастом декоратор. Этот должен принимать другие аргументы помимо функции, поэтому мы объявляем другой декоратор, чтобы сделать это так.
decorator_with_arguments = lambda decorator: lambda * args, **kwargs: lambda func: decorator(func, *args, **kwargs)
Теперь фактический декоратор:
@decorator_with_arguments
def parse_args_and_create_instance(function, klass, attr_names):
def _function(request, *args, **kwargs):
model_attributes_and_values = dict()
for name in attr_names:
value = kwargs.get(name, None)
if value: model_attributes_and_values[name] = value
model_instance = klass.objects.get(**model_attributes_and_values)
return function(model_instance)
return _function
Этот декоратор ожидает два дополнительных аргумента помимо функции, которую он декорирует. Это соответственно класс модели, для которого должен быть подготовлен и внедрен экземпляр, а также имена атрибутов, которые будут использоваться для подготовки экземпляра. В этом случае декоратор использует атрибуты для get
экземпляра из базы данных.
А теперь «общий» вид, использующий функцию show
.
def show(model_instance):
return HttpResponse(model_instance.some_attribute)
show_order = parse_args_and_create_instance(Order, ['order_id'])(show)
И еще:
show_customer = parse_args_and_create_instance(Customer, ['id'])(show)
Чтобы это работало, параметры конфигурации URL должны содержать те же ключевые слова, что и атрибуты. Конечно, вы можете настроить это, настроив декоратор.
# urls.py
...
url(r'^order/(?P<order_id>\d+)/$', 'show_order', {}, name = 'show_order'),
url(r'^customer/(?P<id>\d+)/$', 'show_customer', {}, name = 'show_customer'),
...
Обновление
Как правильно @rebus указал , вам также необходимо изучить общие взгляды Джанго.