Convert the Django direct_to_template function to use class based view - python

I am updating a Django project which used the direct_to_template as a function ie:
return direct_to_template(request, 'bprofile/init.html', targs)
As described a short way down this page
I have seen the SO question here and read the documentation on this page which decribe the migration of statements of the form
('^about/$', direct_to_template, {'template': 'about.html'})
to look like
('^about/$', TemplateView.as_view(template_name='about.html'))
Unfortunatelty I cannot seem to figure out how to change statements from the form that I have into a working new form.
How might one modify this code to work with the new Templateview form?

You shouldn't be using the generic views for this, that's not what they are for. If you want to render a template, you should use the render shortcut: it takes exactly the same arguments.
return render(request, 'bprofile/init.html', targs)

To use TemplateView you import TemplateView into your urls.py:
from django.views.generic.base import TemplateView
Then you just add the urlconf:
('^about/$', TemplateView.as_view(template_name='bprofile/init.html'))

Related

Is it required to add custom views in admin page in ModelAdmin class when we can do it normally by adding views in views.py and urls in urls.py?

According to django docs:
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.my_view),
]
return my_urls + urls
def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)
If I am not wrong, we can do the same thing by adding url in urls.py and the views in views.py as it is normally done then, what is the use of introducing this way? I am a newbie to django and I may be missing something here.
Can you please provide an example where we cannot do it in views.py and we must use the above method?
Any guidance/help would be appreciated.
I think I figured out, both of them can be used to do the same thing but the key difference is that the views which you write using above method will belong to admin app while the general views in views.py belongs to the particular app in you have written.
Hence, the url in ModelAdmin need to be called using name admin:url_name since the url goes as admin/my_views/ in given example.

Django Templates can not access to context

I checked all the questions and answers in this site, but could not find a solution. I am new in Django, trying to develop a storage model and stucked already in the ListView.
part of my view.py:
from django.shortcuts import render, redirect
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from Storage.models import Storage
from django.http import HttpResponse
class StorageListView(LoginRequiredMixin, ListView):
model = Storage
print(Storage.objects.order_by('-barcode'))
template_name = 'Storage/Storagelist.html'
def get_queryset(self):
return Storage.objects.order_by('-barcode')
I add print statement to check whether I reach the model and
everyting seems normal:
<QuerySet [<Storage: 123>, <Storage: 122>, <Storage: 121>]>
However, I can not reach the context from the template file 'Storagelist.html':
<h3>trial</h3>
{% if storage_list %} <h3>trial</h3> {% endif %}
Just to check access via url configurations, I added 'trial' at the beginning of the template and it also seems normal. I also tried to use context_object_name, but did not help either. Somehow, I can not reach to ListView context data from the template.
My versions of applications are as follows:
Django 2.0.3
Python 3.6.1
Can somebody please help me?
In a ListView I believe the objects will populate into the template as object_list. You might consider using this method to make the template context variable human readable (and also match what you are expecting). In other words, try adding context_object_name = storage_list to your view.

Django - CreateView form on existing view and url

I'm using django generic views in my project CRUD. The CreateView class uses the following url to work:
urls.py
url(r'^create', BookCreate.as_view(model=Books, template_name='Myproj/book_create.html'), name='book_create'),
If I go the www.mywebsite.com/create the form appears just how I wanted it.
My problem is that I want to incorporate the form on another page, that already has a url, a view and a template. The url is like the one bellow:
urls.py
url(r'^author/(?P<id>[0-9]{1,})/$', author_view_handler, name='author_view'),
How can I resolve this?
The CreateView uses a ModelForm. If you want to use it also, you need to create a a Book model form yourself, something like this:
from django.forms import ModelForm
class BookModelForm(ModelForm):
pass
And then instantiate it form=BookModelForm() and pass it to the context of your author_view_handler view.
However I am not really sure why you would want to do something like that...
Update: To pass it to your view, use
from django.shortcuts import render
def author_view_handler(request):
form = BookModelForm()
return render(request, 'author_view_handler.html', {"form": form},
The above just passes the form to the author_view_handler view and does not contain any form handling code.

Login Required Decorator with Many Possible HTML's for Same URL

I would like to restrict access to urls that are served by django generic views. I have researched the login required decorator, but have only had partial success in getting it to work as I have a complication that is not addressed in the docs (or at least I couldn't find it).
Before adding the decorator, in urls.py I have the following:
url(r'^search/(?P<search_type>\w+)', search)
The above named search function is slightly complex in that depending on various conditions, it will render one of four possible html pages.
I don't see in the docs a way to handle multiple html pages using the decorator, and I can't seem to figure out the correct syntax.
I have tried using the decorator with one of the four html pages, and it does work for that one html page:
from django.views.generic import TemplateView
url(r'^search/(?P<search_type>\w+)',
login_required(TemplateView.as_view(template_name='search_form.html',), search)),
But how do I require login for all the possible html's? For example, I tried things like:
url(r'^search/(?P<search_type>\w+)',
login_required(TemplateView.as_view(template_name='search_form.html',), TemplateView.as_view(template_name='search_form_manual.html',), search)),
I also tried subclassing the generic views:
//in view.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name_1 = "search_form.html"
template_name_2 = "search_form_manual.html"
template_name_3 = "search_results.html"
template_name_4 = "tag_search_results.html"
//in urls.py
from views import AboutView
url(r'^search/(?P<search_type>\w+)',
login_required(AboutView.as_view(template_name_1, template_name_2,), search)),
But I get errors that template_name_1 and template_name_2 do not exist...
Any help is appreciated.
Use that with class view
from django.views.generic import TemplateView
class AboutView(TemplateView):
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProtectedView, self).dispatch(*args, **kwargs)
template_name_1 = "search_form.html"
template_name_2 = "search_form_manual.html"
template_name_3 = "search_results.html"
template_name_4 = "tag_search_results.html"

Getting the template name in django template

For debugging purposes, I would like to have a variable in all my templates holding the path of the template being rendered. For example, if a view renders templates/account/logout.html I would like {{ template_name }} to contain the string templates/account/logout.html.
I don't want to go and change any views (specially because I'm reusing a lot of apps), so the way to go seems to be a context processor that introspects something. The question is what to introspect.
Or maybe this is built in and I don't know about it?
The easy way:
Download and use the django debug toolbar. You'll get an approximation of what you're after and a bunch more.
The less easy way:
Replace Template.render with django.test.utils.instrumented_test_render, listen for the django.test.signals.template_rendered signal, and add the name of the template to the context. Note that TEMPLATE_DEBUG must be true in your settings file or there will be no origin from which to get the name.
if settings.DEBUG and settings.TEMPLATE_DEBUG
from django.test.utils import instrumented_test_render
from django.test.signals import template_rendered
def add_template_name_to_context(self, sender, **kwargs)
template = kwargs['template']
if template.origin and template.origin.name
kwargs['context']['template_name'] = template.origin.name
Template.render = instrumented_test_render
template_rendered.connect(add_template_name_to_context)
From Django 1.5 release notes:
New view variable in class-based views context
In all generic class-based views (or any class-based view inheriting from ContextMixin), the context dictionary contains a view variable that points to the View instance.
Therefore, if you're using class-based views, you can use
{{ view.template_name }}
This works if template_name is explicitly set as an attribute on the view.
Otherwise, you can use
{{ view.get_template_names }}
to get a list of templates, e.g. ['catalog/book_detail.html'].
Templates are just strings not file names. Probably your best option is to monkey patch render_to_response and/or direct_to_template and copy the filename arg into the context.

Categories

Resources