Bootstrap templates auto-generated? - flask

I'm having trouble setting up Flask-bootstrap. From the official documentation, it seems like all I have to do is apply the Bootstrap constructor to my app, and the templates will be automatically created. So I tried this:
from flask import Flask
from flask.ext.bootstrap import Bootstrap
app = Flask(__name__)
Bootstrap(app)
#app.route('/')
def index():
return '<h1>Where is Bootstrap?</h1>'
if __name__ == '__main__':
app.run(debug=True)
When I run it, no new directories are created and I find no base templates anywhere. Am I missing a critical step? Is there some directory to be created first (I tried creating templates and static and setting the permissions to 777 but that didn't help)? Or perhaps the base templates are first to be generated from the command line?

The base templates are part of the Flask-Bootstrap package you installed. You extend the boostrap base template and override the blocks in it to create a page with a standard layout. You still need to write bootstrap related markup. This is explained right in the docs you linked to.
my_project/templates/my_page.html:
{% extends "bootstrap/base.html" %}
{% block title %}This is an example page{% endblock %}
{% block navbar %}
<div class="navbar navbar-fixed-top">
<!-- ... -->
</div>
{% endblock %}
{% block content %}
<h1>Hello, Bootstrap</h1>
{% endblock %}

Related

How to pass the context to a Django template with include?

I have started building a django project from the tutorial at https://docs.djangoproject.com/en/2.1/intro/tutorial01/
After finishing the base tutorial which creates a project with one app called "polls" I wanted to build a sort of home page that can hold many apps together. For this reason I built an app called "news" and now I'm looking at ways to compose the two apps together.
So far I'm doing so in the main 'news' template, which is called 'news/base.html' and I'm including the different apps in the code.
This is my 'news/base.html' file:
{% include 'news/index.html' %}
{% include polls_template %}
{% include 'news/footer.html' %}
The two templates 'news/index.html' and 'news/footer.html' are just html pages with no arguments, just for testing and they work fine.
The polls_template variable instead is a template variable that I create in the news.views.base function and pass to the template in the context.
This is the view snippet that does this:
def base(request):
t = loader.get_template('polls/index.html')
return render(request, 'news/base.html', {'polls_template': t})
The template is showing just fine but it shows an empty poll since there is no argument. Now my problem is that I cannot find a way to pass a context variable to this template object in order to fill it's fields.
I tried to do something like:
{% include polls_template with context=polls_context %}
But it does not work.
Ideally I would like a way to do all of that in the view because this would allow me to build the apps separately and then just use one view to gather them all and pass them to a template. Thanks in advance for any help!
Possible duplicate of Django - two views, one page (disregard the references to Ajax.) One quick note: I see what you are trying to do, but you should understand that render() is a shortcut that includes both the template loading and the HttpResponse(). You don't need to call loader() if you are using render(). Another problem with your function, you've included the template within the context dict. Please read the linked post b/c there are a number of different approaches but for the sake of completeness, here's one way to approach what you are trying to do. First, typically you'd create a 'base.html' file that would be the container for your content, it would include header, footer and possibly the messaging templates. You could then extend the base.html and include other templates.
'base.html'
<!doctype html>
<html lang="en">
<head>
{% include 'header.html' %}
<body>
{% include 'news.html' %}
{% block content %}
//to be replaced by index/polls content that extends this template//
{% endblock %}
</body>
{% include 'footer.html' %}
</html>
'index.html'
{% extends 'base.html' %}
{% block content %}
<ul>
{% for question in questions%}
<li> {{question}}</li>
{% endfor %}
</ul>
{% endblock %}
'news.html'
<ul>
{% for article in news %}
<li> {{article}}</li>
{% endfor %}
</ul>
And then your function
def index(request):
polls_questions = Question.objects.all()
newest_articles = Articles.objects.filter(post=OuterRef('pk')).order_by('-created_at')
return render(request, 'index.html', {'questions' : polls_questions, 'news': newest_articles})

Custom tag not loaded in template

I've created a custom tag that I want to use, but Django can't seem to find it. My templatetags directory is set up like this:
pygmentize.py
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from django import template
from pygments.formatters.other import NullFormatter
register = template.Library()
#register.tag(name='code')
def do_code(parser,token):
code = token.split_contents()[-1]
nodelist = parser.parse(('endcode',))
parser.delete_first_token()
return CodeNode(code,nodelist)
class CodeNode(template.Node):
def __init__(self,lang,code):
self.lang = lang
self.nodelist = code
def render(self,context):
code = self.nodelist.render(context)
lexer = get_lexer_by_name('python')
return highlight(code,lexer,NullFormatter())
I am trying to use this tag to render code in gameprofile.html.
gameprofile.html
(% load pygmentize %}
{% block content %}
<title>{% block title %} | {{ game.title }}{% endblock %}</title>
<div id="gamecodecontainer">
{% code %}
{{game.code}}
{% endcode %}
</div>
{% endblock content %}
When I navigate to gameprofile.html, I get an error:
Invalid block tag on line 23: 'code', expected 'endblock'. Did you forget to register or load this tag?
For Django 2.2 up to 3, you have to load staticfiles in html template first before use static keyword
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
For other versions use static
{% load static %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
Also you have to check that you defined STATIC_URL in setting.py
At last, make sure the static files exist in the defined folder
The error is in this line: (% load pygmentize %}, an invalid tag.
Change it to {% load pygmentize %}
{% load static %}
<img src="{% static "my_app/example.jpg" %}" alt="My image">
in your templates, use the static template tag to build the URL for the given relative path using the configured STATICFILES_STORAGE.
did you try this
{% load games_tags %}
at the top instead of pygmentize?
{% load static %}
Please add this template tag on top of the HTML or base HTML file
Encountered this same issue but I just added {% load static %} from my extends template and it worked. So in your case if you're trying to load gameprofile.html from a base template you just need to add it like this:
{% extends 'some_base.html' %}
{% block content %}
{% load pygmentize %}
I had the same problem, here's how I solved it. Following the first section of this very excellent Django tutorial, I did the following:
Create a new Django app by executing: python manage.py startapp new_app
Edit the settings.py file, adding the following to the list of INSTALLED_APPS: 'new_app',
Add a new module to the new_app package named new_app_tags.
In a Django HTML template, add the following to the top of the file, but after {% extends 'base_template_name.html' %}: {% load new_app_tags %}
In the new_app_tags module file, create a custom template tag (see below).
In the same Django HTML template, from step 4 above, use your shiney new custom tag like so: {% multiply_by_two | "5.0" %}
Celebrate!
Example from step 5 above:
from django import template
register = template.Library()
#register.simple_tag
def multiply_by_two(value):
return float(value) * 2.0
The app that contains the custom tags must be in INSTALLED_APPS. So Are you sure that your directory is in INSTALLED_APPS ?
From the documentation:
The app that contains the custom tags must be in INSTALLED_APPS in order for the {% load %} tag to work. This is a security feature: It allows you to host Python code for many template libraries on a single host machine without enabling access to all of them for every Django installation.
In gameprofile.html please change the tag {% endblock content %} to {% endblock %} then it works otherwise django will not load the endblock and give error.
You need to change:
{% endblock content %}
to
{% endblock %}

Django - Dynamically include JS/CSS based on installed apps

Does anybody know a way to adjust the included JS/CSS resources in a template based on the apps you've installed?
Let's say we have a basic feature in app x using template.html, and this requires foo.js which is provided in the static files for the app.
What I'd like is a way of saying an additional and optional app y can register bar.js to be included in template.html as well and this provides some advanced functionality.
Ideally, this should be tied in on a feature level - so I register both foo.js and bar.js to provide for feature A and in my template I just indicate I want all the static content for A.
You can follow the django admin framework approach. In your base template have an extra section for style and javascript. Based on some condition you can insert the new files.
For Example:
Define these two blocks in your base template
{% block extracss %}{% endblock %}
{% block extrajs %}{% endblock %}
If you want to add a js or css based on some condition, you can add a check inside
{% block extracss %}
{% if new_app_installed %}
# Insert your CSS
{% else %}
# Default
{% endif %}
{% endblock %}
You can also check if your plugin app is installed and pass this context variable from view to template.
from django.conf import settings
if "new_app" in settings.INSTALLED_APPS:
is_new_app_installed = True

Overriding admin css in django

I want to change certain css in admin django like base.css. Is it better to change directly in the django library? How can I override it in the best way?
It depends a lot of what you want to do. Though first of all: do not overwrite it in the Django admin directly. You got two options I think are reasonable:
If you want to change the appearance of the admin in general you should override admin templates. This is covered in details here: Overriding admin templates. Sometimes you can just extend the original admin file and then overwrite a block like {% block extrastyle %}{% endblock %} in django/contrib/admin/templates/admin/base.html as an example.
If your style is model specific you can add additional styles via the Media meta class in your admin.py. See an example here:
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ('js/admin/my_own_admin.js',)
css = {
'all': ('css/admin/my_own_admin.css',)
}
In settings.py, make sure your app is listed before admin in the INSTALLED_APPS.
Create (your-app)/templates/admin/base_site.html and put the <style> block into the {% block extrahead %}
Example:
{% extends "admin/base_site.html" %}
{% block extrahead %}
<style>
.field-__str__ {
font-family: Consolas, monospace;
}
</style>
{% endblock %}
This solution will work for the admin site, I think it's the cleanest way because it overrides base_site.html which doesn't change when upgrading django.
Create in your templates directory a folder called admin in it create a file named base_site.html.
Create in your static directory under css a file called admin-extra.css .
Write in it all the custom css you want for your forms like: body{background: #000;}.
Paste this in the base_site.html:
{% extends "admin/base.html" %}
{% load static from staticfiles %} # This might be just {% load static %} in your ENV
{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "css/admin-extra.css" %}" />{% endblock %}
{% block branding %}
<h1 id="site-name">{{ site_header|default:_('Django administration') }}</h1>
{% endblock %}
{% block nav-global %}{% endblock %}
As mentioned in the comments:
make sure your app is before the admin app in INSTALLED_APPS, otherwise your template doesn't override django's
That's It! you're done
I just extended admin/base.html to include a reference to my own css file - at the end. The beauty of css is that you don't have to touch existing definitions, just re-define.
In your static directory, create a static/admin/css/base.css file.
Paste in Django's default Admin CSS first, then add your customizations at the bottom.
If you want a global scope and you don't want to think about overriding templates a mixin works really well for this. Put this code wherever you want:
class CSSAdminMixin(object):
class Media:
css = {
'all': ('css/admin.css',),
}
Then, make a CSS file called admin.css with your overrides, for example:
select[multiple] {
resize: vertical;
}
Then, in whatever models you want, do:
class MyModelAdmin(admin.ModelAdmin, CSSAdminMixin):
And you'll be all set.
Have admin/css/changelists.css inside a folder in STATICFILES_DIRS, and it will user that changelists.css instead of the default admin one.
It just so happens that using <style> tag inside {% block extrastyle %}{% endblock %} did not work for me when I wanted to override css. Theming support provides the correct way. All I was missing is {{ block.super }} :-
{% extends 'admin/base.html' %}
{% block extrastyle %}{{ block.super }}
<style>
--- your style ---
--- properties here ---
</style>
{% endblock %}

How do include a dynamic template from another app in Django?

I currently have two apps:
app1/
app2/
templates/
app1.html
app2.html
In app1.html, I'm including app2.html:
<!-- app1.html -->
{% include "app2.html" %}
app2 has some dynamic content:
<!-- app2.html -->
{% app2_value %}
When I display app1.html, the value app2_value doesn't show up. What's the best way to handle the above in Django?
Django doesn't really process dynamic including like PHP or other languages do. Instead, you should have a base template, and use template inheritance and blocks to accomplish what you're trying to do.
So your app2.html would have the same dynamic content, but have a place for app1.html to either override or insert things.
app2.html:
{% block 'title' %}
{{ app2.title }}
{% endblock %}
{% block 'content' %}
{% endblock %}
App1's template can then extend App2's:
app1.html:
{% extends "app2.html" %}
{% block 'title' %}
Actually App 1!
{% endblock %}
{block 'content' %}
...
{% endblock %}
Unfortunately, include-handling is still new in Django and against best practices from what I've seen in the documentation and community.
In Django your views and your templates are decoupled from each other, so when you use {% app2_value %} in a template it will assume that was passed to it from the calling view.
So, to answer your question, to get that value to display, pass it to app1 template in whatever view you use to call it:
# app1 views.py
from django.shortcuts import render_to_response
import app2
def app1_view(request):
return render_to_response('app1.html', {'app2_value': app2.somevalue})
You can actually render a temple as a string and then send it to another template to be displayed. You would still need to send the variabels to the template you are rending as a string. A good use case would be to use the same template to render list or dicts in a special way.