django activate link/button if the path startes with `<path>` - django

I'm building a Django app and I have a link on my navbar that I want to activate it(means add a css class) if the path starts with <base_url>/accounts/
I tried the following and it doesn't work
{% url 'accounts:profile' as pro %}
{% url 'accounts:setting' as set %}
{% url 'accounts:anotherpage' as ano %}
This doesn't work
{% if request.path == pro or request.path == set or request.path == ano %} active {% endif %}

This should solve your ask:
{% if pro in request.path or set in request.path or ano in request.path %} active {% endif %}
but if you want
I want to activate it if the path starts with <base_url>/accounts/
in this case:
{% if '/accounts/' in request.path %} active {% endif %}

Related

How to apply multiple if condition filter in djago template

I am rendering two filter from my views to html template. 1) notifications_approved 2)notifications_pending. I am using this two filter separately in my html. Is there any way to use this two filter together in if statement? here is my code:
#html template
{% for notification in notifications_approved %}
{% endif %}
{% for notification in notifications_pending %}
{%endif%}
I tried this but it's not rendering anything's in my template:
{%if notification in notifications_approved or notifications_pending %}
{%endif%}
I also tried this
{%if notification|notifications_approved or notification|notifications_pending %}
{%endif%} #getting TemplateSyntaxError
I also surprised very much why this if statement not working:
{% if notification in notifications_approved %}
{% endif %}
views.py
def ShowAuthorNOtifications(request):
notifications_approved = Notifications.objects.filter(notification_type="Comment Approved").order_by('-date')
notifications_pending = Notifications.objects.filter(notification_type="New Comment").order_by('-date')
{% if notification in notifications_approved %}
{% endif %}
If statement not working because we are not comparing anything. notifications_approved is a query set which contains list of objects. You need to loop it first. Secondly, if you need to check if the query set is empty or not, use:
{% with notifications_approved as np %}
{% if np %}
# your code
{% endif %}
{% endwith %}
OR
{% if notifications_approved or notifications_pending %}
OR
{% if notifications_approved.exists or notifications_pending.exists %}
OR
{% if notifications_approved.all or notifications_pending.all %}
You can use empty tag as well to check if empty:
{% for na in notifications_approved %}
# code
{% empty %}
# code for empty query set
{% endfor %}

Get the user context in all views django?

Im using a template syntax to set the permissions for the topbar of the application like so
Top bar permision
{% if user.is_authenticated %}
# Top bar html code
{% endif %}
but the problem is that when a user i authenticated they can accress the profile picture and name of another user if they have the correct url:uuid link.
I managed to get this fixed by putting this syntax in the template
{% if object == request.user %}
{% if object.pk %}
{% endif %}
{% endif %}
This fixed the issue on the pages where the request.user can be accressed from the profile view. How can i accress the request.user in all the views at once?
Solved the problem i moved the templates tags to this order
{% if user.is_authenticated %}
{% if user == request.user %}
{% if user.pk %} {% endif %}
{% endif %}
{% endif %}

How to display django-treebeard MP in template as dropdown menu?

