0

My project has many APIs. but now I have to put a check in all of these APIs before start executing the codes in it. I have to make sure that API only returns data if that particular form's deactivation date is grater than datetime.date.today(). Queryset would be -

available_for_entry = Forms.objects.filter(form_id=form_id, deactivate_date__gte=today_date).exists()

One way to do this to write that query set in each of APIs and then use if available_for_entry: condition. But, I was wondering if there is any other way to achieve this without writing similar conditions so many times.

I tried to achieve this with writing decorator but I could not able to pass the form_id value from function based API to that decorator. snapshot of the code is...

def is_form_available(func):
    def checking():
        today_date = datetime.date.today()
        available_for_entry = Forms.objects.filter(form_id=form_id, deactivate_date__gte=today_date).exists()
        if available_for_entry:
            func()
        else:
            print('form is not available now')
    return checking
    

@api_view(['POST'])
@is_form_available
def question_list(request):
  form_id = request.POST.get('form_id')
  parameter_list = (FormParameters.objects.filter(mappings__form__formparametermappings=   form_id).all())
  serializer = FormParametersQuizSerializer(parameter_list, many=True)

  return serializer.data
Raju Singh
  • 455
  • 1
  • 6
  • 15

1 Answers1

2

Decorator is a good idea, you can get some inspiration from native Django decorators like require_http_methods

from functools import wraps

def is_form_available(func):
    @wraps(func)
    def checking(request, *args, **kwargs):
        form_id = <extract from request>
        today_date = datetime.date.today()
        available_for_entry = Forms.objects.filter(form_id=form_id, deactivate_date__gte=today_date).exists()
        if available_for_entry:
            return func(args, kwargs)
        else:
            print('form is not available now')
    return checking
Mihai
  • 831
  • 6
  • 13
  • Yes, it worked!, but I wanted to understand about 1. `@wraps(func)` I am getting desire result even without that line. do you think I should still need to have that line ? and I needed to make a change in this line `return func(args, kwargs)`, It also required.to pass `request` in it other wise it throw an error. – Raju Singh Mar 09 '21 at 03:15
  • one more question - What if I need to put a check like, `form_id` has been given or not. where should I write that condition - in the decorator or in the main function? – Raju Singh Mar 09 '21 at 03:54
  • 1
    Glad I could help! This post explains in detail what wraps does https://stackoverflow.com/questions/308999/what-does-functools-wraps-do ; TLDR it lets you keep the function name which is useful especially in Django view names where logging helps a lot. For the second question I guess it really depends on how general is that check, if it applies for all cases then decorator is a good place. You can start with it in the decorator and refactor later. – Mihai Mar 09 '21 at 22:07