I have a string variable in a Python file that I am trying to render in my HTML template. The variable is called contacts, and in my template, I have {{contacts|default:"null"}}. From the documentation, it seems like that should work, but the template keeps coming up with the null keyword. I've scoured the documentation and found nothing. Probably a super simple thing I'm overlooking that has frustrated me to no end.
In the python file, I'm using an API to get a JSON and unloading it into a dictionary (don't know all the specific terms), where I then extract the value I need into a string:
...
dict_data = dict(json.loads(data))
contacts = str(dict_data["contact_count"])
Then in my HTML file:
<p class="spotbanner">
{{contacts|default:"null"}} spots left!
</p>
Is there something else I'm missing? Something super simple that I just don't understand about Django despite having used this method before? Happy to provide more information.
Poked around a teensy bit more and found an answer. For those like me:
It's not as simple as just rendering the variable. Django doesn't see it until you import the .py file into your views.py. Once you've done that, you'll need to create a context in the method that renders the page. For me, it finally worked once I added:
context = context = {"contacts":contacts}
Maybe a simple example might help you. Calling render_to_string to load a template HTML in Django.
Be aware the key name will map to the variable name in the HTML
from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})
# {{foo}} will show string 'bar' in HTML
Referral: https://docs.djangoproject.com/en/3.1/topics/templates/
Accordingly, by your cases, suppose we'll see something like
contacts = str(dict_data["contact_count"])
# if you want to show contact_count --> use {{contact_count}} in HTML
rendered = render_to_string('my_template.html', contacts)
Related
I have django template file. Now i want to get all the variables list that are between curly brackets. I think it is possible with the regular expressions. And i read about regular expressions. But there is no function i found to be helpful.
template code snippet:
<tr><td>
Dear Candidate,<br/>
Welcome to Creative Talent Management!<br/>
We have created an account for you. Here are your details:<br/>
Name:{{name}}<br/>
Email:{{email}}<br/>
Organization:{{organization}}<br/>
Password:{{password}}<br/>
</td></tr>
I want to get name,email,organization,password in my python function.
Right now i'm reading the template but getting empty list.
if created:
temp_path = str(instance.html_template.path)
html_file = open(instance.html_template.path, 'r', encoding='utf-8')
file_data = html_file.read()
render_param = re.findall("^{{ . }}$", file_data)
print("html param ",render_param)
That's sort of back-to-front. You would normally pass all the variables which might be used from your view to the template rendering through the context. It doesn't matter if one or more of the context variables are unused by the template. Of course, you should have a test which catches variable name spelling errors ({{usernmae}} will render as null string without error ).
For checking the template, you might simply grep '{{' some_template.html, or write something in Python to get (say) an alphabetically sorted list of variable names. But that's a program-development aid, not a part of the Django server code.
If you really wanted to, you could just open the template file and write similar Python code as part of your view. But, why??
Why do I need to give html file name in render() - I have already set url in my project file in urls.py in django
urls.py
url('view-books',views.viewBooks)
views.py
def viewBooks(request):
books=models.Book.objects.all()
res=render(request,'BRMapp/view_book.html',{'books':books})
Why can I not give in render view-books?
i think you have typo
def viewBooks(request):
books=models.Book.objects.all()
context = {"books":book}
return render(request,'BRMapp/view_book.html',context)
your question why you need html file name in render because render is a function it takes 3 arguments 1st is request second is "path of the html file" 3rd is the context
further explaination
Do you have basic idea how django work first of first you are not giving url in render you are giving path to render which template should be render . django follow mvc pattern you read on it but to simplify it urls just have the routing task they are just there to filter routes not to do any thing in url you can give 3 arguments two are compulsary first the path by which it recognize that the time has come to act the second the function name which direct him where to go then its function responsibilty to process the data
Unfortunately, you didn't return anything in your view. So you need to add return to your function:
def viewBooks(request):
books=models.Book.objects.all()
return render(request,'BRMapp/view_book.html', {'books':books})
You might want to take a look at this tutorial.
https://yourwebsite/view-book is not the same as BRMapp/view_book.html, Django needs to know that one corresponds to the other.
The routing in Django works like this:
The user sends a request to Django with a url.
Django looks through your urls in urls.py for a path that matches what was requested.
When it finds a path, like view-books, that path has a view. The view is just a function (viewBooks()), and Django executes it.
The view function is expected to return the content that the user will see. You could, if you wanted, write the whole page by hand as a string in the return line of viewBooks(), but that's inconvenient, so instead you tell Django to make the page for you, starting from a template. To do so, you call render().
What render() does is take the template and replace all parts that need to be replaced for the user that will see it. But to know what the initial content will look like, it needs to read it from somewhere, and that's the HTML file BRMapp/view_book.html.
The HTML file doesn't need to have the same name as the view, you could have called it foobar.html and it would have worked the same. But regardless of its name, you need to tell Django that you want to use a file (render() tells Django that), and you need to tell Django where that file is. You'll have many different files in different places with different names, and it can happen that you have the same name for templates in different directories, so Django will not attempt to guess which one you want: you'll have to put its path inside render() so that Django knows where to start building the page.
If you gave the URL to render() instead of the path to the file, Django would get to point 5 and then back again to 1 to figure out what that URL means, and so on and so forth forever.
I have this situation in my views.py
d = {'05:45':3,'06:30':6 (...) }
T = ['05:45','06:30' (...)]
I would like to get d[T[i]] in my HTML site
I tried to call this with dot, but it doesn't work. I will be thankful for help/hint.
Thing you are trying to do is to get element from dictionary using variable. Am I right ? In django template engine it's a little bit tricky, but possible. Use some template tag from this question to acomplish this
Performing a getattr() style lookup in a django template
I am looking for a way to render a variable that will be available in the context of the the page where the cms page will be rendered.
Ex:
I have in the context the logged in user and I also have the last transaction he made on the website.
I would like the text in the rich text field in Wagtail to be like this so that the marketing team can tweak the copy.
Hello ||firstname|| thanks for your purchase. ||productname|| will be
shipped to you soon. The expected delivery date is
||expected_delivery_date||
To be less confusing I replace the double brackets by double pipes to show that the templating system does not need to be django templates for those ones. Simple templating is enough maybe using https://docs.python.org/3.4/library/string.html#template-strings
I think I can achieve this by doing:
A stream field that would have blocks of rich text field and a custom block with the possible context variable they can use
A custom render function that would regex and replace the merge tags in the rich text block with the context values
Create a new filter for simple templating. ex: {{ page.body|richtext|simpletemplate }}
Is there any more obvious way or out of the box way to do templating from within a rich text field?
It would be clunky with a separate streamfield block for each inserted context variable. You'd have to override the default rendering which wraps elements in div tags. However I like that it is more foolproof for the editors.
I've done something like the custom rendering before, but with simple TextFields for formatting special offer code messages. Wagtail editors were given the following help_text to illustrate:
valid_placeholders = ['offer_code', 'month_price']
template_text = models.TextField(
_('text'),
help_text="Valid placeholder values are: {all_valid}. Write as {{{example}}}".format(
all_valid=", ".join(valid_placeholders),
example=valid_placeholders[0],
)
)
This rendered as Valid placeholder values are: offer_code, month_price. Write as {{offer_code}}.
Then in the view:
template_keys = [i[1] for i in Formatter().parse(template_text)]
…and continued rendering from there. Remember to validate the field appropriately using the above Formatter().parse() function too.
I used Django's template formatting rather than Python's string.format() because it fails silently, but you could go with string.format() if cleaned adequately.
The custom template filter would feel easiest to me, so I'd start with that approach and switch to a custom render function if I ran into hurdles.
I found an easier way to do this. I wanted my editors to be able to create pages with dynamic customization to the individual user. With this, my editors are actually able to put template variables into any type of content block as {{ var }} which works just like the Django templating language. For my use case, I am allowing my editors to create email content in the CMS, then pulling that to send the emails:
This is the function to call:
def re_render_html_template(email_body, context):
"""
This function takes already rendered HTML anbd re-renders it as a template
this is necessary because variables added via the CMS are not caught by the
first rendering because the first rendering is rendering the containing block,
so instead they are rendered as plaintext in content the first render, e.g., {{ var }}
Example:
input: <p>Hey {{ user_account.first_name }}, welcome!</p>
output: <p>Hey Brett, welcome!</p>
#param email_body: html string
#type email_body: str
#param context: context dictionary
#type context: dict
#return: html string
#rtype: str
"""
from django.template import Context
from django.template import Template
template = Template(email_body)
context = Context(context)
email_body = template.render(context)
return email_body
Then I call it like so:
email_body = render_to_string(template, context)
# need to re-render to substitute tags added via CMS
email_body = re_render_html_template(email_body, context)
For my site need some "widgets" that elaborate output from various data models, because this widgets are visible in any page is possible with mako to retrieve the data without pass (and elaborate) every time with render() in controllers?
May be you need use helpers
in lib/helpers.py
def tweets(**params):
context = {}
return render('tweets.mako', context)
In you page template do this to render you tweets widget:
h.tweets()
It sounds like you're looking for some combination of FormAlchemy, ToscaWidgets and/or Sprox. I would check out those three.
Also, you might read Chapter 6 of http://pylonsbook.com/en/1.1/ . It helped me a bunch; maybe you'll get something out of it as well.