From 901a799cd26709ff76b595fe246f4287e54470c3 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sat, 30 Sep 2023 19:38:29 +0200 Subject: [PATCH] =?UTF-8?q?Remplace=20la=20m=C3=A9thode=20d=C3=A9pr=C3=A9c?= =?UTF-8?q?i=C3=A9e=20request.is=5Fajax=20(pr=C3=A9paration=20pour=20Djang?= =?UTF-8?q?o=204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zds/forum/utils.py | 8 ++++---- zds/forum/views.py | 15 ++++++++------- zds/member/views/hats.py | 3 ++- zds/member/views/profile.py | 3 ++- zds/middlewares/matomomiddleware.py | 3 ++- zds/mp/views.py | 5 +++-- zds/tutorialv2/mixins.py | 3 ++- zds/tutorialv2/views/comments.py | 7 ++++--- zds/tutorialv2/views/containers_extracts.py | 3 ++- zds/tutorialv2/views/help.py | 5 +++-- zds/tutorialv2/views/misc.py | 5 +++-- zds/utils/misc.py | 19 +++++++++++++++++++ 12 files changed, 54 insertions(+), 25 deletions(-) diff --git a/zds/forum/utils.py b/zds/forum/utils.py index f24dfbd9b5..4a637d2b58 100644 --- a/zds/forum/utils.py +++ b/zds/forum/utils.py @@ -10,7 +10,7 @@ from django.utils.translation import gettext as _ from zds.forum.models import Forum, Topic, Post from zds.member.views import get_client_ip -from zds.utils.misc import contains_utf8mb4 +from zds.utils.misc import contains_utf8mb4, is_ajax from zds.utils.mixins import QuoteMixin from zds.utils.models import CommentVote, get_hat_from_request @@ -141,7 +141,7 @@ def get(self, request, *args, **kwargs): if "cite" in request.GET: text = self.build_quote(request.GET.get("cite"), request.user) - if request.is_ajax(): + if is_ajax(request): return HttpResponse(json.dumps({"text": text}), content_type="application/json") form = self.create_forum(self.form_class, **{"text": text}) @@ -172,11 +172,11 @@ def get(self, request, *args, **kwargs): def post(self, request, *args, **kwargs): form = self.get_form(self.form_class) new_post = None - if not request.is_ajax(): + if not is_ajax(request): new_post = self.object.last_message.pk != int(request.POST.get("last_post")) if "preview" in request.POST or new_post: - if request.is_ajax(): + if is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST.get("text")}) return StreamingHttpResponse(content) else: diff --git a/zds/forum/views.py b/zds/forum/views.py index f55ca2e7c8..0f49c4af3d 100644 --- a/zds/forum/views.py +++ b/zds/forum/views.py @@ -28,6 +28,7 @@ from zds.utils import old_slugify from zds.utils.context_processor import get_repository_url from zds.forum.utils import create_topic, send_post, CreatePostView +from zds.utils.misc import is_ajax from zds.utils.mixins import FilterMixin from zds.utils.models import Alert, Tag, CommentVote from zds.utils.paginator import ZdSPagingListView @@ -108,7 +109,7 @@ def post(self, request, *args, **kwargs): response["email"] = self.perform_follow_by_email(self.object, request.user) self.object.save() - if request.is_ajax(): + if is_ajax(request): return HttpResponse(json.dumps(response), content_type="application/json") return redirect(f"{self.object.get_absolute_url()}?page={self.page}") @@ -265,7 +266,7 @@ def post(self, request, *args, **kwargs): form = self.get_form(self.form_class) if "preview" in request.POST: - if request.is_ajax(): + if is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST["text"]}) return StreamingHttpResponse(content) else: @@ -356,7 +357,7 @@ def post(self, request, *args, **kwargs): form = self.get_form(self.form_class) if "preview" in request.POST: - if request.is_ajax(): + if is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST["text"]}) return StreamingHttpResponse(content) else: @@ -391,7 +392,7 @@ def post(self, request, *args, **kwargs): response["requesting"], response["newCount"] = self.toogle_featured_request(request.user) self.object.save() - if request.is_ajax(): + if is_ajax(request): return HttpResponse(json.dumps(response), content_type="application/json") return redirect(f"{self.object.get_absolute_url()}?page={self.page}") @@ -511,7 +512,7 @@ def post(self, request, *args, **kwargs): response["email"] = self.perform_follow_by_email(self.object, request.user) self.object.save() - if request.is_ajax(): + if is_ajax(request): return HttpResponse(json.dumps(response), content_type="application/json") return redirect(f"{self.object.get_absolute_url()}?page={self.page}") @@ -635,7 +636,7 @@ def post(self, request, *args, **kwargs): form = self.get_form(self.form_class) if "preview" in request.POST: - if request.is_ajax(): + if is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST.get("text")}) return StreamingHttpResponse(content) else: @@ -717,7 +718,7 @@ def dispatch(self, request, *args, **kwargs): def post(self, request, *args, **kwargs): self.perform_useful(self.object) - if request.is_ajax(): + if is_ajax(request): return HttpResponse(json.dumps(self.object.is_useful), content_type="application/json") return redirect(self.object.get_absolute_url()) diff --git a/zds/member/views/hats.py b/zds/member/views/hats.py index f5a655e8ad..7f03f9f5a8 100644 --- a/zds/member/views/hats.py +++ b/zds/member/views/hats.py @@ -15,6 +15,7 @@ from zds.member.decorator import LoginRequiredMixin from zds.member.forms import HatRequestForm from zds.pages.models import GroupContact +from zds.utils.misc import is_ajax from zds.utils.models import HatRequest, Hat, get_hat_to_add from zds.utils.paginator import ZdSPagingListView @@ -74,7 +75,7 @@ def get_initial(self): return initial def post(self, request, *args, **kwargs): - if "preview" in request.POST and request.is_ajax(): + if "preview" in request.POST and is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST.get("text")}) return StreamingHttpResponse(content) diff --git a/zds/member/views/profile.py b/zds/member/views/profile.py index 5f95c5e5d4..16b0a83aaf 100644 --- a/zds/member/views/profile.py +++ b/zds/member/views/profile.py @@ -36,6 +36,7 @@ from zds.notification.models import TopicAnswerSubscription, NewPublicationSubscription from zds.tutorialv2.models import CONTENT_TYPES from zds.tutorialv2.models.database import PublishedContent, ContentContribution, ContentReaction +from zds.utils.misc import is_ajax from zds.utils.templatetags.pluralize_fr import pluralize_fr @@ -244,7 +245,7 @@ def get_form(self, form_class=ProfileForm): def post(self, request, *args, **kwargs): form = self.form_class(request.POST) - if "preview" in request.POST and request.is_ajax(): + if "preview" in request.POST and is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST.get("text")}) return StreamingHttpResponse(content) diff --git a/zds/middlewares/matomomiddleware.py b/zds/middlewares/matomomiddleware.py index 89a66b6e60..d7c43e99ef 100644 --- a/zds/middlewares/matomomiddleware.py +++ b/zds/middlewares/matomomiddleware.py @@ -10,6 +10,7 @@ from django.urls import reverse from zds.member.views import get_client_ip +from zds.utils.misc import is_ajax matomo_token_auth = settings.ZDS_APP["site"]["matomo_token_auth"] matomo_api_url = "{}/matomo.php?token_auth={}".format(settings.ZDS_APP["site"]["matomo_url"], matomo_token_auth) @@ -96,7 +97,7 @@ def matomo_track(self, request, search_data=None): self.queue.put(tracking_params) def process_response(self, request, response): - if response.status_code not in tracked_status_code or request.is_ajax(): + if response.status_code not in tracked_status_code or is_ajax(request): return response # only on get if request.method in tracked_methods: diff --git a/zds/mp/views.py b/zds/mp/views.py index 0accd2bb1e..82d6de8c2b 100644 --- a/zds/mp/views.py +++ b/zds/mp/views.py @@ -30,6 +30,7 @@ PrivatePostVote, is_reachable, ) +from zds.utils.misc import is_ajax class PrivateTopicList(LoginRequiredMixin, ZdSPagingListView): @@ -64,7 +65,7 @@ def post(self, request, *args, **kwargs): form = self.get_form(self.form_class) if "preview" in request.POST: - if request.is_ajax(): + if is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST["text"]}) return StreamingHttpResponse(content) else: @@ -307,7 +308,7 @@ def post(self, request, *args, **kwargs): form = self.get_form(self.form_class) if "preview" in request.POST: - if request.is_ajax(): + if is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST["text"]}) return StreamingHttpResponse(content) elif form.is_valid(): diff --git a/zds/tutorialv2/mixins.py b/zds/tutorialv2/mixins.py index ddb76876cb..0a5ac3be9a 100644 --- a/zds/tutorialv2/mixins.py +++ b/zds/tutorialv2/mixins.py @@ -12,6 +12,7 @@ from zds.tutorialv2.models.database import PublishableContent, PublishedContent, ContentRead from zds.tutorialv2.utils import mark_read from zds.tutorialv2.models.help_requests import HelpWriting +from zds.utils.misc import is_ajax class SingleContentViewMixin: @@ -186,7 +187,7 @@ def post(self, request, *args, **kwargs): if "preview" in request.POST: self.form_invalid(form) - if request.is_ajax(): + if is_ajax(self.request): content = render_to_string("misc/preview.part.html", {"text": request.POST.get("text")}) return StreamingHttpResponse(content) diff --git a/zds/tutorialv2/views/comments.py b/zds/tutorialv2/views/comments.py index 4c2bdd2b20..291324ae15 100644 --- a/zds/tutorialv2/views/comments.py +++ b/zds/tutorialv2/views/comments.py @@ -20,6 +20,7 @@ from zds.tutorialv2.forms import NoteForm, NoteEditForm from zds.tutorialv2.mixins import SingleOnlineContentFormViewMixin, MustRedirect, SingleOnlineContentViewMixin from zds.tutorialv2.models.database import ContentReaction +from zds.utils.misc import is_ajax from zds.utils.models import CommentEdit, get_hat_from_request, Alert @@ -97,7 +98,7 @@ def get(self, request, *args, **kwargs): text = "\n".join("> " + line for line in reaction.text.split("\n")) text += f"\nSource: [{reaction.author.username}]({reaction.get_absolute_url()})" - if self.request.is_ajax(): + if is_ajax(self.request): return StreamingHttpResponse(json_handler.dumps({"text": text}, ensure_ascii=False)) else: self.quoted_reaction_text = text @@ -110,7 +111,7 @@ def get(self, request, *args, **kwargs): ) def post(self, request, *args, **kwargs): - if "preview" in request.POST and request.is_ajax(): + if "preview" in request.POST and is_ajax(request): content = render(request, "misc/preview.part.html", {"text": request.POST["text"]}) return StreamingHttpResponse(content) else: @@ -362,6 +363,6 @@ def post(self, request, *args, **kwargs): response["follow"] = ContentReactionAnswerSubscription.objects.toggle_follow( self.get_object(), self.request.user, True ).is_active - if self.request.is_ajax(): + if is_ajax(self.request): return HttpResponse(json_handler.dumps(response), content_type="application/json") return redirect(self.get_object().get_absolute_url()) diff --git a/zds/tutorialv2/views/containers_extracts.py b/zds/tutorialv2/views/containers_extracts.py index c13192aad3..c6e480baf3 100644 --- a/zds/tutorialv2/views/containers_extracts.py +++ b/zds/tutorialv2/views/containers_extracts.py @@ -27,6 +27,7 @@ try_adopt_new_child, TooDeepContainerError, ) +from zds.utils.misc import is_ajax logger = logging.getLogger(__name__) @@ -277,7 +278,7 @@ def form_valid(self, form): self.object.update(sha_draft=sha, update_date=datetime.now()) self.success_url = extract.get_absolute_url() - if self.request.is_ajax(): + if is_ajax(self.request): return JsonResponse( {"result": "ok", "last_hash": extract.compute_hash(), "new_url": extract.get_edit_url()} ) diff --git a/zds/tutorialv2/views/help.py b/zds/tutorialv2/views/help.py index 434ef1a546..bf0c5f3f3a 100644 --- a/zds/tutorialv2/views/help.py +++ b/zds/tutorialv2/views/help.py @@ -12,6 +12,7 @@ from zds.tutorialv2.models.database import PublishableContent from zds.tutorialv2.models.help_requests import HelpWriting +from zds.utils.misc import is_ajax from zds.utils.paginator import ZdSPagingListView @@ -84,12 +85,12 @@ def form_valid(self, form): self.object.helps.remove(data["help_wanted"]) self.object.save() signals.help_management.send(sender=self.__class__, performer=self.request.user, content=self.object) - if self.request.is_ajax(): + if is_ajax(self.request): return JsonResponse({"state": data["activated"]}) self.success_url = self.object.get_absolute_url() return super().form_valid(form) def form_invalid(self, form): - if self.request.is_ajax(): + if is_ajax(self.request): return JsonResponse({"errors": form.errors}, status=400) return super().form_invalid(form) diff --git a/zds/tutorialv2/views/misc.py b/zds/tutorialv2/views/misc.py index 7ea06666b9..443b3535d1 100644 --- a/zds/tutorialv2/views/misc.py +++ b/zds/tutorialv2/views/misc.py @@ -17,6 +17,7 @@ from zds.tutorialv2.mixins import SingleOnlineContentViewMixin, SingleContentFormViewMixin from zds.tutorialv2.utils import search_container_or_404 from zds.mp.utils import send_mp +from zds.utils.misc import is_ajax class RequestFeaturedContent(LoggedWithReadWriteHability, FeatureableMixin, SingleOnlineContentViewMixin, FormView): @@ -32,7 +33,7 @@ def post(self, request, *args, **kwargs): response = dict() response["requesting"], response["newCount"] = self.toogle_featured_request(request.user) - if self.request.is_ajax(): + if is_ajax(self.request): return HttpResponse(json_handler.dumps(response), content_type="application/json") return redirect(self.public_content_object.get_absolute_url_online()) @@ -68,7 +69,7 @@ def post(self, request, *args, **kwargs): elif "email" in request.POST: response["email"] = self.perform_follow_by_email(user_to_follow, request.user) - if request.is_ajax(): + if is_ajax(self.request): return HttpResponse(json_handler.dumps(response), content_type="application/json") return redirect(request.META.get("HTTP_REFERER")) diff --git a/zds/utils/misc.py b/zds/utils/misc.py index a7052dbdb8..588ed88a43 100644 --- a/zds/utils/misc.py +++ b/zds/utils/misc.py @@ -2,6 +2,7 @@ import re from django.contrib.auth import get_user_model +from django.http import HttpRequest THUMB_MAX_WIDTH = 80 THUMB_MAX_HEIGHT = 80 @@ -78,3 +79,21 @@ def check_essential_accounts(): f"User {username!r} does not exist. You must create it to run the server. " f"On a development instance, load the fixtures to solve this issue." ) + + +def is_ajax(request: HttpRequest): + """ + Check whether the request was sent asynchronously. + + The function returns True for : + * requests sent using jQuery.ajax() since it sets the header `X-Requested-With` + to `XMLHttpRequest` by default ; + * requests sent using the tools provided by `ajax.js`, which reproduce the behavior + described above to ease the progressive removal of jQuery from the codebase. + + The function returns False for requests without the appropriate header. + These requests will not be recognized as AJAX. + + The function replaces `request.is_ajax()`, which is removed starting from Django 4.0. + """ + return request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"