3

In huge efforts to move from Django Templates to Jinja2 I got into some issues. Unfortunately (surprisingly) I couldn't find much information on this.

The main issue is the tags:

<a class="ui twitter button" href="{% provider_login_url "twitter" method="oauth2" next="/photos/new" %}">

Jinja2 won't recognize it:

django.template.exceptions.TemplateSyntaxError: ("Encountered unknown tag 'provider_login_url'.

There must be someone out there who has managed to make this work. Isn't there an easy way to make the template tag available for jinja2 to use? What's the generic way to make a 3rd party library to work with jinja2?

David Buck
  • 3,752
  • 35
  • 31
  • 35
Pithikos
  • 18,827
  • 15
  • 113
  • 136

2 Answers2

1

This is what I used (register as func for jinja2), not sure if it's 100% works as native tag, but I hadn`t had any issues yet.

def provider_login_url(request, provider_id, **kwargs):
    provider = providers.registry.by_id(provider_id) 
    query = kwargs
    if 'next' not in query:
       next_ = request.GET.get('next')
       if next_:
           query['next'] = next_
    else:
        if not query['next']:
           del query['next']
    return provider.get_login_url(request, **query)
Basalex
  • 1,147
  • 9
  • 20
  • this no longer works as of [django-allauth 0.55.0](https://github.com/pennersr/django-allauth/blob/fccd33f68b4c19acfa4277c97fbbf0a9226d2367/ChangeLog.rst#backwards-incompatible-changes-1) as `providers.registry.by_id` has been removed – A Lee Sep 02 '23 at 00:33
0

The general method for converting a django templatetag to a jinja function is:

  1. create a function that's equivalent to the django templatetag (e.g., provider_login_url)
  2. add the function to the jinja Environment that you configured as the jinja environment in your django settings, usually in an env.globals.update call - see https://stackoverflow.com/a/41283502/93370 for more details

The above answer from Basalex used to work great but django-allauth>=0.55.0 removed providers.registry.by_id so it won't work anymore if you upgrade django-allauth past that version.

I'm still looking for the "right" way to handle this but following django-allauth's provider_login_url implementation it seems you can do something like:

from allauth.socialaccount.adapter import get_adapter

def provider_login_url(request, provider_id, **kwargs):
    provider = get_adapter(request).get_provider(request, provider_id)
    ... # logic to clean up next, auth_params etc.
    return provider.get_login_url(request, **kwargs)

it also seems like you can look it up via the allauth.socialaccount.models.SocialApp model

from allauth.socialaccount.models import SocialApp

def provider_login_url(request, provider_id, **kwargs):
    provider = SocialApp.objects.get(provider=provider_id).get_provider(request)
    ... # logic to clean up next, auth_params etc.
    return provider.get_login_url(request, **kwargs)
A Lee
  • 7,828
  • 4
  • 35
  • 49