Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template tags do not accept variable as argument #149

Open
adrien-delhorme opened this issue Apr 2, 2012 · 3 comments
Open

Template tags do not accept variable as argument #149

adrien-delhorme opened this issue Apr 2, 2012 · 3 comments

Comments

@adrien-delhorme
Copy link

For example, when I pass STATIC_URL to the facebook_button tag:

{% facebook_button STATIC_URL %}

the HTML output is:

<input type="image" onclick="this.form.submit();" src="TATIC_UR" />

To make it work, I changed the line 11 into socialregistration/templatetags/__init__.py by:

return ButtonTag(template, parser.compile_filter(bits[1]))

and the line 27 by:

return template.loader.render_to_string(self.template, {'button': self.button.resolve(context)}, context)

But this patch does not work for openID button.

So here is my full patch for socialregistration/templatetags/__init__.py:

from django import template
from django.utils.translation import ugettext_lazy as _

register = template.Library()

def button(template):
    def tag(parser, token):
        bits = token.split_contents()
        try:
            # Is a provider and a custom button passed in?
            return ButtonTag(template, parser.compile_filter(bits[2]), parser.compile_filter(bits[1]))
        except IndexError:
            try:
                # Is a custom button passed in?
                return ButtonTag(template, parser.compile_filter(bits[1]))
            except IndexError:
                # No custom button
                return ButtonTag(template)
    return tag

class ButtonTag(template.Node):
    def __init__(self, template, button = None, provider=None):
        self.template = template
        self.button = button
        self.provider = provider

    def render(self, context):
        if not 'request' in context:
            raise AttributeError(_("Please add 'django.core.context_processors.request' "
                "'to your settings.TEMPLATE_CONTEXT_PROCESSORS'"))

        dict = {'button': self.button.resolve(context)}
        if self.provider:
            dict.update(provider=self.provider.resolve(context))

        return template.loader.render_to_string(self.template, dict, context)

and socialregistration/contrib/openid/templatetags/openid.py is just like facebook.py:

from django import template

from socialregistration.templatetags import button

register = template.Library()

register.tag('openid_form', button('socialregistration/openid/form.html'))
@flashingpumpkin
Copy link
Owner

Hi

I'll have a look as soon as possible

Cheers

@zalmoxis
Copy link
Contributor

I did not notice this issue and implemented my own version. I actually needed to mix context variables with strings like:
{% facebook_button STATIC_URL "images/tiny_facebook.png" %}

The implementation should be able to handle an arbitrary number of variables and strings. I did not add any tests, but the current facebook tests were passing. Could someone also chime in on how I could run all tests? The tests.py classes inherit from object and not TestCase. Sorry for the noob question. I didn't find info on running the tests in the documentation.

Here it is:

from django import template
from django.utils.translation import ugettext_lazy as _

register = template.Library()

def button(template_name):
    def tag(parser, token):
        bits = token.split_contents()
        if len(bits) > 1:
            return ButtonTag(template_name, *bits[1:])
        else:
            # No custom button
            return ButtonTag(template_name)
    return tag

class ButtonTag(template.Node):
    def __init__(self, template_name, *input):
        self.template = template_name
        self.input = input

    def render(self, context):
        output = []
        for bit in self.input:
            if not (bit[0] == bit[-1] and bit[0] in ('"', "'")):
                output.append(template.Variable(bit).resolve(context))
            else:
                output.append(bit[1:-1])
        self.button = ''.join(output)

        if not 'request' in context:
            raise AttributeError(_("Please add 'django.core.context_processors.request' "
                "'to your settings.TEMPLATE_CONTEXT_PROCESSORS'"))

        return template.loader.render_to_string(self.template, {'button': self.button, 'next': context.get('next', None)}, context)

You can pull from: https://bitbucket.org/dori/django-socialregistration/
Sorry about the bitbucket/mercurial ....

@zalmoxis
Copy link
Contributor

I have modified the openid_form tag to be able to work the same way:

def openid_form(context, provider=None, *params):
    button = ''.join(params)
    return {
        'provider': provider,
        'button': button,
        'request': context['request']
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants