Is there a way to call all my user data? without using all the template variables in my views
Templates:
{% csrf_token %}
<h1>Welcome {{user.full_name}} {{user.last_name}}</h1>
<h1>{{user.email}}</h1>
so in my views I'll use less code, by not declaring all the dict
views
return render_to_response('user/userhome.html', user)
For django version 1.8 or more you can directly access {{user}} in template. However you can add the following in the TEMPLATE_CONTEXT_PROCESSOR of your settings to access {{user}} directly in the template.
'django.contrib.auth.context_processors.auth',
You can use a dict-like object that defines __contains__ and __getitem__, but uses attribute access to set properties, eg.:
from django import shortcuts, template
from django.contrib.auth.decorators import login_required
class Page(dict):
# see http://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute-in-python
def __init__(self, *args, **kwargs):
super(Page, self).__init__(*args, **kwargs)
self.__dict__ = self
#login_required
def foo(request):
page = Page()
page.user = request.user
return shortcuts.render_to_response('foo.html', page)
then you can write your template exactly the way you would like.
Related
I've passed a variable to base.html from my views.py file in a context. I've extended this base.html to another several templates. The variable is only visible in the base.html and not any other extended template.
It does work if I pass the same context to each templates views.py file.
As I extended the base, shouldn't it also extend the variable? Is there any other way to get this working, or am I missing something?
When you extend a template, it inherits the html code. The context needs to be always injected by the view. If you want to pass always the same context, you need to subclass the view and not the template. You can write a mixin:
class GetContextViewMixin:
def get_context_data(self, *args, **kwargs):
return ['foo': 'foo'] # Replace with the real context
Then when you need the same context, you can use inheritance:
from django.views.generic import TemplateView
# The template of this view will obtain its context from the mixin method
class ExampleView(GetContextViewMixin, TemplateView):
template_name = 'foo.html'
If you want to extend the context in subclasses, you can override get_context_data (remember to call super):
from django.views.generic import TemplateView
class ExampleView2(GetContextViewMixin, TemplateView):
template_name = 'foo2.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['foo2'] = 'foo2' # Extend the context
return context
I know there is a change/update view in Django admin but is there any detail view that just lists out the record's attributes? Kind of like the DetailView in the Django app?
Or does anyone know any 3rd party packages I can install to provide the same functionality?
I too was investigating this recently.
One approach that works is to create a custom ModelAdmin with a detail_view method that forwards the call to ModelAdmin's changeform_view() method. Then this view is added to the urls list via overriding ModelAdmin.get_urls().
Then, in this method set a class attribute, say __detail_view to True. Then override has_change_permission() method, which returns False, if __detail_view is detected and set to True. This will cause AdminSite to render the fields in readonly mode (using the AdminReadonlyField wrapper fields) instead of the standard AdminField objects.
You can also change the change_form_template to a custom template for detail_view to accommodate custom rendering for detail views.
class CustomModelAdmin(admin.ModelAdmin):
def has_change_permission(self, request, obj=None):
if getattr(self, '__detail_view', None):
return False
return super().has_change_permission(request, obj)
def detail_view(self, request, object_id, form_url='', extra_context=None):
setattr(self, '__detail_view', True)
# Custom template for detail view
org_change_form_template = self.change_form_template
self.change_form_template = self.detail_view_template or self.change_form_template
ret = self.changeform_view(request, object_id, form_url, extra_context)
self.change_form_template = org_change_form_template
delattr(self, '__detail_view')
return ret
def get_urls(self):
urls = super().get_urls()
# add detail-view for the object
from django.urls import path
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
wrapper.model_admin = self
return update_wrapper(wrapper, view)
info = self.model._meta.app_label, self.model._meta.model_name
# Replace the backwards compatibility (Django<1.9) change view
# for the detail view.
urls[len(urls)-1] = path('<path:object_id>/', wrap(self.detail_view), name='%s_%s_detail' % info)
return urls
I haven't tried the custom template approach, but using the __detail_view object attribute to force readonly rending seems to work.
The default change_form_template still shows the delete button at the bottom, which is okay I guess. But it needs another button to actually take you to the real change page where the object can be changed. Again template customization is the way to go here. Hint: look at {% submit_row %} in admin templates and model a custom inclusion template tag that displays the Change button, if the user has change permission. Take note to call the has_change_permission() here to get the real permission before setting the __detail_view attribute.
Not sure if there are other implications for doing it this way, but it ought to work.
HTH
This is the views.py file:
from django.shortcuts import render
from django.views.generic import TemplateView
from .models import Report
import random
class HomePageView(TemplateView):
def get(self, request, **kwargs):
args = {}
data = Report.objects.all()
args['data'] = data
return render(request, 'index.html',args)
I'm finding it difficult to understand the framework since I'm a beginner. So please help me.
You are trying to use class base view which will be different from function base view, to pass context data to template in class base view you need to override get_context_data method as below:
class HomePageView(TemplateView):
""" Home page view """
template_name = "index.html"
def get_context_data(self, **kwargs):
# first of all calling it's parent class method to get context (if any)
context = super(HomePageView, self).get_context_data(**kwargs)
# now you can update context dictionary as below:
context['data'] = Report.objects.all()
return context
Now you can access data in your template using {{ data }}
You can display the FileField content by passing the following
{{ context_obj.file_field_name.url }} in the template.
Context processors in Django usually allow for a variable to be accessed by all templates. How do I access this variable in the views.py (backend) code?
Here is what I have tried:
def index(request):
request_context = RequestContext(request)
center = request_context.get("center")
But I get "none" for the center variable.
And in the context processor code:
def center(request):
return {'center': '123'}
I have added the context processor's "center" function to the context processor list in settings.
Use decorators instead of context_processors. It will be really very simple for you.
In views.py use #csrf_exempt before function from which you want to take a variable and use {% csrf_token %} on the end of a line in the template where you want to use that variable.
Official documentation on csrf decorators
If you need to see an example then check out this. Here in template/add_comment.html and views.py is using decorators.
NOTE:- you need to import csrf_exempt in views.py before using it like:-
from django.views.decorators.csrf import csrf_exempt
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()