2

Is there a way to get around python appending an "L" to Ints short of casting every time they come out of the database? (Note: I'm using Mysql)

OR, is there a way to ignore the L in django templates? (I keep getting invalid formatting errors because of this, but I'd rather not do list comprehension/casting EVERY time)

e.g. I have a dict with the object's pk as the key and I get the following in firebug:

invalid property id alert({183L: <Vote: colleen: 1 on Which best describes your wardrobe on any g...

Model: Question object, other attributes don't matter because the attribute in question is the pk

View: I didn't write the code and I can't follow it too well, so I can't post the section where the variable is being created, but it is a dict with Question pks as keys and Vote objects as values (code in question is from http://code.google.com/p/django-voting/wiki/RedditStyleVoting)

Template: {% votes_by_user user on questions as vote_dict %} to produce the dict in question alert({{vote_dict}}); is triggering the error

While in this particular case I'm just trying to alert the dict I got back, this has been a recurring problem for me when passing dicts or arrays into js functions where the function call fails because of the L. (Just to give you motivation behind the question)

Colleen
  • 23,899
  • 12
  • 45
  • 75
  • 4
    I'm confused. Django literally prints the "L" in the template? The `L` is just like `u` for unicode strings. It's not part of the actual number, just a type-signal for Python internally. – Chris Pratt Feb 22 '12 at 22:42
  • I know it's supposed to just be a signal, but yes, Django literally prints the L just like it literally prints the u. – Colleen Feb 22 '12 at 23:03
  • How is defined in the integer in your model and how do you use it in the template? The issue is that django uses `__repr__` method instead of `__str__` method, but you can probably fix that oveloading `__unicode__` method in your model. – jcollado Feb 22 '12 at 23:07
  • Are you sure your variable is actually a long, and not a string? Say you have a model instance called `instance`, calling `{{ instance.pk }}` in a template will not cause any `L` to be printed. – Thomas Orozco Feb 22 '12 at 23:08
  • Yes, the variable is actually a long. It is, in fact, the pk of the instance. For some reason, if you, say, construct a dict in your view with the pk without casting to an int, it will print the pk with an L (i.e. this issue only seems to arise when I'm passing a var from the view, not accessing properties in the template). In the model, I'm assuming pks are defined as Ints, or BigInts? I'd rather not override __unicode__ just to get a reasonable representation of a pk for a model. – Colleen Feb 22 '12 at 23:13
  • Well I guess you can always use the `stringformat` template filter `{{ value|stringformat:"s" }}` should be OK as `4L.__str__() == '4'` – Thomas Orozco Feb 22 '12 at 23:24
  • nope :( I've got a dict and just tried {{dict|stringformat:"s"}} and firebug says:invalid property id alert({183L: <Vote: colleen: 1 on Which best describes your wardrobe on any g... – Colleen Feb 22 '12 at 23:31
  • 2
    You're going to have to post the relevant model, view and template code at some point I think. – Thomas Orozco Feb 22 '12 at 23:32
  • What backend are you using? I just tested this with sqlite and the ``pk`` field is of type ``int`` and it comes out into the template as expected. – jterrace Feb 22 '12 at 23:44
  • I'm using mysql (I put mysql as a tag, but didn't explicitly state, sorry!) – Colleen Feb 22 '12 at 23:48

2 Answers2

1

There's nothing wrong with Django here. However, it's going to be difficult to provide you with a relevant solution as we don't really know what you're trying to achieve.

Anyway, calling {{ vote_dict }} will call said dict's __str__ method, which is the common {key_repr:value_repr} pattern.

If you were to do the following:

{% for key, value in vote_dict.items %}
    {{ key }} : {{ value }}
{% endfor %}

You'd get what you expect, without the L's.

On a sidenote, alert({{vote_dict}}) will almost always raise a JS error: alert's parameter is supposed to be a string.

Regarding Django - JS interoperability

If what you're trying to achieve is to pass Django items into JS funcitons seamlessly (which could indeed be possible with list instances), you could define a template filter that would return what you need.

For a list (or any kind of iterable that you'd want to represent as a list), you could use the following:

def js_list(iterable):
    return '[%s]' % ', '.join(str(item) for item in iterable)
Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • in this particular case, I'm not really trying to achieve anything beyond alerting to see what I have, although you make a good point about alert that I just sort of forgot about. However, this is a problem I've had over and over, generally related to passing dicts into js functions and having the function call fail because of it. In which case, your solution won't really work for me. – Colleen Feb 22 '12 at 23:51
  • If you just want to see what you have, simply call `alert('{{ vote_dict }}')` then. – Thomas Orozco Feb 22 '12 at 23:53
  • Indeed, but that's probably because your problem itself isn't really defined from an external viewer. On a sidenote, you don't need to get offensive. – Thomas Orozco Feb 22 '12 at 23:55
  • I realize I didn't define it well. Hopefully the edits I've made help? How am I getting offensive? – Colleen Feb 22 '12 at 23:58
  • so what it comes down to is that there's nothing built into django that would let me format querysets or template vars properly? Bummer. – Colleen Feb 23 '12 at 00:11
  • The invalid property id is certainly a Javascript error caused by the fact that the alert parameter was not a string. After you put the wrapping '' as Thomas suggested the error remains the same? Could you repost the output? – Xbito Feb 23 '12 at 00:47
0

Sounds like the meat of the problem here is that you want control over how the Django template language formats numbers before putting them into a HTTP response.

I would recommend using django.contrib.humanize, which provides template filters for this purpose.

See this question: Format numbers in django templates .

EDIT:

Realized that you are talking about iterables here. So a solution using the humanize filters would require you to loop through the iterable with a {% for %} {% endfor %} . Probably better to do it in the view as suggested in the first answer.

Community
  • 1
  • 1
foobarbecue
  • 6,780
  • 4
  • 28
  • 54