I have a celery task that runs periodically and fetches some data for all companies that use a certain accounting service. I now need to make that task run on-demand with a click of a button, and fetch only the current company's data.
Modified celery task:
#APP.task
def import_data_for_company(company_id):
for integration in settings.INTEGRATIONS:
if integration["owner"]["company_id"] == company_id:
print("omlette du fromage")
Current button in Django template
{% for integration in settings.INTEGRATIONS %}
{% if company.company_id == integration.owner.company_id %}
<div class="button">
<a class="btn" href="#">Import Data</a>
</div>
{% endif %}
{% endfor %}
I need to trigger that task from the Django template and pass a company ID as an argument while doing it. But according to this comment, I cannot pass arguments from the Django template. Writing a custom template tag/filter seems not to help here.
What are my options for calling that function via this button?
Have to note, that I'm very green at this still.
You should create a view that takes your company id. Within this view, you will trigger import_data_for_company. Then you can redirect back to your initial view. Or you can trigger the view with AJAX as well.
Add the URL in your template accordingly: {% url 'some_name' company.company_id %}
urls.py:
path(
"your_desired_trigger_url/<id:company_id>/",
trigger_company_data,
name="some_name",
),
views.py:
def trigger_company_data(request, company_id):
import_data_for_company(company_id)
return HttpResponseRedirect(reverse("your_initial_view"))
Related
So I want to add a extra link in the Wagtail admin. I am following the docs (Register Admin Menu Item Hook) and using this hook to contruct a new menu item.
They use this hook for adding menu items:
#hooks.register('register_admin_menu_item')
def register_edit_menu_item():
return MenuItem('Edit profile', 'edit_link', classnames='icon icon-folder-inverse', order=10000)
This should become a link which starts editing a page that is owned by the current logged in user. In a template I use this code to create a direct link to edit the profile of a user:
{% with request.user.owned_pages.all as pages %}
{% if pages.exists %}
{% for p in pages %}
{% if p.get_parent.id == 17 %}
<a class="list-group-item" href="/dashboard/pages/{{ p.id }}/edit/"><i class="fe-icon-edit mr-1 text-muted"></i>Edit profile</a>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
This is working just fine, it links directly to the page that it is supposed to link to. However how do I implement a condition like this where I generate the menu link based on the current logged in user?
I would think something like:
if request.user.owned_pages.exists():
for p in request.user.owned_pages.all():
if p.get_parent.id == 17:
edit_link = "/dashboard/pages/" + p.id + "/edit/"
But how can I implement something like this into the Wagtail menu hook?
The default implementation of MenuItem assumes that the URL will be constant over all page requests, meaning that we can pass that fixed URL to the MenuItem constructor inside the register_admin_menu_item hook (that runs on server startup).
In your case, this isn't true, so you'll need to define a custom subclass of MenuItem. If you look at the code for MenuItem, you'll see that it implements a get_context(self, request) method to gather all the template variables it needs to render the menu item, including url. You can override this method to set a dynamic URL in place of the fixed one:
class EditProfileMenuItem(MenuItem):
def get_context(self, request):
context = super().get_context(request)
edit_link = None
if request.user.owned_pages.exists():
for p in request.user.owned_pages.all():
if p.get_parent().id == 17:
edit_link = "/dashboard/pages/" + p.id + "/edit/"
if edit_link:
context['url'] = edit_link
return context
You can then use this subclass in the register_admin_menu_item hook, in place of MenuItem:
#hooks.register('register_admin_menu_item')
def register_edit_menu_item():
return EditProfileMenuItem('Edit profile', 'edit_link', classnames='icon icon-folder-inverse', order=10000)
(Depending on your requirements you may want to override the is_shown method too, so that the menu item is hidden from those users who don't have a profile.)
For example I have the following situation where a delete button has to be routed different depending upon who has clicked it, like if he's an admin display a message else go to the delete view. I thought I will place the function to send a message in detail generic view but how to call that function directly from template?
{% if user_detail.status == ADMIN %}
<button class="btn clearfix"><i class="icon-trash"></i>Cannot Delete Admin</button>
{% else %}
<i class="icon-trash"></i>Delete User
{% endif %}
The delete generic view is directly linked to the template, is there to display message in detail view itself before redirecting to the template?
There are many solutions to do this, one is to check for staff-status in the View, using one of the multiple mixins already made for this or check if hes a admin some other way and then either return an error message or redirect to one i.e
def myview(request):
if not request.user.is_staff:
return HttpResponseRedirect(..errormessage-url or view..)
.. do stuff here for admin users..
Django-Bootstrap-Calendar (https://github.com/sandlbn/django-bootstrap-calendar) is a Django implementation of this calendar application: http://bootstrap-calendar.azurewebsites.net/
However, I can't figure out how to add events to the calendar via Django. The "non-Django" bootstrap calendar is rather simple, you just add events to the JSON file that gets loaded.
Has anyone here added events to Django-Bootstrap-Calendar before? I emailed the author of the project, however, he never responded to me.
The closest post I found to my question is here: Getting a bootstrap-calendar component to work with Django However, the author figured out how to add entries to the non-Django calendar only.
Edit: I figured out how to add events via the Admin panel.
In models.py, you simply add:
###Admin
class CalendarEventAdmin(admin.ModelAdmin):
list_display = ["title", "url", "css_class", "start", "end"]
list_filler = ["title"]
admin.site.register(CalendarEvent,CalendarEventAdmin)
Then, in the admin panel you can add events (ultimately, I want non-admin users and anonymous visitors to be able to register events on the Calendar.)
However, this reveals a larger problem: the calendar doesn't display.
Edit 2: I have the calendar loading now by adding
{% load bootstrap_calendar %}
{% bootstrap_calendar_css %}
{% bootstrap_calendar_js language="template" %}
{% bootstrap_calendar_init language="template" %}
<!-- {% bootstrap_controls 'optional-css-classes' %} -->
{% bootstrap_calendar 'optional-css-classes' %}
to my index.html file. However, the calendar doesn't display the event(s) created with the Admin Panel.
Simply put
{% bootstrap_calendar_init language="template" %}
after
{% bootstrap_calendar 'optional-css-classes' %}
I need to show different button in my template based on user's log in. The scenario is my template show follow button:
Check whether the user logged in or not-
if user logged in-
check which channel he follwed:
if he followed any channel
beside that channel name show "followed" button
else
show "follow" button with the path follow_save
elif user not logged in:
show follow button with the path follow_save
I am stuck how to do that? Is this a task for views or for template? how to do that? Any help from you experts will save me..Also I have wanted to take the user_id from session.
Here is my views.py
e= EventArchiveGallery.objects.all()
user = request.session['user_id']
if user:
j = EventArchiveGallery()
joining_list = j.joiningList(user)
return render_to_response('gallery/allevents.html',
{
'joining_list':joining_list,
},
context_instance=RequestContext(request)
)
This is my templates:
{% for event in live %}
<p>Event Title:{{event.event_title}}<p/>
<p>Channel Name:{{event.channel_id.channel_title}}</p>
<p>Event Description{{event.event_description}}</p>
{% if event in joining_list %}
<p>followed</p>
{%else%}
<p>follow</p> #I have wanted to show follow_save function call from this button,when user clicked
{endif%}
{% endfor %}
You are asking 2 questions better if you can split in 2 questions, anyway ...
show different button in my template based on user's log in
Better way would be identify what to show in view and pass context parameter to template. Depending upon this variable template will render different HTML.
example template : Assumes view passes followed_channel parameter.
{% if user.is_authenticated %}
{%if followed_channel %}
{# render html you want #}
{%else%}
{# render another way #}
{%endif%}
{%endif%}
Also I have wanted to take the user_id from session
Before you get from session, you have to store it. So you can update your view as
e= EventArchiveGallery.objects.all()
user = request.session.get('user_id')
if not user:
request.session['user_id'] = request.user.id
if user:
j = EventArchiveGallery()
joining_list = j.joiningList(user)
return render_to_response('gallery/allevents.html',
{
'joining_list':joining_list,
},
context_instance=RequestContext(request)
)
I want to display a menu that changes according to the user group of the currently logged in user, with this logic being inside of my view, and then set a variable to check in the template to determine which menu items to show....I'd asked this question before, but my logic was being done in the template. So now I want it in my view...The menu looks as below
<ul class="sidemenu">
<li>General List </li>
<li>Sales List </li>
<li>Add a New Record </li>
<li>Edit Existing Record </li>
<li>Filter Records </li>
<li>Logout </li>
</ul>
Suppossing the user is management, they'll see everything...But assuming the user is in the group sales, they'll only see the first two and the last two items...and so on. I also want a dynamic redirect after login based on the user's group. Any ideas?
The standard Django way of checking permissions is by the individual permission flags rather than testing for the group name.
If you must check group names, being aware that Users to Groups is a many-to-many relationship, you can get the first group in the list of groups in your template with something like this:
{{ user.groups.all.0 }}
or using it like this in a conditional (untested but should work):
{% ifequal user.groups.all.0 'Sales' %}
...
{% endif %}
If you go with the preferred permission model you would do something like the following.
...
{% if perms.vehicle.can_add_vehicle %}
<li>Add a New Record </li>
{% endif %}
{% if perms.vehicle.can_change_vehicle %}
<li>Edit Existing Record </li>
{% endif %}
...
These are the permissions automatically created for you by syncdb assuming your app is called vehicle and the model is called Vehicle.
If the user is a superuser they automatically have all permissions.
If the user is in a Sales group they won't have those vehicle permissions (unless you've added those to the group of course).
If the user is in a Management group they can have those permissions, but you need to add them to the group in the Django admin site.
For your other question, redirect on login based on user group: Users to Groups is a many-to-many relationship so it's not really a good idea to use it like a one-to-many.
user.groups.all.0.name == "groupname"
Create a user_tags.py in your app/templatetags follow above:
# -*- coding:utf-8 -*-
from __future__ import unicode_literals
# Stdlib imports
# Core Django imports
from django import template
# Third-party app imports
# Realative imports of the 'app-name' package
register = template.Library()
#register.filter('has_group')
def has_group(user, group_name):
"""
Verifica se este usuário pertence a um grupo
"""
groups = user.groups.all().values_list('name', flat=True)
return True if group_name in groups else False
And finally in template use it:
{% if request.user|has_group:"Administradores"%}
<div> Admins can see everything </div>
{% endif %}
If you are working with Custom User Model (best practice with Django), you can create a method:
CustomUser(AbstractUser):
# Your user stuff
def is_manager(self):
return self.groups.filter(name='Management').exists()
Then inside your template you just call it this way:
{% if user.is_manager %}
{# Do your thing #}
{% endif %}
That method will be also useful validating permission in other parts of your code (views, etc.)