I've been trying for a while to get a ModelResource or a View working using the Django Rest Framework. I'm following the examples but the code in the examples is not working for me. Can anyone tell me why I might be getting this error.
views.py
# Create your views here.
from django.http import HttpResponse
from django.utils import simplejson
from django.core import serializers
from djangorestframework.views import View
from djangorestframework.response import Response
from djangorestframework import status
from interface.models import *
def TestView(View):
def get(self, request):
return Person.objects.all()
urls.py
from django.conf.urls.defaults import *
from djangorestframework.resources import ModelResource
from djangorestframework.views import ListOrCreateModelView, InstanceModelView, View
from interface.models import *
from interface.views import *
class PersonResource(ModelResource):
model = Person
ordering = ('LastName')
urlpatterns = patterns('',
url(r'^$', 'interface.views.index'),
url(r'^testview/$', TestView.as_view()),
url(r'^people/$', ListOrCreateModelView.as_view(resource=PersonResource)),
)
I'm now getting the error 'function' object has no attribute 'as_view'.
Since this is the #1 hit on google for this error message and there's a more subtle and probably common cause for it than the OPs, I'm posting this comment here.
This error can also be caused by using a standard view decorator on a class based view instead of on the __dispatch__ method within the view.
def TestView(View): should be class TestView(View):. As it stands, you define a function called TestView which takes an argument called View -- its body defines an inner function, then returns None.
To add to Tim Saylor point,
https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#id1
To decorate every instance of a class-based view, you need to decorate
the class definition itself. To do this you apply the decorator to the
dispatch() method of the class.
A method on a class isn’t quite the same as a standalone function, so
you can’t just apply a function decorator to the method – you need to
transform it into a method decorator first. The method_decorator
decorator transforms a function decorator into a method decorator so
that it can be used on an instance method. For example:
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
class ProtectedView(TemplateView):
template_name = 'secret.html'
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProtectedView, self).dispatch(*args, **kwargs)
I am also getting this error but in my case i solved it with following idea.
That error usually happens if you try to override a class. That sometimes happens if you copy&paste code and forget to change e.g. the class name. But in my case it was little different
If you apply #login_required to a class, you will receive the error message:
‘function’ object has no attribute ‘as_view’
So, how should you decorate classes in Django now?
For class-based views, you have two options of decorating your classes.
1) Decorating the URLconf
2) Decorating the class
Both options leads to the same result - restricting the access to a class only for logged users. The difference between the options is how the decorator is applied to the class instance.Refer this page for decorators implementation
https://docs.djangoproject.com/en/1.4/topics/class-based-views/#decorating-class-based-views
use this if you use a class your decorator should be
import first:
from django.utils.decorators import method_decorator
then
#method_decorator(login_required(login_url='login'),name="dispatch")
class YourClassView(YourView):
Related
I'm trying to add a custom permission to a view which extends a generic DetailView:
from django.views.generic import DetailView
from rest_framework.permissions import BasePermission
class MyCustomPermission(BasePermission):
def has_permission(self, request, view):
return False
class MyView(SomeMixin, DetailView):
model = MyObject
template_name = "my_template.html"
permission_classes = [MyCustomPermission]
def get_object(self):
return MyObject.objects.get(id=123)
This should always fail, but it doesn't. I can also put a breakpoint in there (e.g. import pudb; pudb.set_trace()) but that won't ever get hit either.
I know that has_object_permission(...) needs to be explicitely called, but I thought has_permission(...) got called when the view first got called.
You are using Django generic DetailView and expecting to behave as DRF views
So I want to customize the admin page using the AdminSite class as described in the docs.
from django.contrib.admin import AdminSite
from .models import MyModel
class MyAdminSite(AdminSite):
site_header = 'Monty Python administration'
admin_site = MyAdminSite(name='myadmin')
But instead of using admin_site.register(MyModel) I would like to use the register decorator like
from django.contrib.admin import ModelAdmin
#admin_site.register(MyModel)
class MyModelAdmin(ModelAdmin):
pass
However, this only throws the error TypeError: 'NoneType' object is not callable. Is there now register decorator for subclasses of AdminSite in Django yet (1.9) or am I missing something?
You can use the keyword argument site like this:
#admin.register(MyModel, site=MyAdminSite)
from django.contrib import admin
...
#admin.register(MyModel, site=MyAdminSite)
class MyModelAdmin(ModelAdmin):
pass
Docs on the register decorator:
https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#the-register-decorator
I'm not sure if you have figured it out yet. But I see that you haven't subclassing admin.ModelAdmin in your admin class.
#admin_site.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
pass
class MyAdminSite(AdminSite):
...
admin_site = MyAdminSite()
#admin_site.register(MyModel)
def ...
TypeError: 'NoneType' object is not callable is caused by the fact that admin_site.register is calling method register of AdminSite.
You should use django.contrib.admin.register which is the correct decorator:
from django.contrib import admin
#admin.register(MyModel, site=admin_site)
class MyModelAdmin(ModelAdmin):
...
When using method-based view, redirecting with reverse didn't complain about this and can still find the root url conf. But, in class-based views, it complain:
ImproperlyConfigured at /blog/new-post/
The included urlconf 'blog.urls' does not appear to have any
patterns in it. If you see valid patterns in the file then the
issue is probably caused by a circular import.
My class is defined like this:
class BlogCreateView(generic.CreateView):
form_class = Blog
template_name = 'blog/new-post.html'
success_url = reverse('blog:list-post')
How to properly use reverse for success_url in class-based views? Thanks.
PS: And I'm interested in why it's need to restart runserver after this error (not like an error like TemplateDoesNotExists which is no need to restart runserver)
Using reverse in your method works because reverse is called when the view is run.
def my_view(request):
url = reverse('blog:list-post')
...
If you overrride get_success_url, then you can still use reverse, because get_success_url calls reverse when the view is run.
class BlogCreateView(generic.CreateView):
...
def get_success_url(self):
return reverse('blog:list-post')
However, you can't use reverse with success_url, because then reverse is called when the module is imported, before the urls have been loaded.
Overriding get_success_url is one option, but the easiest fix is to use reverse_lazy instead of reverse.
from django.urls import reverse_lazy
# from django.core.urlresolvers import reverse_lazy # old import for Django < 1.10
class BlogCreateView(generic.CreateView):
...
success_url = reverse_lazy('blog:list-post')
To answer your final question about restarting runserver, the ImproperlyConfigured error is different from TemplateDoesNotExists because it occurs when the Django application is loaded.
Try using reverse_lazy instead of reverse in your CBV. Its a lazily evaluated version of reverse. It won't execute until the value is needed.
from django.core.urlresolvers import reverse_lazy
class BlogCreateView(generic.CreateView):
form_class = Blog
template_name = 'blog/new-post.html'
success_url = reverse_lazy('blog:list-post')
I have an admin mixin that I'm using to prevent caching and make sure users are logged in by overriding dispatch(). It's being used in my class-based views.
# mixins.py
from django.contrib.admin.views.decorators import staff_member_required
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
class AdminPageMixin(object):
#method_decorator(never_cache)
#method_decorator(staff_member_required)
def dispatch(self, request, *args, **kwargs):
return super(AdminPageMixin, self).dispatch(request, *args, **kwargs)
# views.py
class SomeAdminView(AdminPageMixin, ListView):
I'm running into a problem when I'm trying to run unit tests against SomeAdminView. Yes, I know I can use django's test client to login, but I'm trying to stay away from writing functional tests. I'd like, instead, to wrap AdminPageMixin functionality into a single decorator and call that decorator in urls.py, like so:
url(r'^myurl/$', decorator_wrapper(SomeAdminView.as_view()), name='some-admin-view'),
Alternatively, I could do this:
url(r'^myurl/$', never_cache(staff_member_required(SomeAdminView.as_view())), name='some-admin-view'),
but if I wanted to add a third or forth decorator, I'd be updating a lot of lines in urls.py and repeating a lot of code.
Any ideas how to create this decorator wrapper?
It is quite against the spirit of the CBVs to use decorators in the URLconfs. Instead, use mixins to add the functionality directly to the dispatch method of the view class.
It happens a lot, when all the views in a specific module are supposed to be available only when the user is authorized, or they should all do the same checks.
How could I avoid repeating the annotations all over the file?
In your urls
url(r'someregexp/$', mydecorator(view.myview.dude), 'name_of_view'),
When using class-based views you can create a base class/mixin for all these views which implements the desired functionality (also using decorators) and then have all the views inherit from this base view.
from django.views.generic import TemplateView
class BaseView(TemplateView):
def get(self, request, *args, **kwargs):
# do some checking here
if not request.user.is_authenticated():
# do something if anonymous user
return super(BaseView, self).get(request, *args, **kwargs)
class MyView(BaseView):
pass
You could write a dispatcher, but if you have many urls for a module it would probably be more convenient to create a middleware layer.
See also: decorating-all-django-admin-views-1-4
When many urls need to be added, better wrap the decorator inside a function and call that function.
from django.conf.urls import re_path
from . import views
from somewhere import decorator
def url_with_decorator(regex, view, kwargs=None, name=None):
return re_path(regex, decorator(view), kwargs, name)
urlpatterns = [
url_with_decorator(r'^$', views.index, name='index'),
url_with_decorator(r'^any_thing$', views.any_view, name='index'),
# TODO: add url here
]