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.
Related
Using Django I want to implement some middleware that will calculate some context that is to be used by the view itself.
For example, I have a middleware that looks at the request, and adds the user's permissions to the request, or some user configuration. The view looks at these permissions and decides how to handle the request using it.
This saves the need for multiple views (and multiple parts within the view) to query for this information.
I'm wondering what is the correct way to do that. One option is to just add request.user_permissions=... directly on the request. But is there some documented and expected way to do that?
There's no real documented way to do that, but Middleware is the correct place to do it and just adding properties to the request object is also the correct way.
You can confirm this, because Django is already doing it:
LocaleMiddelware
AuthenticationMiddleware
RemoteUserMiddleware
CurrentSiteMiddleware
SessionMiddleware
So just pick whatever is the most convenient data structure for your use case and tack that on to the request object.
This is not a perfect answer but at my experience I use this code. Every permission is saved in a boolean value which is true or false. You can access it in a html template like.
{% if request.user.is_admin %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
and to send extra context you should create and pass an dicionary and pass it as as an argument to the render method from the view.
For eg:
def view(request, slug):
context = {'administrator':True}
blog_post = get_object_or_404(BlogPost, slug=slug)
context['blog_post'] = blog_post
return render(request, 'blog/detail_blog.html', context)
and access it like
{% if context.administrator %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
I believe, since your middleware will calculate context, it should be implemented as context processor.
https://docs.djangoproject.com/en/3.1/ref/templates/api/#using-requestcontext
https://docs.djangoproject.com/en/3.1/ref/templates/api/#writing-your-own-context-processors
I was wondering how might I show a new user a message such as 'First time here?' in a Django template using conditionals?
e.g.
{% if this_website_has_not_been_accessed_by_user %}
<h3>First time here?</h3>
<h5>Follow these steps...</h5>
{% endif %}
What might be the best way to do this? Thanks
Assuming you only want to show that banner at the top of the page for logged in users (those that have a User instance in the current request), you could create a Model (or, if you have your own user profile model, add a field to it) to save that.
class Access(models.Model):
user = models.ForeignKey(User)
has_been_here_before = models.BooleanField(default=False)
In your view you would have to check that Model to see if the user is registered there and has the flag set.
See this post for detecting first login.
See also this similar post for detecting a visit to each individual page or view.
EDIT: according to your comments you want to show the welcome banner to anonymous users (not logged in) if they visit for the first time.
You could achieve that using djangos session framework. You can use request.session just like a simple dict.
In your home page view (or through a custom middleware so it affects all pages not just the home page) you could check if a user has already dismissed the welcome banner or not.
def my_home_view(request):
...
# as default 'show_welcome_banner' will be True
context['show_welcome_banner'] = request.session.get('show_welcome_banner', True)
...
Then, in your template use:
{% if show_welcome_banner %}
<h3>First time here?</h3>
<h5>Follow these steps...</h5>
{% endif %}
Your banner could have a 'dismiss' button that posts a hidden to a different url (maybe even through ajax). This url would alter the users session info:
def dismiss_welcome_banner(request):
...
if request.method == 'POST':
request.session['show_welcome_banner'] = False
...
Notes:
if a user access the site through incognito mode (the session cockie gets deleted when he closes the browser) he will need to click the dismiss button every time he opens the incognito browser.
You could additionally check that loggen in users do not get to see that banner, depending of how you prefer it.
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 %}
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 using django 1.6.0. I am working on a web app with a client "dashboard". In the client dashboard there are tabs in the header of the base template. The tabs are dynamic and change based on the role/permissions of the user viewing the dashboard.
All the views are written using class based views. All of the dashboard views inherit from a parent mixin view that makes sure the logged in user has permission to view the objects that they requested to view, and that builds the dashboard tabs based on their user role.
class ParentMixin(object):
pages = OrderedDict([
('General': { 'link': build_a_link_for_the_logged_in_user()}),
])
def dispatch(self, *args, **kwargs):
# validate that logged in user has permission to view requested objects
if user_passes_test(self.request.user):
self.object = get_users_object_to_view(self.request.user)
def get_context_data(self, **kwargs):
if self.request.is_superuser and self.object.is_demo:
self.pages['Superuser'] = {'link': build_link()}
context = super(parent_get_context_data)
context['pages'] = self.pages
Then in base template that all dashboard views inherit from, the dynamic tabs/links are displayed:
{% for page_name, page_data in pages.items %}
{% if page_data.is_current %}
<a href="{{ page_data.link }}" class="current">
{% else %}
<a href="{{ page_data.link }}">
{% endif %}
{{ page_name }}
</a>
{% endfor %}
My Question:
This morning, i noticed if I had a requested a demo object, then clicked on a link to view a different objects dashboard, the last objects Superuser Link would still show up in the pages dictionary!!!! I put in debug statements in the view. The view would recognize that I was a superuser and the object.is_demo was False. So the conditionaly would not add the Superuser link to the self.pages. But the Superuser link was still in self.pages and it had the Link from the last object I viewed. This is the only place that self.pages['Superuser'] was being set.
Does anyone know how this data could persist between requests? Or could see something wrong with my approach??
I fixed the bug this morning by removing the Superuser from self.pages before doing the conditional check to see if a superuser was making the request and the object was a demo:
if 'Superuser' in self.pages:
del(self.pages['Superuser'])
Thank you,
This is doing exactly what you tell it. You've set pages to be a class attribute of ParentMixin, which means it will also be a class attribute of any view class you mix it in to. Class attributes are shared across all instances of the class within a process, and since a process lasts across many requests, the data will persist across those requests.
You should always set attributes on self, which means doing it inside a method, in this case probably inside get_context_data. Django goes to some lengths to ensure that instance data is not shared in class-based views, but this does not apply to class-level data.