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/
Related
I've been trying to wrap my head around best practices in vue.js (+ pinia as store). I'm coming from using Django templates where one can use template functions on variables to massage data for displaying. However, I'm not sure where to put such functions in vue.js.
Suppose I have a variable holding a string and I want to cut off trailing digits. The variable is coming from a vue.js for-loop over a list variable present in the store. I would create some function to do so:
displayString(s) {
const re = /\d+$/;
return s.replace(re, "");
}
I would use it in the template in some way:
<th v-for="(item, index) in store.myList" :key="index">
{{ displayString(item) }}
</th>
To me, neither place for putting the function (methods/computed or actions/getters in pinia) would be right as they are all intended to use data from the store or component (and not all of them accept parameters anyway).
Conceptually, where would a function go that does not return data from the component or store but accepts a parameter and returns a modified version of it? Or should I design things differently, writing getters/computed functions that massage the list in some way for displaying the data?
I assume there are (hacky?) ways to achieve what I want (e.g. getters/computed returning a function I can pass the parameter to), but I want to know the best way to handle this in general.
This kind of helper function is known as a filter in Vue 2, and it could be used like:
{{ item | displayString }}
Filters were removed in Vue 3, now functions are supposed to be used directly in a template like:
{{ displayString(item) }}
This function is general-purpose formatter that is not specific to a store and doesn't use its state, so it doesn't belong to Pinia. Instead, displayString can be imported in a component where needed. Or be registered globally:
app.config.globalProperties.displayString = displayString
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.
I want to get the datatype of a value in django template. I am sure there is a way because when you do
value|date:"Y-m-d"
django template understands that the value is timestamp. How does django do it?
the "|date" you see is called a template filter and is a built-in function of django
you may want to create one of your own (here's how) that takes something as input and returns its datatype.
but, imo, it's not a best-practice, since a template should mostly be used to just display and format data. if you need an evaluation on the type i suggest you move that inside a view and return the result in the context, eventually
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/
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 .