Django regroup tag problem - django

I have a custom filter user_tz which takes user as an argument. It works fine everywhere, but when I tried to use this filter in the regroup tag it fails saying that user does not exist.
The code:
{% regroup proj_messages.object_list by created_on|user_tz:user as proj_message_list %}
This is the error I am getting:
Caught an exception while rendering: Failed lookup for key [user] in u"Today's tasks".
Thanks,
Masood Ahmed

Strangely even I came across this exactissue.
Though later I had to change my code, i couldn't get on its solution. Apparently what happens is something like as follows.
Whatever you write in templates, is splitted as Nodes, Variables etc. Variables, at time of rendering is searched in context available to that instance. And please note that, for regroup tags, the context available, is just that object_list, which you passed as first argument. Not the usual context(which contains 'user' in your case), which is global to whole template. So, it is unable to find any other variable you specified, which is not in you object_list.
Thus, in your case, the context available to regroup is an object from proj_messages.object_list. And so the resolver code is able to find variable created_on in context, but not user. And that is what throwing the template exception here.
Considering this just imagine, what would happen, if your object_list too, have had the user attribute. In that case there wont be any KeyError, but user passed to the filter, would be not at all the user variable you intended to pass.
Edit on request:
There is not direct way, to pass the user to the such use of filter in regroup tag. But a kind of hack will obviously work. Note, its just a hack. Make each individual entity/object of proj_messages.object_list to contain that user variable from view or using an extra filter on object_list from template.
But better than that, if you want user to be available anywhere, from outside the context, i would like you to consider yet another hack. Check out, http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser .

Related

How to store a dynamic site-wide variable

I have an html file which is the base,where other html documents extends.Its a static page but i want to have variable in the menu.I don't think it's wise to create a view for it,since i don't intend to let users visit the base alone.So where in my project can I store site-wide dynamic variables that can be called on any page without explicitly stating them in their views.
Thank you in advance.
For user specific variables, use session.
For global constants (not variables!), use settings.py.
For global variables, consider to store it in database so it can be multithreading & multiprocess safe.
I looked around and saw different approaches,but one that doesn't compromise the DRY philosophy the most for me is registering a tag in your project then input it in the base template.Its neater See here https://stackoverflow.com/a/21062774/6629594 for an example
Storage can take any number of places, I put mine in a stats model in the db so you get all the goodness of that (and make it easy to access in views).
I then have a context processor written as so:
#context_processors.py:
def my_custom_context_processor(request):
return {'custom_context_variable1':'foo','custom_context_variable2':'bar'}
Add this to your context processors in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"my_app.context_processors.ny_custom_context_processor",
)
Provided you use render() to render your templates you can then you can just use:
{{ custom_context_variable1 }}
to return 'foo' in your template. Obviously returning strings is for example only, you can use anything you like so long as your context processor returns a dict.
you can also try using php pages.
Then acces the variable on each page with an include 'file containing the var.php' on every page.
None of this will be visible in the source html as it is only processed on the server side.
If you you would like to try this, mail me and I will send you some sample code.

Django object_name rendering in template

I've seen a SO post on this but can't seem to find it.
My results are rendering in my template with the object_name as
{'sessions__sum': 29649}
instead of just
29649.
How can I show just the sum? Thank you.
Update
I realize, out of lack of knowledge, I may not have asked my question correctly, so below is my view and a screenshot of my template, rendered in the browser. Hopefully this will help clear things up.
view
year_weekly_filter.filter(created__week_day=1).aggregate(Sum('sessions'))
monday2014 = year_weekly_filter.filter(created__week_day=2).aggregate(Sum('sessions'))
Template
{{ monday2014 }}
ScreenShot - how its rendering in the browser
You should note that: "aggregate() is a terminal clause for a QuerySet that, when invoked, returns a dictionary of name-value pairs." - Django Docs
If you just want a single value to be returned to a variable and not a dict, use .get like so:
monday2014 = year_weekly_filter.filter(created__week_day=2).aggregate(Sum('sessions')).get('sessions__sum',0)
Do you mean the {{object}} in the template is rendered by the dictionary object?
In this case, the key is accessed in this way.
{{object.sessions__sum}}
and you may get help in this and the related documentation is here.
I don't have enough points to add a comment, so I leave my guess here.

Django Template Message Resolution

I'm new to Django and I want to know the best practice for resolving messages from data in django templates.
My model has various tokens in it that need to be replaced with user-friendly messages.
like:
MyModelObject.MyProperty = 'FOO'
becasue that's what's stored in the db, but in the template, I can't just output
{{ MyModelObject.MyProperty }}
which is 'FOO'. I may want to output something like "This value is Foo." Or any string for which 'FOO' would be a key.
Is there a way to declare a dictionary in a template, or another supported framework construct?
I'd rather not code a long list of conditionals.
create a dictionary in your view that maps internal return values to user-friendly messages. pass this dict to your template. Alternatively you may want to investigate the django messaging framework - https://docs.djangoproject.com/en/dev/ref/contrib/messages/

How can I call a filter with more than one argument?

I need to call a filter with more than one argument.
If a filter takes only one parameter, for example "cut", we can call it with
{{ somevariable|cut:"0" }}
But if I create a custom filter which takes two parameters, I cannot call it with correct syntax.
For answers, I ask this only:
I don't want to send one argument and parse it in my custom filter.
I also don't want to chain the filters.
I think calling with two arguments is legal because there is a default filter named urlizentrunc.
def urlizetrunc(value, limit, autoescape=None):
You cannot. The only work-arounds are to pass in one parameter and parse it into parts, or to have a variable external to the filter passed in.
The docs state that it cannot be done with custom filters. See this question for a more detailed explanation.
You cannot directly pass multiple parameters to non-custom filters, such as urlizetrunc either. urlizetrunc takes one parameter from the template. autoescape is set in by calling the autoescape tag with a parameter of "off" or "on". When you call urlizetrunc from the template, it passes in whatever value autoescape has been set to. You cannot pass in the value of autoescape directly from the template. See this question for a more detailed explanation.
You'll have to settle for taking one argument and then parsing it. The autoescape parameter is kind of special because it's there in cases your filter needs to know whether autoescaping is on or off. For more info, check out this link: https://docs.djangoproject.com/en/1.3/howto/custom-template-tags/#filters-and-auto-escaping
But parsing the argument in your custom filter isn't that hard, usually it's just doing argument.split(" ") or argument.split(",")

How to pass an argument to a method on a template variable in Django?

I am using the lxml library to define a variable (category) in a view. lxml provides a method .get to retrieve custom attributes. I'd like to use it in the template like so:
{{ category.get("foo") }}
I know that when using template variables it is unnecessary to use parenthesis, but I get the following error:
{{ category.get "foo" }}
Could not parse the remainder: ' "foo"' from 'category.get "foo"'
I'm assuming that there is something wrong with my syntax but google has been no help. The django docs say that methods are looked up by using a .
You can't pass an argument to a callable attribute like this. Either pull the value in the view, or write a custom template tag to do it.
I agree with the philosophy of separating logic from design, but there's an exception. I am currently writing a get_image(height=xxx, width=xxx) method for a model. Clearly, it should be up to the template designer to decide the size of the image as the last stage. Though I suppose the correct thing to do is write a custom tag, but why restrict?
Here I wrote a hack to call a function and pass the arguments
http://www.sprklab.com/notes/13-passing-arguments-to-functions-in-django-template/