How to route URL pattern with URL path separator? - django

I have to route the following URL pattern to view api/v1/{resourceId}/owners in DRF
But the problem is resourceID contains / in it. eg api/v1/somethings/value/owners the additional / causing get 404 resource not found exception
Is there way to route the URL and get resourceID in view
My urls.py
path('api/v1/<str:resource_id>/owners', ResourceOwnershipView.as_view())
views.py
class ResourceOwnershipView(APIView):
def get(self, request: HttpRequest, resource_id: str) -> Response:
# do something with resourceID

<str:> probably doesn't allow slashes in it. I would try to use regular expression version of routing definition re_path:
https://docs.djangoproject.com/en/4.1/ref/urls/#re-path

Related

CloudWatch Insights filter to only homepage requests including with query string

We have a field for "url" in our logs, and I'd like to be able to filter down to just requests hitting the homepage. This would be requests for / and for /?*, i.e. with any query string.
Just getting homepage requests is | filter url = "/" but how do you include those requests that have a query string also?
You can use regex: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html
Something like this should work:
filter url = "/" or url like /^\/\?.*/

ExtJS 5 application + Django rest framework CORS error when changing URL of store

I am developing a ExtJS application that uses a Django-rest-framework service. I am using CORS headers to allow fetching the data from the service (https://github.com/OttoYiu/django-cors-headers).
What happens is that at a point in time I want to change the URL from the store. And when I do that I get the following error:
XMLHttpRequest cannot load http://10.98.0.241:8000/reacsearch/as?_dc=1418831884352&page=1&start=0&limit=25. The request was redirected to 'http://10.98.0.241:8000/reacsearch/as/?_dc=1418831884352&page=1&start=0&limit=25', which is disallowed for cross-origin requests that require preflight.
In the settings.oy I define the following properties for the CORS
CORS_ALLOW_METHODS = (
'GET',
'OPTIONS'
)
CORS_ORIGIN_ALLOW_ALL = True
This works fine when I use URLs to list all the elements in my database, however when I change the store for another URL I get the error above. Also the link works fine in the browser.
The store url change is made this way:
var store = Ext.getStore(storeName);
store.getProxy().setUrl(newURL);
store.load();
The difference between the views, is that the two that work on the application are viewsets, while the other is just a generic list
class Example1viewset(viewsets.ModelViewSet):
"""
API endpoing that allows metabolites to be viewed.
"""
queryset = examples1.objects.all()
serializer_class = Example1Serializer
class Example1SearchList(generics.ListAPIView):
serializer_class = Example1Serializer
def get_queryset(self):
queryset = Example.objects.all()
if 'attr' in self.kwargs:
queryset = queryset.filter(Q(attribute1__contains=self.kwargs['attr']) | Q(attribute2__contains=self.kwargs['abbr']))
return queryset
Like I mentioned both examples work fine in the browser (even accessing through other computers in the network), however in the application when changing the URL of the store I get the CORS error. Does anyone has any idea why this is happening?
Thank you.
Edit:
Just for clarification, the problem is not in changing the url of the store. As I tried to set those urls as defaults, but they are not working when accessing from the application.
My urls.py file:
router = routers.DefaultRouter()
router.register(r'example', views.Example1ViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^reacsearch/(?P<attr>.+)/$', Example1SearchList.as_view()),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
Can it be that the problem is related with the fact that I am not adding the search list to the router?
Edit2
Problem solved since I was trying to fetch data from a different domain. I changed the type of store to jsonp in Extjs, and I also allowed my rest service to render data as jsonp.
Just a reminder if anyone comes accross this same problem, it is necessary to add ?format=jsonp to the store url:
http://my/url/?format=jsonp
Since it looks like an alternate solution was found, I'll explain what the issue appeared to be as well as why the alternative works.
XMLHttpRequest cannot load first url. The request was redirected to 'second url', which is disallowed for cross-origin requests that require preflight.
The issue here is that you are telling Django to enforce the trailing slash, which makes it automatically redirect urls without a trailing slash to urls with a trailing slash, assuming that one exists. This is why, as stated in the error, the request was redirected to the second url, which you can tell has the missing trailing slash. This is controlled by the APPEND_SLASH Django setting which is True by default.
The problem is that when CORS is doing a preflight request, which is what allows it to determine if the request can be made, there must be a valid response at the requested URL. Because you are redirecting the request, the preflight request fails and you're stuck without your information.
You can fix this by adding the trailing slash in your code. There appear to be a few solutions for doing this with ext, but I personally can't recommend a specific one. You can also manually set the url to use the trailing slash, which sounds like what you were doing previously.
Or you can use JSONP...
You've found the alternative solution, which is to use JSONP to make the request instead of relying on CORS. This gets around the preflight issue and works in all major browsers, but there are some drawbacks to consider. You can find more information on CORS vs JSONP by looking around.
You're going to need CORS if you want to push any changes to your API, as JSONP only supports GET requests. There are other advantages, such as the ability to abort requests, that also comes with CORS.

Django catches wrong url, have to fix regex

I ended up like
www.ww.mywebsite.com/ urls with google search results,
I asked in google groups and They pointed the obvious that, www.ww.mywebsite.com, shouldnt be a 200 ok response.
(r'^$', myview), this is how I catch a url for my homepage,
I dont think this problem occurs cause of my url patterns cause, as far as I know, url patterns for to catch trailing words. www.wwww.example.com/test/, there would be 'test' to be our word to process, what about this wwww staff before my website name?
In the fully qualified URL www.example.com/test/, the Django URL matching only looks at the /test/ part. Here you need to filter the domain names, for which the ALLOWED_HOSTS setting was introduced. For example you can put in settings.yml:
ALLOWED_HOSTS = ['mywebsite.com', 'www.mywebsite.com']
Alternatively, you can use a custom middleware to redirect the user to the canonical URL. This is a better solution if the non-canonical URLs should still be accessible to the users:
class CanonicalDomainRedirectMiddleware(object):
def process_request(self, request):
if request.get_host() == 'mywebsite.com':
return None
if request.is_secure():
protocol = 'https'
else:
protocol = 'http'
return HttpResponsePermanentRedirect('%s://%s/%s' % (
protocol, 'mywebsite.com', request.get_full_path)

Programmatically perform a nested GET request in Django

During the processing of a request in Django, I need to perform a nested request to the same application. Consider this example, where while processing the sendmail request, I attempt to make another request to the same server to obtain the content of an attachment (the body of the mail and a list of urls whose content to attach are provided to the sendmail view function through POST parameters):
def sendmail(request):
mail = #... create a mail object
for url in urls: # iterate over desired attachments urls
data = urllib.urlopen('http://127.0.0.1:8000' + url).read()
mail.attach(data)
There are several issues with this approach. First, it doesn't work with the development server because it can only process one request at a time: as it is already processing the sendmail request, attempting to read from the given url will block forever.
Second, I have to specify the server's ip and port, which is not very nice.
I would like to do something like that instead:
data = django_get(url).read()
where the hypothetical django_get method would not really make an http request, but instead directly call the django component that takes an url and returns an HttpResponse. That would solve both problems, as there would not be any actual socket connection, and it would not be necessary to include the server/port in the url. How could that be achieved?
The opposite of reverse() is resolve().
Also, this.
This is Ignacio Vazquez-Abrams' answer for the lazy:
from django.core.urlresolvers import resolve
def sendmail(request):
mail = #... create a mail object
for url in urls: # iterate over desired attachments urls
resolved = resolve(url)
request.path = url
mail.attach(resolved.func(request, *resolved.args, **resolved.kwargs))
Put the desired functionality in a separate function that both your sendmail function and the original page's function can call.

Django redirecting to external url that contains parameters (for development)

When developing with Django without a web server (serving directly from Django) I have a problem with external urls that lack the domain part and have parameters.
Let's say I'm using a javascript library that does an ajax call to "/prefix/foo/bar?q=1" (the url is not something I can change). It is not a problem for the production server but only a problem when not using a web server. I can redirect by adding the following pattern to my urlpatters:
(r'^prefix/(?P<path>.*)$', 'django.views.generic.simple.redirect_to', {'url': 'htttp://example.com/prefix/%(path)s'}),
but of course %(path)s will only contain "foo/bar" not "foo/bar?q=1".
Is there a way to handle this problem with Django?
You'll have to write your own redirect:
def redirect_get(request, url, **kwargs):
if request.META['QUERY_STRING']:
url += '?%s' % request.META['QUERY_STRING']
return redirect_to(request, url, **kwargs)