Importing from python to html in flask - python

I am using flask, and I am wondering, how can I get my application variable into my html template without needing to add it when calling the template like in this example:
render_template('home.html', app=app)
Maybe there is a import function I don't know about.
I would like to make it so I can loop through all of my endpoints(app.url_map.iter_rules()) and compare them with the current endpoint( request.endpoint) . My current main problem is getting all of the endpoints into my html file.
My current way of achieving my navigation bar is this:
<header>
<div class="head" align="center">
{% if request.endpoint!='users.login' and current_user.is_authenticated!=true %}
<a href="{{ url_for('users.login') }}">
<button class="tablecontent">Login</button>
</a>
{% endif %}
{% if request.endpoint!='users.register' %}
<a href="{{ url_for('users.register') }}">
<button class="tablecontent">Register</button>
</a>
{% endif %}
{% if request.endpoint!='core.home_page' %}
<a href="{{ url_for('core.home_page') }}">
<button class="tablecontent">Home</button>
</a>
{% endif %}
{% if current_user.is_authenticated %}
{% if request.endpoint!='users.logout' %}
<a href="{{ url_for('users.logout') }}">
<button class="tablecontent">Logout</button>
</a>
{% endif %}
{% endif %}
{% if current_user.is_authenticated %}
{% if request.endpoint!='products.new_product' %}
<a href="{{ url_for('products.add_product') }}">
<button class="tablecontent">Add Product</button>
</a>
{% endif %}
{% endif %}
</div>
</header>
The import error when I try to use the sitemap from the answer:
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\application.py", line 20, in register_applications
from database_website.applications.core.urls import blueprint as core_blueprint
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\applications\core\urls.py", line 3, in <module>
from database_website.applications.core import views
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\applications\core\views.py", line 7, in <module>
from database_website.properties import sitemap
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\properties.py", line 4, in <module>
from database_website.application import application
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\application.py", line 39, in <module>
application = Application.create()
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\application.py", line 35, in create
instance.register_applications()
File "C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\application.py", line 20, in register_applications
from database_website.applications.core.urls import blueprint as core_blueprint
ImportError: cannot import name 'blueprint' from 'database_website.applications.core.urls' (C:\Users\ulman\PycharmProjects\database_website_optimised\source\database_website\applications\core\urls.py)
My view file:
from flask import Flask, render_template, url_for, flash, redirect, request
from flask.views import MethodView
from database_website.applications.views import FormViewMixin
from database_website.applications.products.models import Product
from database_website.applications.core import forms
from database_website.application import application
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
arguments = rule.arguments if rule.arguments is not None else ()
return len(defaults) >= len(arguments)
def sitemap():
links = []
for rule in application.url_map.iter_rules():
# Filter out rules we can't navigate to in a browser
# and rules that require parameters
if "GET" in rule.methods and has_no_empty_params(rule):
url = url_for(rule.endpoint, **(rule.defaults or {}))
links.append((url, rule.endpoint))
return links
class HomePageView(MethodView, FormViewMixin):
def get(self):
form = forms.ProductSearchForm()
products = Product.query.all()
return render_template('core/home.html', title='Home', products=products, form=form)
def post(self):
product_search = request.form.get('search_name')
return redirect(url_for('products.search_product', search_name=product_search))
This is when it has sitemap hardoced, it still shows the exact same error because at the time, when the application object gets imported it does not exist yet. I can show the way I initialize my app.

Hopefully this will help :
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
arguments = rule.arguments if rule.arguments is not None else ()
return len(defaults) >= len(arguments)
def sitemap():
links = []
for rule in app.url_map.iter_rules():
# Filter out rules we can't navigate to in a browser
# and rules that require parameters
if "GET" in rule.methods and has_no_empty_params(rule):
url = url_for(rule.endpoint, **(rule.defaults or {}))
links.append((url, rule.endpoint))
return links
render_template('home.html', links=sitemap())
{% for url, endpoint in links %}
{{ endpoint }}
{% endfor %}

Related

Django How to pass username in a predefined template