Following the treebeard docs api example, I created an annotated_list of my tree using get_annotated_list(parent=None, max_depth=None) with parent=<my root node>. I pass this to my template and using the example they attribute in the docs to Alexey Kinyov, I am able to successfully display my tree using
{% for item, info in annotated_list %}
{% if info.open %}
<ul><li>
{% else %}
</li><li>
{% endif %}
{{ item }}
{% for close in info.close %}
</li></ul>
{% endfor %}
{% endfor %}
What I would like though is to be able to give these nested lists dropdown features. Borrowing from this standard example on w3schools, I modified it to work with my annotated_list template variable and ended up with this:
<ul id="myUL">
<li><span class="caret">{{ annotated_list.0.0 }}</span>
{% for item, info in annotated_list|slice:"1:" %}
{% if info.open %}
<ul class="nested"><li>
{% else %}
</li><li>{% if item.get_children_count > 0 %}<span class="caret">
{% endif %}
{% endif %}
{{ item }}
{% if item.get_children_count > 0 %}</span>
{% endif %}
{% for close in info.close %}
</li></ul>
{% endfor %}
{% endfor %}
</li>
</ul>
My code almost works, but does not seem to display node children for left-most nodes and I can't figure out why.
Note: CSS & JS not included in question but needed to make the dropdown menu work (I'm just using the out-of-the-box CSS/JS used in that w3schools example)
The most likely reason is that there is a problem with the tree.
Run Model.find_problems() to confirm.
Model.fix_tree() can fix most of the common problems.
Note that the get_annotated_list_qs() function doesn't really work at all.
You can try this Code:
<ul id="myUL">
{% for item, info in annotated_list %}
{% if item.get_children_count > 0 %}
<li><span class="box">{{item}}</span><ul class="nested">
{% else %}
<li>{{item}}</li>
{% endif %}
{% for close in info.close %}
</ul>
{% endfor %}
{% endfor %}
</ul>
It worked for me.
To add some missing context:
views.py:
def tree(request):
annotated_list = Category.get_annotated_list()
# template_name = 'JsonDefine/tree.html'
context = {
'annotated_list': annotated_list
}
return render(request, 'JsonDefine/tree3.html',context)
urls.py
from django.urls import path
from . import views
app_name = 'MyApp'
urlpatterns = [
path('tree/', views.tree, name='tree'),
]

Overriding django admin pagination along with url parameters

I would like to implement custom pagination for my admin panel.
My url looks like the following:
http://localhost:8000/admin/items/?group_id=20
On this URL I do some work to filter the results using the parameter group_id (by overriding get_changelist method).
The page results are corrects, the problem is my pagination ending up like this http://localhost:8000/admin/items/?p=1 whereas I would like the URL to be http://localhost:8000/admin/items/?group_id=20&p=1 and keep the parameter.
Basically I want the same result as How to paginate Django with other get variables? but using Django admin.
How can I keep the parameter along with the pagination?
I've tried overriding pagination.html file but without any success.
Thank you.
Edit
I've tried overriding pagination.html but request.GET.items is still empty (even if my settings file is well configured)
{% load admin_list %}
{% load i18n %}
{% load content_extras %}
<p class="paginator">
{% if pagination_required %}
{% for i in page_range %}
{{ i }}
{% endfor %}
{% endif %}
{{ cl.result_count }} {% if cl.result_count == 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endif %}
{% if show_all_url %}{% trans 'Show all' %}{% endif %}
{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}">{% endif %}
</p>
FOUND A SOLUTION:
1/ Override changelist_view on admin.py and pass the extra data
def changelist_view(self, request, extra_context=""):
response = super(ItemAdmin, self).changelist_view(request, extra_context)
group_id = request.GET.get('group_id', None)
if group_id:
extra_context = {
'group_id': group_id,
}
response.context_data.update(extra_context)
return TemplateResponse(request, "admin/changelist.html", response.context_data)
2/ Create changelist.html file based on django admin template (copy/paste)
Add {% load content_extras %} at the top of the file (line 3)
Change line {% block pagination %}{% pagination cl %}{% endblock %} with {% block pagination %}{% custom_pagination cl %}{% endblock %}
3/ Create content_extras.py under templatetags folder and write custom_pagination function
from django import template
from django.contrib.admin.templatetags import admin_list
register = template.Library()
#register.inclusion_tag('admin/pagination.html', takes_context=True)
def custom_pagination(context, cl):
pagination = admin_list.pagination(cl)
if 'group_id' in context:
params = (('group_id', context['group_id']),)
pagination['params'] = params
return pagination
4/ Create pagination.html (same location as changelist.html)
{% load admin_list %}
{% load i18n %}
{% load content_extras %}
<p class="paginator">
{% if pagination_required %}
{% for i in page_range %}
{{ i }}
{% endfor %}
{% endif %}
{{ cl.result_count }} {% if cl.result_count == 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endif %}
{% if show_all_url %}{% trans 'Show all' %}{% endif %}
{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}">{% endif %}
</p>
If you activated django.template.context_processors.request in your settings, you can access parameters from your request directly from your template.
And then you can access the parameters in your templates directly. Something like:
href="?page={{ data.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}"
Research (context_processors.request was moved from django.core to django.templates some time ago)

django template tag check if image exists

I've got a portion of my app that allows a custom logo.
Default object (and object view) state is no custom logo, but if one exists, replace the header with a custom logo navbar.
logo is a standard ImageField on co(mpany) model:
models.py:
class Co(models.Model):
logo = models.ImageField(blank=True)
template:
{% if co.logo %}
{% block navbar %}
{% include 'templates/navbar_logo.html' %}
{% endblock %}
{% endif %}
I've also tried this with {% if co.logo == None %}, {% if not ... %}, {% if co.logo.url %} and trying to model the logic with co.logo|default_if_none:"" but in instances where a logo isn't set the view throws:
ValueError at /co/foo
The 'logo' attribute has no file associated with it.
for... empty also doesn't work
{% for co.logo.url in co %}
...
{% empty %}
...
{% endfor %}
in django shell:
(with logo)
c.logo >> <ImageFieldFile: logo.png>
c.logo.url >> '/media/logo.png'
(no logo)
b.logo >> <ImageFieldFile: None>
is there a built in django template tag filter that will allow this condition to pass True only if the field has an image uploaded? otherwise don't load the nav block? thanks
I solved this by re-ordering the tags:
{% block navbar %}
{% if co.logo %}
{% include 'templates/navbar_logo.html' %}
{% else %}
{% include 'templates/navbar.html' %}
{% endif %}
{% endblock %}
Try Use 'is not null'
{% if co.logo.url is not null %}
{% block navbar %}
{% include 'templates/navbar_logo.html' %}
{% endblock %}
{% endif %}