Django REST shows non-allowed methods under Allow in the Browser - django

Goal
Is to disable OPTIONS method globally.
Background
According to the official Django REST docs (https://www.django-rest-framework.org/api-guide/metadata/), the proper way to do it is to set DEFAULT_METADATA_CLASS to None.
This resolves the problem. After trying to send the OPTIONS curl request, the server responds with the 405.
Problem
However the API Browser would still show methods under Allow that are actually not allowed:
Question
How to hide not-supported methods under Allow in Django API Browser?

After checking the Disable a method in a ViewSet, django-rest-framework, it turned out there are at least 3 good approaches to address this:
Use Specific ViewSets instead of just inheriting ModelViewSet
Overwrite _allowed_methods()
Define http_method_names()
It was decided to:
Set DEFAULT_METADATA_CLASS to None (to make sure non-defined methods are not exposed).
Define http_method_names for each ViewSet (to hide them in the Browser API).

Related

Multiple same requests in django rest class based view

I recently began using class-based views in the development of Django rest APIs.
While discussing this with a friend, he inquired, "What if I have the same type of request multiple times in the same class?"
because, as stated in the rest documentation, I created post functions for POST requests and get functions for GET requests.
So, how to write two GET or other types of requests within the same class?
Was trying out the earlier accepted answer, does not seem to be correct.
The below solution is what shall work for you.
For multiple GET request in same api you need to implement Django Viewset and routers.
I found the below link to be well explained with examples:
https://testdriven.io/blog/drf-views-part-3/

Django: Per View authentication scheme

The django rest framework does allow per view authentication schemes:
http://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme
I think this is handy and I ask myself why this gets reinvented in the django rest framework.
"Why does django not provide this?" is a question which would get closed here on stackoverflow soon.
That's why I ask:
How to get per view authentication schemes in django?
"Why does django not provide this?"
It's an opinion. I don't see why someone should limit a specific view to some authentication backends. Whatever my/your opinion is, the decision is made in Django/DRF. Contact their mailing list and search their bug repo to find out why a specific decision made.
How to get per view authentication schemes in django?
Before anything be sure you know how Django works. Read all authentication related documents like this and this.
You could go the DRF way: Completely ditch Django authentication and write it yourself. Replace Django authentication backend abstract with your desired one and make a way to configure each view (e.g. Use a decorator to set attributes on you view function or use class based views + some fields). Then add a middleware to authenticate users and replace Django's AuthenticationMiddleware to provide request.user. You should also make sure that things like login_required work without modification or you should provide an alternative.

Is it necessary to have all the types of requests in an app even though only post is being used for that app?

I have an app in django project which is exposed to only post method. I want to know whether it is compulsory to expose this app to other types of requests like get, put, and delete or not.
Thank you in advance
Seems improbable that a web framework wont handle a the very least GET and POST request, but if it the case, there is no point for you to have GET, PUT and DELETE endpoints indeed.

How does viewset aligns with rest methods

I am relatively new to DRF, but found viewsets an amazing abstraction technique for writing RESTful API. I am having a hard time correlating Viewsets with REST methods though. Let's say I have a viewset for Userprofiles and somebody new creates a profile on client.
Should this send a PUT or a POST ?
Which url should this request go to, http://user or http://user/new_id ?
If I want this profile only accessible to the user or admin(all CRUD operations), then where should I handle the code for making it inaccessible to others ?
Should I create a new permission ? If yes, should I handle rest methods in has_permission/has_object_permission ?
I have gone through the tutorial, and know how permissions/mixins works, but I am not able to connect these dots here.
1/ In general, POST is for creating new, PUT is for updating. See the docs on the SimpleRouter to show how the various types of Http methods align with various actions in your Django backend.
2/ You'll find that different situations call for different routing methods. If yours is standard, you may want to use a SimpleRouter like the example above. In that case, creating a new user would be a POST request to /user/ and updating a user would be a PUT request to /user/{{user_id}}/.
3/ To limit access to various API methods, you want to use Permissions. It's possible that you could use one of DRF's Custom Permissions. I've found that in general, if you want only the user to access his/her own profile, it's easier to either use conditional logic within a view (i.e., return a DRF PermissionDenied exception in the view logic if the request.user.pk is not the pk of that REST url. More often than not, I've used the UserPassesTestMixin from Django Braces, that works pretty well to filter user permissions.
4/ I guess the Django Braces mixin above answers this question. You should include a test_func method if you're using Django Braces that returns True if you want to grant the user access, and False otherwise.
Hope this helps! I agree that these are difficult parts of DRF and perhaps some of these could more effectively get incorporated into the source. Good luck!

How to post json to Django

What is the proper way to post json to Django? I have tried to use views, but I am not certain how to handle csrf. Is there another way to bypass views and simply accept a post of json?
Views are what handle the post data. There is no concept of "bypass views" because that is where the work of processing a request is done.
This is probably what your are looking for:
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
This shows you how to handle csrf tokens with ajax (namely by using cookies).
I also might suggest you slow down and try to work through the tutorial found here:
https://docs.djangoproject.com/en/dev/intro/tutorial01/
You will likely have an easier time with django if you undertstand how the pieces (Models, Views, Templates, urls, Forms, etc) fit together.
Since you've added that these are API calls the simplest thing to do would be to mark these views as csrf_exempt. Additionally, as you might guess creating an API from models is a common task (I'm assuming that your API maps to models as that's the common case and you haven't specified) you may want to not reinvent the wheel and instead use piston or tastypie to make this easier on you: http://djangopackages.com/grids/g/api/
Use the #csrf_exempt decorator on any API views.