I'm trying NOT to write same code twice on different templates. Real hassle when changing something.
So when I go to a section of the webpage, I want to display a side menu. This side-menu is suppose to be on several templates. Like index.html, detail.html, manage.html and so on.
But the section is only a part of the webpage, so I can't have it in base.html.
I was thinking about using include. But since the side menu is dependent of DB queries to be generated, I then have to do queries for each view. Which also makes redundant code.
What is best practice for this feature?
Cheers!
You could write custom inclusion_tag, that's more feasible for the scenario:
my_app/templatetags/my_app_tags.py
from django import template
register = template.Library()
#register.inclusion_tag('side_menu.html')
def side_menu(*args, **kwargs):
# prepare context here for `side_menu.html`
ctx = {}
return ctx
Then in any template you want to include side menu do this:
{% load side_menu from my_app_tags %}
{% side_menu %}
Related
I currently have a function called "copyright" (a dynamic copyright message) that I am trying to include into my base Django template, like below:
def copyright():
some code
some more code
print(finaloutput)
I have it sitting in my modules/utils.py which is in my assets directory which I have registered in my static directories.
I want to be able to call that function like {{ copyright }} straight in my top level base.html inside my main templates folder.
I have tried everything to ensure I am loading the staticfiles with no luck. Am I approaching this the wrong way?
Unfortunately almost everything you're doing here is wrong.
This has nothing to do with static files: as you said yourself, this is a dynamic function so isn't static by definition. Anyway, you can't put Python code in your assets directory. And finally, any function like this will always need to return the result, not print it.
What you need here is a template tag, which you put in your app's templatetags directory and register via the decorator:
#register.simple_tag
def copyright():
some code
some more code
return finaloutput
Then, load the tags in your template and call it as a tag, not a variable:
{% load utils %} # or whatever you called the file
...
{% copyright %}
See the template tags docs.
There are several ways to achieve your end goal, but nothing you are doing will get you there.
You can,
Use template tags.
Use context processors, in several different ways.
Use {{ view.function_name }} as-is in your templates if you are using class based generic views from Django.
Judging from how I think you have things set up, the fastest way could be to just pass in some context data in your views.
If you are using functional views, your code can look something like this:
def my_view(request):
def copyright():
return "copyright 2018"
return render('my_template.html', {'copyright': copyright})
If you are using class based generic views, you can simply modify your get_context_data.
class Home(TemplateView):
def get_context_data(self, *args, **kwargs):
ctx = super(TemplateView, self).get_context_data(self, *args, **kwargs)
ctx['copyright'] = self.copyright()
return ctx
def copyright(self):
return "copyright 2018"
Sorry in advance if there is an obvious answer to this, I'm still learning the ropes with Django.
I'm creating a website which has 6 pre determined subjects (not stored in DB)
english, civics, literature, language, history, bible
each subject is going to be associated with a unique color.
I've got a template for a subject.html page and a view that loads from the url appname/subject/subjectname
what I need to do is apply particular css to style the page according to the subject accessed. for example if the user goes to appname/subject/english I want the page to be "themed" to english.
I hope I've made myself clear, also I would like to know if there is a way I can add actual css code to the stylesheet and not have to change attributes one by one from the back-end.
thanks very much!
In templates you can use conditionals for add css, like this:
<div class="{% if subject=='civics' %}civic-class{% endif %}"></div>
For this, subject value should come from view.
Now, for themed page, you could use the extends tag. Let's supose:
def your_view(request):
subject # Here you get the url subject, 'how' is up to you
if subject == 'english'
template_base = '/some/html/tenplate.html'
elif subject == 'civis':
template_base = '/some/other/template.html'
... # then you return 'template_base' variable to template
Then in template:
{% extends template_base %} # at the top
Hope this helps, is the same logic if you use Class-Based views.
Django's views are not responsible for the presentation, it's the template (and css etc of course)'s reponsability. Now assuming you have the same view serving different subjects, the view obviously need to know which is the current subject (I assume from a captured part of the url passed as argument to the view), so it can easily pass this information to the template, which in turn can use it to add a subject-specific class to the body tag. Then you only have to write your css accordingly.
As an example:
# urls.py
patterns = urlpatterns('',
#...
url(r'whatever/(P?<subject>[a-z-]+>)/$', 'myviews.index', ...),
)
# myviews.py
def index(request, subject):
# do whatever
context = {
# whatever else
'subject':subject
}
return render(request, "whatever/index.html", context)
# whatever/index.html
<html>
# headers etc
<body class="something {{ subject }} etc">
# whatever here
</body>
</html>
You can do this is many ways.
In general you need to return some variable from your view to the html and depending on this variable select a style sheet, if your variable name will match you style sheet's name you can do "{{variable}}.css", if not you can use JQuery.
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
views.py
def edit_report(request, report_id):
"""Edit report navigation from action needed screen
"""
user = request.user
if 'report_id' in request.session:
del request.session['report_id']
try:
member = Members.objects.get(member=user)
account_user = member.user
except:
account_user = user.id
request.session['report_id'] = report_id
request.session['account_user'] = account_user
return redirect('incident.views.new_report')
template.html
<td class="irlist-num">{{list.report.incident_number}}{%if list.report.is_draft%} DRAFT{% endif %} </td>
Now,when a new report is created using New Report tab,that tab will be highlighted.
The above view is for editing a report.In template,if the user clicks the report name link({% url incident.views.edit_report list.report.id%}),it will takes the user to edit that particular report.Since this report is open under New Report Tab, New Report Tab is highlighted.I want to customize this to not highlight while open a report via this edit_report.
I am thinking to validate it using session in report_id,so if this report_id is in session the New report menu should not highlight,but i updated the tried code ,still it doesn't worked for me.Need help
Thanks
Without seeing the code for the new_report view, it looks like it must be loading the correct report info based on session.session['report_id']. I think rather than passing things like that around via the session, you should probably just pass it as an argument to the new_report view when you call redirect (see link for django docs on redirect). Note that you'd also have to edit your view definition doing this.
Better yet, combine edit_report and new_report into a single view, if you've got almost all of the edit functionality in edit_report already.
Anyway, back to the question being asked. You can check if the report_id is set in you session in the new_report view (I assume you're doing this already). Then based on this, you can pass a variable in a RequestContext to your template
Views.py
def new_report(request):
view_template = loader.get_template('template.html')
if 'report_id' in request.session:
highlight_new_report = True
else:
highlight_new_report = False
view_context = RequestContext(request,{
'highlight_new_report' : highlight_new_report
})
return HttpResponse(view_template.render(view_context))
Then wherever the menu is in your template (note that this could very likely be in a base template being extended by your_template.html), you can use this to decide what class to add to the tab/link. There is probably something there already adding a class to highlight it, you should be able to override this based on the highlight_new_report variable which is now available in your template
template.html (or a template template.html extends)
<!-- Menu tabs -->
<a href="/new_report"
{% if highlight_new_report %}
class="highlighted_tab">
{% endif %}
</a>
Edit for more info
Sorry should have been clearer. The above code is an example of how you can set the class based on your report_id, but I left it unspecific because I didn't know what your template would look like.
If you've used the above code to add a CSS class which removes the highlight, then you can add another class which will add a highlight:
template.html (or a template template.html extends)
<!-- Menu tabs -->
<a href="/new_report"
{% if highlight_new_report %}
class="highlighted_tab"
{% else %}
class="non_highlighted_tab">
{% endif %}
</a>
Where highlighted_tab is a class which adds a highlight, and non_highlighted_tab is one which doesn't, or which overrides a highlight styling already being applied.
The reason I didn't write the answer this way to begin with, is because you probably already had something like class="active" being added based on the current page. So I expected you to use a condition like that above, to restrict the addition of this active class to when highlight_report = True
It is possible to do using session.
By seeing this bit of code,i understand that you are creating a session for new report.But what you are trying to do is not possible to handle with the same session.
I think,for new report and edit report their are two different methods.If this is the case its easy to handle.
Let us see this,
1.You should create a session in edit report method.
2.Should validate,whether that session is in new report,if that newly created session is in new report should set new_report=False and pass to render.
3.You should delete that newly created session in new report method,if not then menu will always be not highlighted.
As per the above one,if the user clicks report from {% url incident.views.edit_report list.report.id%} or edit report menu,the newly created session gets started from edit report method and will be available.
Hope this gives you an idea.
I am creating an application to display articles. In my model, I have a TextField that will contain the content of the article.
Now I would like to be able to render another application within my article. Let say I have a poll application and I would like to display a poll in the middle of the article. How can I do that ?
I tried by putting a {% render_poll 42 %} within the post but, as expected, it just display that within the generated page.
Should I create some kind of tag (like let say [poll=42]) and parse it before displaying the rendered html page ? (I use the markdown library, maybe I could extend it.) How can I do that to stay in a nice "django friendly" way ? I want that, when in the admin panel, I can easily insert poll (or other apps) within an article.
You could compile the TextField string as a template. Ie.:
from django.db import models
from django.template import Template, Context
class YourModel(models.Model):
body = models.TextField()
def render_body(self, context=None):
template = Template(self.body)
context = context or {}
context['object'] = self
return template.render(Context(context))
Then in the actual template, you could use {{ your_model.render_body }} rather than {{ your_model.body }}.