formsbuttons.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. from django.contrib import messages
  2. from django.db import transaction
  3. from django.shortcuts import redirect
  4. from .base import AdminView
  5. class TargetedView(AdminView):
  6. is_atomic = True
  7. def dispatch(self, request, *args, **kwargs):
  8. if self.is_atomic:
  9. with transaction.atomic():
  10. return self.wrapped_dispatch(request, *args, **kwargs)
  11. return self.wrapped_dispatch(request, *args, **kwargs)
  12. def wrapped_dispatch(self, request, *args, **kwargs):
  13. target = self.get_target_or_none(request, kwargs)
  14. if not target:
  15. messages.error(request, self.message_404)
  16. return redirect(self.root_link)
  17. error = self.check_permissions( # pylint: disable=assignment-from-no-return
  18. request, target
  19. )
  20. if error:
  21. messages.error(request, error)
  22. return redirect(self.root_link)
  23. return self.real_dispatch(request, target)
  24. def get_target_or_none(self, request, kwargs):
  25. try:
  26. return self.get_target(kwargs)
  27. except self.get_model().DoesNotExist:
  28. return None
  29. def get_target(self, kwargs):
  30. if len(kwargs) > 1:
  31. raise ValueError("TargetedView.get_target() received more than one kwarg")
  32. if len(kwargs) != 1:
  33. return self.get_model()()
  34. queryset = self.get_model().objects
  35. if self.is_atomic:
  36. queryset = queryset.select_for_update()
  37. (pk,) = kwargs.values()
  38. return queryset.get(pk=pk)
  39. def check_permissions(self, request, target):
  40. pass
  41. def real_dispatch(self, request, target):
  42. pass
  43. class FormView(TargetedView):
  44. form_class = None
  45. template_name = "form.html"
  46. def get_form_class(self, request):
  47. return self.form_class
  48. def get_form(self, form_class, request):
  49. if request.method == "POST":
  50. return form_class(request.POST, request.FILES)
  51. return form_class()
  52. def handle_form(self, form, request):
  53. raise NotImplementedError(
  54. "You have to define your own handle_form method to handle form submissions."
  55. )
  56. def real_dispatch(self, request, target):
  57. FormType = self.get_form_class(request)
  58. form = self.get_form(FormType, request)
  59. if request.method == "POST" and form.is_valid():
  60. response = self.handle_form(form, request)
  61. if response:
  62. return response
  63. if "stay" in request.POST:
  64. return redirect(request.path)
  65. return redirect(self.root_link)
  66. return self.render(request, {"form": form})
  67. class ModelFormView(FormView):
  68. message_submit = None
  69. def get_form_class(self, request, target):
  70. return self.form_class
  71. def get_form(self, form_class, request, target):
  72. if request.method == "POST":
  73. return form_class(request.POST, request.FILES, instance=target)
  74. return form_class(instance=target)
  75. def handle_form(self, form, request, target):
  76. form.instance.save()
  77. if self.message_submit:
  78. messages.success(request, self.message_submit % {"name": target.name})
  79. def real_dispatch(self, request, target):
  80. form_class = self.get_form_class(request, target)
  81. form = self.get_form(form_class, request, target)
  82. if request.method == "POST" and form.is_valid():
  83. response = self.handle_form( # pylint: disable=assignment-from-no-return
  84. form, request, target
  85. )
  86. if response:
  87. return response
  88. if "stay" in request.POST:
  89. return redirect(request.path)
  90. return redirect(self.root_link)
  91. template_name = self.get_template_name(request, target)
  92. return self.render(request, {"form": form, "target": target}, template_name)
  93. def get_template_name(self, request, target):
  94. return "%s/%s" % (self.templates_dir, self.template_name)
  95. class ButtonView(TargetedView):
  96. def real_dispatch(self, request, target):
  97. if request.method == "POST":
  98. new_response = self.button_action(request, target)
  99. if new_response:
  100. return new_response
  101. return redirect(self.root_link)
  102. def button_action(self, request, target):
  103. raise NotImplementedError("You have to define custom button_action.")