For every user in my django application, I generate a static .ical file which I would like to serve. Is there a CBV for that and which method would I overwrite?
As all of my views are class based I' d rather not use a function-based view with a HttpResponse and a #auth_required decorator according to this:
Django: Serving a Download in a Generic View
Just inherit from the View model and override the view method.
class ICalDownload(View):
def get(self, *args, **kwargs):
# return your response just like you would in a function view.
If you want to protect the view, I like to use django-braces. Otherwise, you need to use method_decorator on the dispatch method:
#method_decorator(auth_required)
def dispatch(self, *args, **kwargs):
return super(ICalDownload, self).dispatch(*args, **kwargs)
At this point, a function based view might be a little simpler, but like you, I like to always use class based views.
Related
I have a created a view class "class Demo", which has 3 functions
def update_time()
def get_context()
def before_response()
urls.py : url(r'^demo/$', Demo.as_view(),name='demo_class'),
When i'll enter url /demo/ how will it determine which function to call from "class Demo" ?
Because Django’s URL resolver expects to send the request and associated arguments to a callable function, not a class, class-based views have an as_view() class method which serves as the callable entry point to your class. The as_view entry point creates an instance of your class and calls its dispatch() method. dispatch looks at the request to determine whether it is a GET, POST, etc, and relays the request to a matching method if one is defined, or raises HttpResponseNotAllowed if not.
just read the docs
Basically class based views are recommended when you need to handle both get and post requests at one point. For example in get method of class Register, you can render the registration form and in its post method, you can handle the form submission. If its a get request it will automatically invoke the get() method in the class, same for post request. Also you can write any common code in the dispatch() method which will be invoked for every request.eg:
class Register(View):
def dispatch(self, *args, **kwargs):
'''
common code here
'''
return super(Register, self).dispatch(*args, **kwargs)
def get(self, request):
registration_form = RegistrationForm()
return render(request, 'new.html', { 'form': registration_form })
def post(self, request):
registration_form = RegistrationForm(request.POST or None)
if registration_form.is_valid():
#save form
return HttpResponseRedirect(reverse('success-show'))
return render(request,new.html', { 'form': registration_form })
For references you can check this website.
You need to subclass a class based views, and depending on that it will have one or another method.
For example TemplateView renders a template you pass in the template_name attribute.
All class based views care about is that the attributes needed to work properly are setted. That is done via different methods. You can check the django's documentation for specifics.
For example, if you want to render a form in your template view, you will need to pass the form in the context, so you can override get_context_data() like:
def get_context_data(self, **kwargs):
context = super(DemoClass, self).get_context_data(**kwargs)
context['form'] = MyForm()
return context
There are different methods to handle different things, like querysets, objects, etc.
They are not complicated, but they are specific. If a class based view does not fit what you need, it may be easier to implement the functionality from a more general view (View, TemplateView) than forcing a more specific one to do things it is not intended for.
slightly change the url
add numbers one to three in url and put the condition in your view.
Ex.
url(r'^abc/(?P<newid>.*)$', 'class_demo'),
so your url will be like abc/1 or abc/2 or abc/3
view
def class_demo(requests, newid):
if newid==1:
update_time()
elif newid==2:
get_context()
I believe this is a simple one, just can't spot the solution. I have a view that does a bit of work on the server then passes the user back to another view, typically the original calling view.
The way I'm rendering it now, the url isn't redirected, ie it's the url of the original receiving view. So in the case the user refreshes, they'll run that server code again.
class CountSomethingView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
# so some counting
view = MyDetailView.as_view()
return view(request, *args, **kwargs)
I strongly recommend not overriding get or post methods. Instead, override dispatch. So, to expand on Platinum Azure's answer:
class CountSomethingView(LoginRequiredMixin, RedirectView):
permanent = False
def get_redirect_url(self, **kwargs):
url = you_can_define_the_url_however_you_want(**kwargs)
return url
def dispatch(self, request, *args, **kwargs):
# do something
return super(CountSomethingView, self).dispatch(request, *args, **kwargs)
when a user does an action and I need to redirect him to the same page, first of all I use a templateView to display a simple "thanks" (for example) then provide a link to go back to the previous page with a simple {% url %}
for example :
from django.views.generic import CreateView, TemplateView
from django.http import HttpResponseRedirect
class UserServiceCreateView(CreateView):
form_class = UserServiceForm
template_name = "services/add_service.html"
def form_valid(self, form):
[...]
return HttpResponseRedirect('/service/add/thanks/')
class UserServiceAddedTemplateView(TemplateView):
template_name = "services/thanks_service.html"
def get_context_data(self, **kw):
context = super(UserServiceAddedTemplateView, self).\
get_context_data(**kw)
context['sentance'] = 'Your service has been successfully created'
return context
in the template thanks_service.html i use {% url %} to go back to the expected page
Hope this can help
Performing a redirect in a Django Class Based View is easy.
Simply do a return redirect('your url goes here').
However, I believe this isn't what you want to do.
I see you're using get().
Normally, when speaking about HTTP, a GET request is seldom followed by a redirect.
A POST request is usually followed by a redirect because when the user goes backwards you wouldn't want to submit the same data again.
So what do you want to do?
What I think you want to do is this:
def get(self, request, *args, **kwargs):
return render_to_response('your template', data)
or even better
def get(self, request, *args, **kwargs):
return render(request, self.template_name, data)
If you're creating or updating a model, consider inheriting from CreateView or UpdateView and specifying a success_url.
If you're really doing a redirect off of an HTTP GET action, you can inherit from RedirectView and override the get method (optionally also specifying permanent = False):
class CountSomethingView(LoginRequiredMixin, RedirectView):
permanent = False
def get(self, request, *args, **kwargs):
# do something
return super(CountSomethingView, self).get(self, request, *args, **kwargs)
Note that it's really bad practice to have a get action with side-effects (unless it's just populating a cache or modifying non-essential data). In most cases, you should consider using a form-based or model-form-based view, such as CreateView or UpdateView as suggested above.
We use class based views for most of our project. We have run into an issue when we try and create a CSV Mixin that will allow the user to export the information from pretty much any page as a CSV file. Our particular problem deals with CSV files, but I believe my question is generic enough to relate to any file type.
The problem we are having is that the response from the view is trying to go to the template (say like from django.views.generic import TemplateView). We specify the template in the urls.py file.
url(r'^$', MyClassBasedView.as_view(template_name='my_template.html'))
How can you force the response to bypass the template and just return a standard HttpResponse? I'm guessing you'll need to override a method but I'm not sure which one.
Any suggestions?
EDIT1: It appears that I was unclear as to what we are trying to do. I have rendered a page (via a class based view) and the user will see reports of information. I need to put in a button "Export to CSV" for the user to press and it will export the information on their page and download a CSV on to their machine.
It is not an option to rewrite our views as method based views. We deal with almost all class based view types (DetailView, ListView, TemplateView, View, RedirectView, etc.)
This is a generic problem when you need to provide different responses for the same data. The point at which you would want to interject is when the context data has already been resolved but the response hasn't been constructed yet.
Class based views that resolve to the TemplateResponseMixin have several attributes and class methods that control how the response object is constructed. Do not be boxed into thinking that the name implies that only HTML responses or those that need template processing can only be facilitated by this design. Solutions can range from creating custom, reusable response classes which are based on the behavior of the TemplateResponse class or creating a reusable mixin that provides custom behavior for the render_to_response method.
In lieu of writing a custom response class, developers more often provide a custom render_to_response method on the view class or separately in a mixin, as it's pretty simple and straightforward to figure out what's going on. You'll sniff the request data to see if some different kind of response has to be constructed and, if not, you'll simply delegate to the default implementation to render a template response.
Here's how one such implementation might look like:
import csv
from django.http import HttpResponse
from django.utils.text import slugify
from django.views.generic import TemplateView
class CSVResponseMixin(object):
"""
A generic mixin that constructs a CSV response from the context data if
the CSV export option was provided in the request.
"""
def render_to_response(self, context, **response_kwargs):
"""
Creates a CSV response if requested, otherwise returns the default
template response.
"""
# Sniff if we need to return a CSV export
if 'csv' in self.request.GET.get('export', ''):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="%s.csv"' % slugify(context['title'])
writer = csv.writer(response)
# Write the data from the context somehow
for item in context['items']:
writer.writerow(item)
return response
# Business as usual otherwise
else:
return super(CSVResponseMixin, self).render_to_response(context, **response_kwargs):
Here's where you can also see when a more elaborate design with custom response classes might be needed. While this works perfectly for adding ad-hoc support for a custom response type, it doesn't scale well if you wanted to support, say, five different response types.
In that case, you'd create and test separate response classes and write a single CustomResponsesMixin class which would know about all the response classes and provide a custom render_to_response method that only configures self.response_class and delegates everything else to the response classes.
How can you force the response to bypass the template and just return
a standard HttpResponse?
This kinda defeats the point of using a TemplateView. If the thing you're trying to return isn't a templated response, then it should be a different view.
However...
I'm guessing you'll need to override a method but I'm not sure which one.
...if you prefer to hack it into an existing TemplateView, note from the source code...
class TemplateView(TemplateResponseMixin, ContextMixin, View):
"""
A view that renders a template. This view will also pass into the context
any keyword arguments passed by the url conf.
"""
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
...so you'd have to override the get() method so it doesn't call render_to_response() when returning your CSV. For example...
class MyClassBasedView(TemplateView):
def get(self, request, *args, **kwargs):
if request.GET['csv'].lower() == 'true':
# Build custom HTTP response
return my_custom_response
else:
return TemplateView.get(request, *args, **kwargs)
If you need a generic mixin for all subclasses of View, I guess you could do something like...
class MyMixin(object):
def dispatch(self, request, *args, **kwargs):
if request.GET['csv'].lower() == 'true':
# Build custom HTTP response
return my_custom_response
else:
return super(MyMixin, self).dispatch(request, *args, **kwargs)
class MyClassBasedView(MyMixin, TemplateView):
pass
I have a template that I want to be able to both serve directly and embed in arbitrary other templates in my Django application. I tried to create a view class for it that looks like this:
class TemplateView(View):
def get(self, request):
context = self._create_context(request)
return render_to_response('template.html', context)
def get_string(self, request):
context = self._create_context(request)
return render_to_string('template.html', context)
def _create_context(self, request):
context = {}
# Complex context initialization logic...
return context
I've wired get to my Django URLs. However, I haven't been able to figure out how to instantiate TemplateView so that I can call get_string from other views.
There must be a better way to go about doing this. Ideas?
Update: I've seen some folks talking about making a request internally and using response.content, which would save me from having to write the get_string method. So, perhaps a better question is: How do I make a request to TemplateView from another view?
I'd follow in django's CBV pattern: it determines via dispatch what method to return. By default based on request.method. Why not based on any other argument passed to dispatch()?
So subclass dispatch and give it a way to determine whether or not to return get_string.
def dispatch(self, request, *args, **kwargs):
if 'as_string' in kwargs:
return self.get_string(request)
return super(TemplateView, self).dispatch(request, *args, **kwargs)
response = TemplateView.as_view()(request, as_string=True)
I am new to django and in my current job i had to edit the existing code.
Now i am not able to find in the documentation where i can find all methods which can be over ridden and what they are suppose to do.
In mY views file someone has defined these functions but i don't know what they are supposed to do.
Like
def get_context_data(self, **kwargs):
def get(self, request, *args, **kwargs):
def post(self, request, *args, **kwargs):
def get_success_url(self):
def form_valid(self, form):
Now i am not sure if he as write his new methods or He is overriding the buil in methods because he is not calling them anywhere.
can someone guide where are these methods defined in documentation so that i can see what are some other methods and what they do
I found this resource really uesful, as it saves you having to manually trace inheritance hierarchies to check which methods a class has.
http://ccbv.co.uk/
The official documentation is here, depending on your django version:
https://docs.djangoproject.com/en/1.3/ref/class-based-views/
https://docs.djangoproject.com/en/1.4/ref/class-based-views/
https://docs.djangoproject.com/en/dev/ref/class-based-views/
get_context_data returns the data that will be accessible in your template
get is all the actions that are performed when a page is loaded
post is all the actions that are performed when data is posted to a url
get_success_url returns the url that the user will be directed to after a post was succesfully made
form_valid here you can add extra actions to the form validation