kopia lustrzana https://github.com/wagtail/wagtail
				
				
				
			
							rodzic
							
								
									c4ef290859
								
							
						
					
					
						commit
						996abeae8e
					
				|  | @ -50,6 +50,7 @@ Changelog | |||
|  * Add the accessibility checker within the page and snippets editor (Thibaud Colas) | ||||
|  * Add `DrilldownController` and `w-drilldown` component to support drilldown menus (Thibaud Colas) | ||||
|  * Add support for `caption` on admin UI Table component (Aman Pandey) | ||||
|  * Add API support for a redirects (contrib) endpoint (Rohit Sharma, Jaap Roes, Andreas Donig) | ||||
|  * Fix: Update system check for overwriting storage backends to recognise the `STORAGES` setting introduced in Django 4.2 (phijma-leukeleu) | ||||
|  * Fix: Prevent password change form from raising a validation error when browser autocomplete fills in the "Old password" field (Chiemezuo Akujobi) | ||||
|  * Fix: Ensure that the legacy dropdown options, when closed, do not get accidentally clicked by other interactions wide viewports (CheesyPhoenix, Christer Jensen) | ||||
|  |  | |||
|  | @ -787,6 +787,7 @@ | |||
| * Jai Vignesh J | ||||
| * Sankalp | ||||
| * V Rohitansh | ||||
| * Andreas Donig | ||||
| 
 | ||||
| ## Translators | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,11 +40,12 @@ content type (such as pages, images and documents) has its own endpoint. | |||
| Endpoints are combined by a router, which provides the url configuration you | ||||
| can hook into the rest of your project. | ||||
| 
 | ||||
| Wagtail provides three endpoint classes you can use: | ||||
| Wagtail provides multiple endpoint classes you can use: | ||||
| 
 | ||||
| -   Pages {class}`wagtail.api.v2.views.PagesAPIViewSet` | ||||
| -   Images {class}`wagtail.images.api.v2.views.ImagesAPIViewSet` | ||||
| -   Documents {class}`wagtail.documents.api.v2.views.DocumentsAPIViewSet` | ||||
| -   Redirects {class}`wagtail.contrib.redirects.api.RedirectsAPIViewSet` see [](redirects_api_endpoint) | ||||
| 
 | ||||
| You can subclass any of these endpoint classes to customise their functionality. | ||||
| For example, in this case if you need to change the `APIViewSet` by setting a desired renderer class: | ||||
|  |  | |||
|  | @ -93,3 +93,24 @@ Options: | |||
| 
 | ||||
|     .. automethod:: add_redirect | ||||
| ``` | ||||
| 
 | ||||
| (redirects_api_endpoint)= | ||||
| 
 | ||||
| ## API | ||||
| 
 | ||||
| You can create an API endpoint to retrieve redirects or find specific redirects by path. | ||||
| 
 | ||||
| See the [](api_v2_configuration) documentation on how to configure the Wagtail API. | ||||
| 
 | ||||
| Add the following code to add the redirects endpoint: | ||||
| 
 | ||||
| ```python | ||||
| from wagtail.contrib.redirects.api import RedirectsAPIViewSet | ||||
| 
 | ||||