I created a templates for header/footer and imports, if I want to acess the username in my header template I cant do that because it has no views. How can I pass the username to the header template?
header_template.py
from django import template
register = template.Library()
#register.inclusion_tag('home/partials/header.html')
def header(element):
return {'element': element, }
Import in Template
{% load header_template %}
{% header context %}
Usage in the template:
{% if user.is_authenticated %}
<a class="btn btn-primary display-4" href="{% url 'home:profil' %}">Profil</a>
{% else %}
<a class="btn btn-primary display-4" href="{% url 'home:login' %}">Login</a>
{% endif %}
Thanks for your help.
You can take context in your tag:
#register.inclusion_tag('home/partials/header.html', takes_context=True)
def header(context, element):
return context | {'element': element}
Read more here:
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
My opinion, you are don't need this, The cause for every new tag in template - a wrong logic.

Getting no reverse match at /post in django

I have been facing this issue. And I have a url name post-page-detail but then also getting error please
See the error screenshot below.
My html page
<a href="{% url "post-detail-page" slug=post.slug %}">
<h2>{{post.tractor_company}} || {{post.tractor_model}}</h2>
<pre><h5>{{post.implimentaion}}</h5>
{{post.farmer}}
Uplode Date : {{post.date}}</pre>
</a>
</div>
URLs.py
from . import views
urlpatterns = [
path("",views.starting_page,name = "starting-page"),
path("posts",views.posts,name = "post-page"),
path("posts/<slug:slug>",views.post_detail,name="post-detail-page"),
]
View.py
from django import forms
from django.contrib.auth.models import User
from django.shortcuts import render, redirect ,get_object_or_404
from .models import Post, Farmer
# Create your views here.
from django.http import HttpResponseRedirect
# Create your views here.
def starting_page(request):
return render(request,"tractor/index.html")
def posts(request):
qs = Post.objects.all()
context = {"posts":qs}
return render(request,"tractor/all-post.html",context)
def add_post(request):
pass
def post_detail(request,slug):
indentified_post = get_object_or_404(Post,slug=slug)
return render(request,"blog/post-detail.html",{'post':indentified_post})
i am iterating through posts and using the post-detail.html page
all-post.html.
{% load static %}
{% block title %}
All Tractors
{% endblock %}
{% block content%}
<section id="all_events">
<br>
<h1 style="text-align:center;">All Tractors</h1>
<ul>
{% for post in posts %}
<br>
{% include "tractor/includes/singlePost.html" %}
{% endfor %}
</ul>
</section>
{% endblock %}```
Try this:
{% url 'post-detail-page' post.slug as post_detail_url %}
<a href="{{ post_detail_url }}">
Let me know if it worked.

Customize show_more tag in django-endless-pagination?

I use pagination on scroll by Django EL(Endless) Pagination library in my project.
By default show_more tag show loading word. I want customize it. I use next code but it work incorrect. It show me 9 icons and at the end don't disappear. I am little bit confused. How to fix it?
settings.py:
EL_PAGINATION_LOADING = """<i class='fa fa-cog fa-spin fa-3x fa-fw text-info text-justify endless_loading'>"""
CURRENT SOLUTION:
I found the working solution but I am not sure that its best and clear way to do that.
custom_tags.py:
from django import template
from django.utils.encoding import iri_to_uri
from el_pagination import (settings, utils)
register = template.Library()
#register.inclusion_tag('documents/show_more_info.html', takes_context=True)
def show_more_info(context, label=None, loading=settings.LOADING, class_name=None):
data = utils.get_data_from_context(context)
page = data['page']
if page.has_next():
request = context['request']
page_number = page.next_page_number()
querystring_key = data['querystring_key']
querystring = utils.get_querystring_for_page(
request, page_number, querystring_key,
default_number=data['default_number'])
return {
'label': label,
'loading': loading,
'class_name': class_name,
'path': iri_to_uri(data['override_path'] or request.path),
'querystring': querystring,
'querystring_key': querystring_key,
'request': request,
}
return {}
documents/show_more_info.html:
{% load i18n %}
{% if querystring %}
<div class="endless_container">
<a class="endless_more{% if class_name %} {{ class_name }}{% endif %}" href="{{ path }}{{ querystring }}" data-el-querystring-key="{{ querystring_key }}">
{% if label %}{{ label|safe }}{% else %}{% trans "more" %}{% endif %}
</a>
<div class="endless_loading" style="display: none;">
<div class="alert alert-info infinite-loading text-center">
<i class="fa fa-cog fa-spin fa-3x fa-fw" aria-hidden="true"></i>
</div>
</div>
</div>
{% endif %}
Finally I can use show_more_info tag instead of default show_me tag.

How to stream the output into browser using flask

I am new to flask. I have code which streams the output to browser. For my below code, i need to input the range value from browser and display the count till the range. thanks in advance.
import flask
import time
from jinja2 import Environment
from jinja2.loaders import FileSystemLoader
app = flask.Flask(__name__)
#app.route('/')
def index():
def inner():
for x in range(100):# eg: 100 should input value from browser
time.sleep(1)
yield '%s<br/>\n' % x
env = Environment(loader=FileSystemLoader('templates'))
tmpl = env.get_template('result.html')
return flask.Response(tmpl.generate(result=inner()))
app.run(debug=True)
result.html
<html>
{% block body %}
<body>
{% for line in result %}
{{ line }}
{% endfor %}
</body>
{% endblock %}
</html>
Here is the answer to do what you are trying to do.
I have modified your app code to:
import flask
import time
from flask import request
from jinja2 import Environment
from jinja2.loaders import FileSystemLoader
app = flask.Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
result = None
if request.method == 'POST':
counter = int(request.form.get('counter', 0))
def inner():
for x in range(counter):# eg: 100 should input value from browser
time.sleep(1)
yield '%s<br/>\n' % x
result = inner
env = Environment(loader=FileSystemLoader('templates'))
tmpl = env.get_template('result.html')
return flask.Response(tmpl.generate(result=result if result is None else result()))
app.run(debug=True)
Here I have modified the index view to handle both GET and POST methods. If a simple GET requests comes it returns the template with result=None and if method is POST it returns=result()(I have assigned result=inner in POST block). The logic to handle None or a value is handled in the template.
And your template needs to be changed to:
<html>
{% block body %}
<body>
{% if result%}
{% for line in result %}
{{ line }}
{% endfor %}
{% else %}
<form method="post">
<input type="text" placeholder="Enter a number" name="counter">
<input type="submit" value="Submit">
</form>
{% endif %}
</body>
{% endblock %}
</html>
I have added the if-else condition as you are using the same template and even the URL doesn't change.
You can follow Flask Quickstart Tutorial to learn more

Clean url in django app. without ?page=1 pattern

I want to have my url pattern like the below pattern:
host:8000/archive/2/
I define page_kwarg in my view but I still receive: host:8000/en/2
Code form main url.py file:
url(_(r'^archive'), include('events.urls_archive', namespace='archive')),
start edit1
and link form main site to my app:
<a href="{% url 'archive:list' %}" title="{% trans 'Archive' %}">
{% trans 'Archive' %}
</a>
end edit1
start edit2
This is the url in my app urls_archive.py:
urlpatterns = [
url('^/(?P<page>\d+)/$', ArchiveListView.as_view(), name="list"),
url('^/(?P<slug>[-\w]+)/(?P<pk>\d+)$', ArchiveDetailView.as_view(), name="detail"),
]
end edit2
The code for my view:
class ArchiveListView(ListView):
model = Booking
queryset = Booking.objects.filter(period__type='archive').order_by('-date_start')
paginate_by = 80
page_kwarg = 'page'
Here is my template code:
{% if is_paginated %}
{% if page_obj.has_previous %}
<h4>Previous</h4>
{% endif %}
<span class="arrow header"><h4>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</h4></span>
{% if page_obj.has_next %}
<h4>Next</h4>
{% endif %}
{% endif %}
Please provide any help.
Thanks.
page_kwarg sets the key that the page number is passed in as. It doesn't affect how it is used in the page. For some reason, you are outputting that directly as /{{ page_obj.previous_page_number }}, which resolves to just /2. You should output it in the same format as it is passed in:
?page={{ page_obj.previous_page_number}}
Edit
If you want your page number to be specified as part of the path arguments, you should use the url tag, like any other URL:
{% url 'archive' page=page_obj.previous_page_number %}

Categories