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.
Related
Need to access URL by name at model, can't just hardcode it. Need it for error message for a new object creating. Any suggestions?
Update: Just need to put url to error message, not reverse
Your question is not totally clear, but I think you are asking about the reverse function.
You can define get_absolute_url method in your model and than access it in other model's methods. Check https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url
I suggest you use a template tag. You can build one for your model and avoid polluting the model about stuff not related to the domain level and keep the presentation level to the template.
Check the docs here on how add a templatetags your app.: https://docs.djangoproject.com/en/2.1/howto/custom-template-tags/
Here a snippet of code to use as starting point for your url generation
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def url_for_object(context, object):
# you have both the context and the object available to
# generate your url here
url = ....
return url
In your template use
{% url_for_object my_object %}
<p>Hello, my name is {{ name }} ! </p>
Where/how do I set the variable: name = 'mike'? I've tried putting this in the settings.py and models.py file and it does not work.
Any info of proper code to put in a .py file would be great! I've searched through the docs page but didn't see how to set a variable for retrieval.
You need to set your variable value in the view function which normally put in view.py
e.g.
def hello(request):
return render(request, "hello.html", {"name": "mike"})
And you may would like to check https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#render to find more about how to render templates with passed variables.
You need also learn more about how does Django's URL mapping works https://docs.djangoproject.com/en/dev/ref/urls/
Use context processors in django. Django handles this dilemma of making some information available to
all pages with something called context processors.
Some Code is like this,
Create a new file called context_processors.py inside your utils app directory, and add the
following code to it:
from project import settings
def context_data(request):
return {
'name': settings.name,
'request': request
}
I am working on Django Project where I need to extract the list of user to excel from the Django Admin's Users Screen. I added actions variable to my Sample Class for getting the CheckBox before each user's id.
class SampleClass(admin.ModelAdmin):
actions =[make_published]
Action make_published is already defined. Now I want to append another button next to Add user button as shown in fig. . But I dont know how can I achieve this this with out using new template. I want to use that button for printing selected user data to excel. Thanks, please guide me.
Create a template in you template folder: admin/YOUR_APP/YOUR_MODEL/change_list.html
Put this into that template
{% extends "admin/change_list.html" %}
{% block object-tools-items %}
{{ block.super }}
<li>
Export
</li>
{% endblock %}
Create a view function in YOUR_APP/admin.py and secure it with annotation
from django.contrib.admin.views.decorators import staff_member_required
#staff_member_required
def export(self, request):
... do your stuff ...
return HttpResponseRedirect(request.META["HTTP_REFERER"])
Add new url into YOUR_APP/admin.py to url config for admin model
from django.conf.urls import patterns, include, url
class YOUR_MODELAdmin(admin.ModelAdmin):
... list def stuff ...
def get_urls(self):
urls = super(MenuOrderAdmin, self).get_urls()
my_urls = patterns("",
url(r"^export/$", export)
)
return my_urls + urls
Enjoy ;)
The easy and accepted way is to override the template.
If you don't want to mess with the Django templates, you could add a Media class to your admin and add some javascript to create the button although I think creating elements with javascript is a bit nasty and should be avoided.
Though other answers are entirely valid, I think it is important to note that it is absolutely not necessary to add a button to get such behavior. You can use admin actions, as you did for the make_published action.
This as the advantage of not requiring to override any template, and thus prevent from potential troubles when upgrading django version (as admin templates may change, and changes might not be "compatible" with the way you overrode it).
import csv
from django.http import HttpResponse
from django.utils import timezone
def export_as_csv(modeladmin, request, queryset):
opts = modeladmin.model._meta
filename = format(timezone.now(), "{app}_{model}-%Y%m%d_%H%M.csv").format(
app=opts.app_label, model=opts.model_name)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
writer = csv.writer(response)
field_names = [f.get_attname() for f in opts.concrete_fields]
writer.writerow(field_names)
for obj in queryset.only(*field_names):
writer.writerow([str(getattr(obj, f)) for f in field_names])
return response
Admin actions are made for this, adding a custom button is one step closer to "over-customization", which means it's probably time to write your own views.
The admin has many hooks for customization, but beware of trying to use those hooks exclusively. If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.
Quote from the introduction paragraph of Django Admin's documentation
I have a custom Contact Form App, and I want to integrate it with django-cms. From what I understand I have to register the app with django-cms, and then in my views I have to return a RequestContext instance instead of a regular context instance. So in my views.py, I have
return render_to_response('my_template.html',
{'form': form},
context_instance=RequestContext(request))
I don't know if I'm missing something here, but my issue here is that I don't want to hardcode the template name my_template.html. Instead, I want the template to be the same one I put when adding a new page, so my question is, is there a way to get the template from the django-cms page thats hosting the app or do I have to hardcode the template to be used?
If your apphook is a single view mounted on /, you can just use {% extends request.current_page.get_template %}, however this does not work on subpages in your app.
For that you would need to reverse the root view of your app, use cms.utils.page_resolver.get_page_from_request with the use_path argument to get the page, then call get_template on the page and extend that.
Currently, I am writing up a bit of a product-based CMS as my first project.
Here is my question. How can I add additional data (products) to my Product model?
I have added '/admin/products/add' to my urls.py, but I don't really know where to go from there. How would i build both my view and my template? Please keep in mind that I don't really know all that much Python, and i am very new to Django
How can I do this all without using this existing django admin interface.
You will want to wire your URL to the Django create_object generic view, and pass it either "model" (the model you want to create) or "form_class" (a customized ModelForm class). There are a number of other arguments you can also pass to override default behaviors.
Sample URLconf for the simplest case:
from django.conf.urls.defaults import *
from django.views.generic.create_update import create_object
from my_products_app.models import Product
urlpatterns = patterns('',
url(r'^admin/products/add/$', create_object, {'model': Product}))
Your template will get the context variable "form", which you just need to wrap in a <form> tag and add a submit button. The simplest working template (by default should go in "my_products_app/product_form.html"):
<form action="." method="POST">
{{ form }}
<input type="submit" name="submit" value="add">
</form>
Note that your Product model must have a get_absolute_url method, or else you must pass in the post_save_redirect parameter to the view. Otherwise it won't know where to redirect to after save.
This topic is covered in Django tutorials.
Follow the Django tutorial for setting up the "admin" part of an application. This will allow you to modify your database.
Django Admin Setup
Alternatively, you can just connect directly to the database using the standard tools for whatever database type you are using.