403 with django's class based view - python

So this is a simple view that I have written.
class PostTestView(View):
def post(self, request, *args, **kwargs):
print request.POST
return HttpResponse("Hello there")
my urls.py has this line for the above view :
url(r'^test/create$',PostTestView.as_view(), name='app.views.create_test')
But I get an 405 Http error when I try to hit http://127.0.0.1:8000/app/test/create
This apparently means that my method post is not in the defined methods list . But I have defined it as above in my view.
What could possibly be wrong here ? I am clueless

Try defining the get method.
The "post" method is commonly used in forms, but when you just point your browser to an url the used method is "get"

Related

Django redirect does nothing

I am currently try to redirect from one view to another view. However, nothing happens, the token gets printed and that's it.
class SocialLoginInvUserAPIView(APIView):
permission_classes = [AllowAny]
#staticmethod
def post(request):
print(request.data["token"])
return redirect("login/")
Here is the login url:
url(r'login/$',
LoginInvUserAPIView.as_view(),
name='auth_user_login'),
redirect("url_name")
This is how redirect works. Don't give url but give its name. Here,
you must write:
....
return redirect('auth_user_login')
....

user_passes_test: raise exception if user does not pass

I am trying to define a decorator to check if the user has admin certain privileges:
def admin_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
actual_decorator = user_passes_test(
lambda u: u.is_staff and u.is_authenticated() and not Association.objects.filter(admins=u).exists(),
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
The aim is to use this throught the views. Particularly, I am using it in a class-based view:
class MyCBV(CreateView):
#method_decorator(admin_required)
def dispatch(self, request, *args, **kwargs):
return super(MyCBV, self).dispatch(request, *args, **kwargs)
The problem is that this view is loaded via AJAX, so the redirect doesn't happen. Also, the HTTP status the view returns is success even when the user authentication fails, so the client (JS) has no way of telling when the action really succeeded or not.
I usually have trouble understanding decorators and Django authentication, so my question is: how can I raise an exception (preferably the PermissionDenied exception) when the authentication decoration function fails?
In Django 1.9+, you can use the UserPassesTestMixin instead of a decorator, and set raise_exception to True.
Since you are using Django 1.4, which is insecure and obsolete, you won't be able to do this. There isn't an option to make user_passes_test raise PermissionDenied rather than redirect. You could either try to detect the redirect in your JavaScript, or look at the user_passes_test source code and implement something similar that returns the response you want.

Django REST Framework strange results

For some reason, I'm getting some weird problems with sending a POST request.
This is my URL settings:
http://host/api/user/1/edit/
http://host/api/address/search/
Where /api/ is the API-Root, user is a model, 1 is user ID, and edit and search are custom functions.
This is inside views.py:
class UserViewSet(viewsets.ModelViewSet):
...
def post(self, request, pk, *args, **kwargs):
... (processing)
#detail_route(methods=['post'])
def edit(self, request, pk, *args, **kwargs):
... (processing)
class AddressViewSet(viewsets.ModelViewSet):
...
def post(self, request, *args, **kwargs):
... (processing)
#detail_route(methods=['post'])
def search(self, request, *args, **kwargs):
... (processing)
This is inside urls.py:
router = DefaultRouter()
router.register(r'user', views.UserViewSet)
router.register(r'address', views.AddressViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^authentication/', include('rest_framework.urls', namespace='rest_framework'))
]
The strange thing I'm encountering is this:
If I'm using httpie and sending a POST edit request like this:
http POST http://host/api/user/1/edit/ name="john" address="google.com"
Then the stuff inside def post will never get executed. This is the same if I make the browser send a POST request.
However, if I send a POST search request by doing:
http POST http://host/api/address/search/ name="john"
Then in this case the stuff inside def search will never get executed, while only the stuff inside def post will get executed.
The only difference I can see is that for edit, there's an extra pk (value of 1 for this example), while there are no pk for `search.
Does anyone know why this is happening? It's really confusing for me
Defining post() in a ViewSet doesn't do anything, this is for APIView derived classes. If you want to override default object creation in a ViewSet you can either
def create(self, request, *args, **kwargs):
... do stuff ...
or even better
def perform_create(self, serializer):
... do stuff ...
serializer.save()
As for the address, you need to use list_route decorator instead of detail_route. detail_route is for operating on an individual object and list_route is for lists. So /address/search/ should be list route and /address/1/search/ would be a detail_route. Mind you that I don't think your code in post() runs in either case.
Here is a relevant piece of docs http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing
When submitting a post request to rest framework the request is mapped to methods on the ViewSet, unlike Django views that simply call the post method.
When posting to user/{pk}/ your request is mapped to the UserViewSet.create method. A post request to user/{pk}/edit/ maps to your UserViewSet.edit method. In both cases, UserViewSet.post is not called.
It seems that when you post to a custom url that doesn't exist the post method is called instead (probably as a fallback). In your case address/search/ isn't a valid url, and instead you've defined an endpoint as address/{pk}/search/.
If you want to access address/search/ you need to update your search method to use a list_route decorator instead of detail_route:
class AddressViewSet(viewsets.ModelViewSet):
...
#list_route(methods=['post'])
def search(self, request, *args, **kwargs):
... (processing)
Hope this helps to clear things up for you.

How to write own methods in class based views and call the methods in urls

Here is my code. I was just trying to implement this but could not.I am in a stage of leaning Django
class BCD(View):
def start(self):
return HttpResponse("Huray Finally I called")
urls.py
urlpatterns = patterns('',
url(r'^login1/$',BCD.as_view(),)
And even i tried
urlpatterns = patterns('',
url(r'^login1/$',BCD.start.as_view(),)
It throws error.I have read the docs of django methods such as get and post ,head can be written they will be called directly according to the request made.But what I is need to make my own methods in class based views
Thanks in Advance
You need to call methods in get(), post() or whatever the HTTP request is. There isn't a start HTTP request so Django won't call that.
You can do the following in your view:
def get(self, request, *args, **kwargs):
return self.start()
This return the result of self.start() whenever you visit your view with a HTTP GET request.

Django GET and POST handling methods

I want a way to automatically route GET and POST requests to subsequent methods in a centralized way.
I want to create my handler in the following way.
class MyHandler(BaseHandler):
def get(self):
#handle get requests
def post(self):
#handle post requests
This is what webapp2 does and I very much like the style, is it possible to do in Django?
I also want the view in Class-method style. What kind of BaseHandler and router should I write.
HINT: Use django generic views.
This is supported in Django as class based views. You can extend the generic class View and add methods like get(), post(), put() etc. E.g. -
from django.http import HttpResponse
from django.views.generic import View
class MyView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('This is GET request')
def post(self, request, *args, **kwargs):
return HttpResponse('This is POST request')
The dispatch() method from View class handles this-
dispatch(request, *args, **kwargs)
The view part of the view – the
method that accepts a request argument plus arguments, and returns a
HTTP response.
The default implementation will inspect the HTTP method and attempt to
delegate to a method that matches the HTTP method; a GET will be
delegated to get(), a POST to post(), and so on.
By default, a HEAD request will be delegated to get(). If you need to
handle HEAD requests in a different way than GET, you can override the
head() method. See Supporting other HTTP methods for an example.
The default implementation also sets request, args and kwargs as
instance variables, so any method on the view can know the full
details of the request that was made to invoke the view.
Then you can use it in urls.py -
from django.conf.urls import patterns, url
from myapp.views import MyView
urlpatterns = patterns('',
url(r'^mine/$', MyView.as_view(), name='my-view'),
)

Categories

Resources