| api_router.register_endpoint('redirects', RedirectsAPIViewSet) | ||||
| ``` | ||||
| 
 | ||||
| With this configuration, redirects will be available at `/api/v2/redirects/`. | ||||
| 
 | ||||
| Specific redirects by path can be resolved with `/api/v2/redirects/find/?html_path=<path>`, | ||||
| which will return either a `200` response with the redirects detail, or a `404` not found response. | ||||
|  |  | |||
|  | @ -82,6 +82,7 @@ This feature was implemented by Nick Lee, Thibaud Colas, and Sage Abdullah. | |||
|  * Keep database state of pages and snippets updated while in draft state (Stefan Hammer) | ||||
|  * Add `DrilldownController` and `w-drilldown` component to support drilldown menus (Thibaud Colas) | ||||
|  * Add support for `caption` on admin UI Table component (Aman Pandey) | ||||
|  * Add API support for a [redirects (contrib)](redirects_api_endpoint) endpoint (Rohit Sharma, Jaap Roes, Andreas Donig) | ||||
| 
 | ||||
| 
 | ||||
| ### Bug fixes | ||||
|  |  | |||
|  | @ -0,0 +1,39 @@ | |||
| from django.http import Http404 | ||||
| from rest_framework import serializers | ||||
| 
 | ||||
| from wagtail.api.v2.filters import FieldsFilter, OrderingFilter, SearchFilter | ||||
| from wagtail.api.v2.serializers import BaseSerializer | ||||
| from wagtail.api.v2.views import BaseAPIViewSet | ||||
| from wagtail.contrib.redirects.middleware import get_redirect | ||||
| from wagtail.contrib.redirects.models import Redirect | ||||
| 
 | ||||
| 
 | ||||
| class RedirectSerializer(BaseSerializer): | ||||
|     location = serializers.CharField(source="link") | ||||
| 
 | ||||
| 
 | ||||
| class RedirectsAPIViewSet(BaseAPIViewSet): | ||||
|     base_serializer_class = RedirectSerializer | ||||
|     filter_backends = [FieldsFilter, OrderingFilter, SearchFilter] | ||||
|     body_fields = BaseAPIViewSet.body_fields + ["old_path", "location"] | ||||
|     name = "redirects" | ||||
|     model = Redirect | ||||
| 
 | ||||
|     listing_default_fields = BaseAPIViewSet.listing_default_fields + [ | ||||
|         "old_path", | ||||
|         "location", | ||||
|     ] | ||||
| 
 | ||||
|     def find_object(self, queryset, request): | ||||
|         if "html_path" in request.GET: | ||||
|             redirect = get_redirect( | ||||
|                 request, | ||||
|                 request.GET["html_path"], | ||||
|             ) | ||||
| 
 | ||||
|             if redirect is None: | ||||
|                 raise Http404 | ||||
|             else: | ||||
|                 return redirect | ||||
| 
 | ||||
|         return super().find_object(queryset, request) | ||||
|  | @ -0,0 +1,105 @@ | |||
| from django.test import TestCase | ||||
| from django.urls import reverse | ||||
| 
 | ||||
| from wagtail.contrib.redirects.models import Redirect | ||||
| from wagtail.models import Page, Site | ||||
| 
 | ||||
| 
 | ||||
| class TestRedirectsAPI(TestCase): | ||||
|     def setUp(self): | ||||
|         self.example_home = Page.objects.get(slug="home").add_sibling( | ||||
|             instance=Page(title="Example Homepage", slug="example-home") | ||||
|         ) | ||||
|         self.example_page = self.example_home.add_child( | ||||
|             instance=Page(title="Example Page", slug="example-page") | ||||
|         ) | ||||
|         self.example_site = Site.objects.create( | ||||
|             hostname="example", root_page=self.example_home | ||||
|         ) | ||||
| 
 | ||||
|         Redirect.objects.create( | ||||
|             old_path="/hello-world", | ||||
|             site=self.example_site, | ||||
|             redirect_link="https://www.example.com/hello-world/", | ||||
|         ) | ||||
| 
 | ||||
|         Redirect.objects.create( | ||||
|             old_path="/good-work", | ||||
|             site=self.example_site, | ||||
|             redirect_link="https://www.example.com/hello-world/", | ||||
|         ) | ||||
| 
 | ||||
|         Redirect.add_redirect( | ||||
|             old_path="/hello-world", redirect_to="https://www.example.net/new-world/" | ||||
|         ) | ||||
| 
 | ||||
|         Redirect.add_redirect( | ||||
|             old_path="/old-example", redirect_to=self.example_home, is_permanent=False | ||||
|         ) | ||||
| 
 | ||||
|         Redirect.add_redirect( | ||||
|             old_path="/old-example?bar=foo&foo=bar", | ||||
|             redirect_to=self.example_page, | ||||
|             is_permanent=False, | ||||
|         ) | ||||
| 
 | ||||
|     def test_redirects_listing(self): | ||||
|         """Returns a list of all redirects""" | ||||
| 
 | ||||
|         url = reverse("wagtailapi_v2:redirects:listing") | ||||
| 
 | ||||
|         response = self.client.get(url) | ||||
| 
 | ||||
|         self.assertEqual(response.status_code, 200) | ||||
| 
 | ||||
|         self.assertEqual(5, len(response.json()["items"])) | ||||
| 
 | ||||
|         item = response.json()["items"][0] | ||||
| 
 | ||||
|         self.assertEqual("https://www.example.com/hello-world/", item["location"]) | ||||
|         self.assertEqual("/hello-world", item["old_path"]) | ||||
| 
 | ||||
|     def test_redirect(self): | ||||
|         """Returns a matching (not site specific) redirect""" | ||||
| 
 | ||||
|         url = reverse("wagtailapi_v2:redirects:find") | ||||
| 
 | ||||
|         html_path = "/hello-world" | ||||
| 
 | ||||
|         # Add the html_path to the URL | ||||
|         url += f"?html_path={html_path}" | ||||
| 
 | ||||
|         response = self.client.get(url) | ||||
| 
 | ||||
|         # Check for a redirect status code | ||||
|         self.assertEqual(response.status_code, 302) | ||||
| 
 | ||||
|         # Follow the redirect to get the final response | ||||
|         response = self.client.get(response.url) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         response_id = response.json()["id"] | ||||
| 
 | ||||
|         expected_dict = { | ||||
|             "id": response_id, | ||||
|             "meta": { | ||||
|                 "detail_url": f"http://localhost/api/main/redirects/{response_id}/", | ||||
|                 "type": "wagtailredirects.Redirect", | ||||
|             }, | ||||
|             "old_path": "/hello-world", | ||||
|             "location": "https://www.example.net/new-world/", | ||||
|         } | ||||
| 
 | ||||
|         self.assertEqual(response.json(), expected_dict) | ||||
| 
 | ||||
|     def test_html_path_without_redirect(self): | ||||
|         html_path = "/good-work" | ||||
| 
 | ||||
|         url = reverse("wagtailapi_v2:redirects:find") | ||||
| 
 | ||||
|         # Add the html_path to the URL | ||||
|         url += f"?html_path={html_path}" | ||||
| 
 | ||||
|         response = self.client.get(url) | ||||
| 
 | ||||
|         # Check for a 404 status code | ||||
|         self.assertEqual(response.status_code, 404) | ||||
|  | @ -9,6 +9,7 @@ from wagtail.admin.views import home | |||
| from wagtail.api.v2.router import WagtailAPIRouter | ||||
| from wagtail.api.v2.tests.test_pages import Test10411APIViewSet | ||||
| from wagtail.api.v2.views import PagesAPIViewSet | ||||
| from wagtail.contrib.redirects.api import RedirectsAPIViewSet | ||||
| from wagtail.contrib.sitemaps import Sitemap | ||||
| from wagtail.contrib.sitemaps import views as sitemaps_views | ||||
| from wagtail.documents import urls as wagtaildocs_urls | ||||
|  | @ -23,6 +24,7 @@ api_router = WagtailAPIRouter("wagtailapi_v2") | |||
| api_router.register_endpoint("pages", PagesAPIViewSet) | ||||
| api_router.register_endpoint("images", ImagesAPIViewSet) | ||||
| api_router.register_endpoint("documents", DocumentsAPIViewSet) | ||||
| api_router.register_endpoint("redirects", RedirectsAPIViewSet) | ||||
| api_router.register_endpoint("issue_10411", Test10411APIViewSet) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Rohit Sharma
						Rohit Sharma