Is it possible to include the following in my django html file?
<!-- Hit template -->
<script type="text/template" id="hit-template">
<div class="hit media">
<a class="pull-left" href="{{ url }}">
<img class="media-object" src="{{ image }}" alt="{{ name }}">
</a>
<div class="media-body">
<h3 class="hit_price pull-right text-right text-danger">
${{ salePrice }}
</h3>
<h4 class="hit_name">{{{ _highlightResult.name.value }}}</h4>
<p>
{{{ _highlightResult.shortDescription.value }}}
</p>
<ul class="hit_tags list-inline">
{{#_highlightResult.manufacturer}}<li>{{{ _highlightResult.manufacturer.value }}}</li>{{/_highlightResult.manufacturer}}
{{#_highlightResult.category}}<li>{{{ _highlightResult.category.value }}}</li>{{/_highlightResult.category}}
{{#type}}<li>{{{ type }}}</li>{{/type}}
</ul>
</div>
</div>
</script>
When I currently include that I get a django error, as django templating engine seems to be trying to parse it first.
If you're running django >= 1.5, try the verbatim template tag.
[edit]
on earlier versions of django, you should be able to replicate the template tag functionality yourself with the following:
"""
From https://gist.github.com/1313862
"""
from django import template
register = template.Library()
class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
def render(self, context):
return self.text
#register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
Related
I am working on an ecommerce store in Django. I want to know that how do I use the database data passed to templates using render() method, conditionally through JavaScript or AJAX or JSON?
For example, let's say I have a following models.py:
from django.db import models
class Suit(models.Model):
title = models.CharField(max_length = 100, verbose_name = "Title")
img = models.FileField(upload_to = 'suit-products/', null = True, verbose_name = "Picture")
def __str__(self):
return f"{self.title}"
class Buttoning(models.Model):
title = models.CharField(max_length = 100, verbose_name = "Title")
img = models.FileField(upload_to = 'buttonings/', null = True, verbose_name = "Picture")
def __str__(self):
return f"{self.title}"
and following views.py
from django.shortcuts import render
def index(request):
suit_prods = Suit.objects.all()
buttoning = Buttoning.objects.all()
context {
"suit_prods": suit_prods,
"buttoning": buttoning
}
return render(request, "index/index.html", context)
and following index.html (template):
{% for element in suit_prods %}
<li>
<a href="#">
<div id="menu">
<img src="{{ element.img.url }}" />
<span>{{ element.title }}</span>
<span></span>
</div>
</a>
</li>
{% endfor %}
Now what I want is, if the clicked element in the list items in index.html has the title as "two_piece_suit" then show items of {{ buttoning }} as a list, otherwise pass.
If I explain it more using some JS syntax, then I want following kind of behaviour:
<scrip>
var suit_menu = document.getElementsByClassName("menu");
for(var i = 0; i < suit_menu.length; i++) {
if(suit_menu.text == "two_piece_suit") {
{% for element in buttoning %}
<li>
<a href="#">
<div id="buttoning">
<img src="{{ element.img.url }}" />
<span>{{ element.title }}</span>
<span></span>
</div>
</a>
</li>
{% endfor %}
}
}
</script>
If I understand correctly, you don't necessarily need JavaScript to achieve this. Also, <script> is missing a t, and your for loop doesn't seem to add the HTML to the document at all.
You can achieve that purely with the Django Template Language by integrating the buttons for loop with an if condition like this:
{% if element.title == 'two_piece_suit' %}
{% for button in buttoning %}
<Some HTML>{{ button.title }}</Some HTML>
{% endfor %}
{% endif %}
That way, the list of buttons is only displayed if the title is two_piece_suit.
Let me start by saying I have 2 variables in an HTML template(messages and users) and I have multiple buttons that when one of them is clicked it calls a jquery code that sends a post request to a Django server and it returns an update to a variable(messages)
however, it's not updating the loop, I also tried to return a new HTML page that contains the new variable updated but the jquery is not updating the whole page with the new HTML
if I can update the variable alone it would be better and if I can't do that how can I make jquery use the new HTML page
the python code i used to return the update to the varialbe messages:
if request.method == 'POST':
send=Message.objects.filter(from_id=request.POST.get('userId'),to_id=2)
rec=Message.objects.filter(from_id=2,to_id=request.POST.get('userId'))
messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True)
print(messages)
return HttpResponse(list(messages))
and the code i used to return new HTML template:
m = Message.objects.filter(to_id=2).order_by('-id')
users = {}
for i in m:
if users.get(i.from_id.username) == None:
users[i.from_id.username] = User.objects.get(id=i.from_id.id)
users = list(users.values())
send=Message.objects.filter(from_id=users[0].id,to_id=2)
rec=Message.objects.filter(from_id=2,to_id=users[0].id)
messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True)
if request.method == 'POST':
send=Message.objects.filter(from_id=request.POST.get('userId'),to_id=2)
rec=Message.objects.filter(from_id=2,to_id=request.POST.get('userId'))
messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True)
print(messages)
return render(request,'psych.html',{"users":users, "messages":list(messages)})
return render(request,'psych.html',{"users":users, "messages":list(messages)})
the HTML code and jquery code that uses the variable and try to update it
function newUser(id){
$.ajax({
type: 'POST',
url:'/psych.html/',
data:{
userId:id,
},
success: function(data){
console.log(data);// the data returnd are correct and as needed
//but i cant make it update the messages
$('#messageDiv').load(document.URL + ' #messageDiv');
}
})
}
{% for i in users %}
<li class="">
<button type="button" class="btn" onClick="newUser({{i.id}})">
<div class="d-flex bd-highlight">
<div class="img_cont">
<!-- here was an image ----------------------------------------------->
</div>
<div class="user_info">
<span>{{i.id}}</span>
</div>
</div>
</button>
</li>
{% endfor %}
<!-- The varialbe that i'm trying to update is called messages bottom -->
{% for o in messages %}
{% if o.to_id.id != 2 %}
<div class="d-flex justify-content-start mb-4">
<div class="img_cont_msg">
<!-- here was an image-->
</div>
<div class="msg_cotainer">
{{o.message}}
<!-- <span class="msg_time">{{o.time}}</span> -->
</div>
</div>
{% else %}
<div class="d-flex justify-content-end mb-4">
<div class="msg_cotainer_send">
{{o.message}}
<!-- <span class="msg_time_send">{{o.time}}</span> -->
</div>
<div class="img_cont_msg">
<!-- here was an image-->
</div>
</div>
{% endif %}
{% endfor %}
if it helps i did it before and updated the messages from jquery but i used form and there was only 1 variable i will add the code to that too
$(document).on('submit','#submitMessage', function (e){
e.preventDefault();
$.ajax({
type: 'POST',
url:'/psych.html/',
data:{
message:$('#messageHolder').val(),
csrfmiddlewaretoken: $('input[message=csrfmiddlewaretoken]').val(),
},
success: function(data){
// it work like charm here
$('#messageDiv').load(document.URL + ' #messageDiv');
}
})
})
{% for o in messages %}
{% if o.to_id.id == 2 %}
<div class="d-flex justify-content-start mb-4">
<div class="img_cont_msg">
<!-- here was an image-->
</div>
<div class="msg_cotainer">
{{o.message}}
<!-- <span class="msg_time">{{o.time}}</span> -->
</div>
</div>
{% else %}
<div class="d-flex justify-content-end mb-4">
<div class="msg_cotainer_send">
{{o.message}}
<!-- <span class="msg_time_send">{{o.time}}</span> -->
</div>
<div class="img_cont_msg">
<!-- here was an image-->
</div>
</div>
{% endif %}
{% endfor %}
<form id="submitMessage" >
{% csrf_token %}
<div class="card-footer">
<div class="input-group">
<div class="input-group-append"></div>
<input name="message" class="form-control type_msg" placeholder="Type your message..." id="messageHolder">
<div class="input-group-append">
<button type="submit" class="btn">
<span class="input-group-text send_btn" ><i class="fas fa-location-arrow"></i></span>
</button>
</div>
</div>
</div>
</form>
Try this
$("#messageDiv").load(location.href+" #messageDiv>*");
i figured the problem and it was because i didn't know that
$("#messageDiv").load(location.href+" #messageDiv>*");
would make a GET request so all I did was adding the necessary data to the URL and then change the URL too(so if the client refreshed the page it would stay in the same spot) without refreshing the page and then do the command app there
if it could help anyone please look at the code below:
function newUser(id){
var url = document.URL;
url = url.split('/');
url[url.length-2] = id;
url = url.join('/');
window.history.pushState("object or string", "my website name", url);
$('#messageDiv').load(url + ' #messageDiv');
}
sadly i don't know how to do post requst then load the page please if you know comment down bellow so someone else might get help from it
Folks, scratching my head at this, there's a kind of an answer to this here, but having difficulty implementing it.
I currently have a recipe and styles table, and when submit an "add recipe" form, it copies data from the styles table into the recipe. What I would like to do is to select a style in the add recipe form and have this data populate form fields. So I'd like style-type for example to be populated in the form on updating the style select dropdown.
My set up:
Routes:
#app.route('/recipe/new', methods=['GET', 'POST'])
#login_required
def addrecipe():
form = RecipeForm()
if form.validate_on_submit():
recipe = Recipe(recipe_name=form.recipe_name.data,
recipe_style=form.style.data.id,
style_name=form.style.data.name,
style_type = form.style.data.type)
db.session.add(recipe)
db.session.commit()
flash('You added your recipe, get brewing!', 'success')
return redirect(url_for('recipes'))
return render_template('add_recipe.html', title = 'Add Recipe', form=form, legend='Add Recipe')
Models:
class Recipe(db.Model):
id = db.Column(db.Integer, primary_key=True)
recipe_name = db.Column(db.String(100), nullable=False)
recipe_style = db.Column(db.Text, db.ForeignKey('styles.id'))
style_name = db.Column(db.String(100))
style_type = db.Column(db.String(100))
# used for query_factory
def getStyles():
return Styles.query.order_by(Styles.name.asc())
Forms:
class RecipeForm(FlaskForm):
recipe_name = StringField('Recipe Name', validators=[DataRequired(), Length(min=2, max=20)])
style = QuerySelectField(query_factory=getStyles,
get_label="name")
style_type = StringField('Style Type')
The Form HTML:
<form method="POST" action="">
{{ form.hidden_tag() }}
<legend class="border-bottom mb-4">{{ legend }}</legend>
<fieldset class="form-group card p-3 bg-light">
<h5 class="card-title">Overview</h5>
<div class="form-row">
<div class="form-group col-md-3">
{{ form.recipe_name.label(class="form-control-label") }}
{% if form.recipe_name.errors %}
{{ form.recipe_name(class="form-control form-control-sm is-invalid") }}
<div class="invalid-feedback">
{% for error in form.recipe_name.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.recipe_name(class="form-control form-control-sm") }}
{% endif %}
</div>
</fieldset>
<fieldset class="form-group card p-3 bg-light">
<h5 class="card-title">Style</h5>
<div class="form-row">
<div class="form-group col-md-3">
{{ form.style.label(class="form-control-label") }}
<input class="form-control form-control-sm" type="text" placeholder="Search Styles" id="myInput" onkeyup="filterFunction()">
{% if form.style.errors %}
{{ form.style(class="form-control form-control-sm is-invalid") }}
<div class="invalid-feedback">
{% for error in form.style.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.style(class="form-control form-control-sm", id="style_name") }}
{% endif %}
</div>
<div class="form-group col-md-2">
{{ form.style_type.label(class="form-control-label") }}
{% if form.style_type.errors %}
{{ form.style_type(class="form-control form-control-sm is-invalid") }}
<div class="invalid-feedback">
{% for error in form.style_type.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.style_type(class="form-control form-control-sm", id="styletype", style_type_tag='{{ form.style.data.type }}' ) }}
{% endif %}
</div>
</div>
</fieldset>
My Javascript so far:
style_name.oninput = function(o) {
// style = document.getElementById('styletype')
styletype.value = $(o).attr('style_type_tag')
}
I can get some basic stuff working with the JS function. So when I update the dropdown, it'll populate the field with some text. What I can't figure out is how to pull the style_type info from the database. The link at the top here loads that info into the html tags of the text box, but it's a little different to what I'm doing. The poster has looped through some items and it isn't a form. My style_type_tag is just showing up as the raw text. I'm guessing that the loop here is crucial but I can't quite make the step to getting into my setup.
Any help much appreciated!
So the answer to this was building a simple API. I'm sure there are simpler methods, but I wanted a bit of practice here and thought it would be useful in building other features into the project.
I followed Brad Traversy's vid on the subject and used the GET section to make this. His project was a simple single file project, so I had to get a bit more involved with imports etc in my project.
Grab postman to interact with the API
Install Marshmallow, To requirements.txt, add the lines:
flask-marshmallow
marshmallow-sqlalchemy
then run
pip install -r requirements.txt
Import and initialise marshmallow. In init.py:
from flask_marshmallow import Marshmallow
ma = Marshmallow(app)
Add style schema To models.py
# import module
from flaskblog import ma
# create schema with the fields required
class StyleSchema(ma.Schema):
class Meta:
fields = ("id", "name", "origin", "type")
# initialise single style schema
style_schema = StyleSchema()
# initialise multiple style schema
styles_schema = StyleSchema(many=True)
Note that the strict=True isn't necessary any more with Marshmallow.
Create endpoints/routes, to routes.py:
# Get All Styles
#app.route('/styleget', methods=['GET'])
def styles_get():
all_styles = Styles.query.all()
result = styles_schema.dump(all_styles)
# return jsonify(result.data) - note that this line is different to the video, was mentioned in the comments. Was originally "return jsonify(result.data)"
return styles_schema.jsonify(all_styles)
# Get Single Product
# passes the id into the URL
#app.route('/styleget/<id>', methods=['GET'])
def style_get(id):
style = Styles.query.get(id)
return style_schema.jsonify(style)
Update JS script:
style_name.onchange = function() {
// creates a variable from the dropdown
style = document.getElementById('style_name').value
// uses the variable to call the API and populate the other form fields
fetch('/styleget/' + style).then(function(response) {
response.json().then(function(data) {
// this takes the 'type' data from the JSON and adds it to the styleType variable
styleType = data.type;
// adds the data from the variable to the form field using the ID of the form.
styletype.value = styleType
});
});
}
Hope this helps anyone who runs into the same challenge!
Hey guys I am beyond frustrated/exhausted trying to fix this unicode code \u200e showing in my web page. I tried everything I can think of. Here is what my page looks like, its data scraped articles from news.google.com and shown on my page with the time submission (the time submission is where the \u200e pops up everywhere)
http://i.imgur.com/lrqmvWG.jpg
I am going to provide my views.py, my articles.html (the page in the picture that is set up to display everything), and header.html (for whatever reason. But this is the parent template of articles.html for the CSS inheriting). Also, I researched and know that the \u200e is a left-to-right mark and when I inspect the source in news.google.com, it pops up in the time submission element as
like so:
<span class="al-attribution-timestamp">51 minutes ago</span>
I tried editing the views.py to encode it using .encode(encoding='ascii','ignore') or utf-8 or iso-8859-8 and a couple other lines of code I found researching deep on google but it still displays \u200e everywhere. I put it in so many different parts of my views.py too even right after the for loop (and right before + after it gets stored as data in the variable "b" and its just not going away. What do I need to do?
Views.py
def articles(request):
""" Grabs the most recent articles from the main news page """
import bs4, requests
list = []
list2 = []
url = 'https://news.google.com/'
r = requests.get(url)
sta = ""
try:
r.raise_for_status() == True
except ValueError:
print('Something went wrong.')
soup = bs4.BeautifulSoup(r.text, 'html.parser')
for listarticles in soup.find_all('h2', 'esc-lead-article-title'):
a = listarticles.text
list.append(a)
for articles_times in soup.find_all('span','al-attribution-timestamp'):
b = articles_times.text
list2.append(b)
list = zip(list,list2)
context = {'list':list, 'list2':list2}
return render(request, 'newz/articles.html', context)
articles.html
{% extends "newz/header.html" %}
{% block content %}
<script>
.firstfont (
font-family: serif;
}
</script>
<div class ="row">
<h3 class="btn-primary">These articles are scraped from <strong>news.google.com</strong></h3><br>
<ul class="list-group">
{% for thefinallist in list %}
<div class="col-md-15">
<li class="list-group-item">{{ thefinallist }}
</li>
</div>
{% endfor %}
</div></ul>
{{ list }}
{% endblock %}
header.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sacred Page</title>
<meta charset="utf-8" />
{% load staticfiles %}
<meta name="viewport" content = "width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static 'newz/css/bootstrap.min.css' %}" type = "text/css"/>
<style type="text/css">
html,
body {
height:100%
}
</style>
</head>
<body class="body" style="background-color:#EEEDFA">
<div class="container-fluid" style="min-height:95%; ">
<div class="row">
<div class="col-sm-2">
<br>
<center>
<img src="{% static 'newz/img/profile.jpg' %}" class="responsive-img" style='max-height:100px;' alt="face">
</center>
</div>
<div class="col-sm-10">
<br>
<center>
<h3><font color="007385">The sacred database</font></h3>
</center>
</div>
</div><hr>
<div class="row">
<div class="col-sm-2">
<br>
<br>
<!-- Great, til you resize. -->
<!--<div class="well bs-sidebar affix" id="sidebar" style="background-color:#E77200">-->
<div class="well bs-sidebar" id="sidebar" style="background-color:#E1DCF5">
<ul class="nav nav-pills nav-stacked">
<li><a href='/'>Home</a></li>
<li><a href='/newz/'>News database</a></li>
<li><a href='/blog/'>Blog</a></li>
<li><a href='/contact/'>Contact</a></li>
</ul>
</div> <!--well bs-sidebar affix-->
</div> <!--col-sm-2-->
<div class="col-sm-10">
<div class='container-fluid'>
<br><br>
<font color="#2E2C2B">
{% block content %}
{% endblock %}
{% block fool %}
{% endblock fool %}
</font>
</div>
</div>
</div>
</div>
<footer>
<div class="container-fluid" style='margin-left:15px'>
<p>Contact | LinkedIn | Twitter | Google+</p>
</div>
</footer>
</body>
</html>
If you want, you can use replace() to strip the character from your string.
b = articles_times.text.replace('\u200E', '')
The reason that you see \u200E in the rendered html instead of is that you are including the tuple {{ thefinallist }} in your template. That means Python calls repr() on the tuple, and you see \u200E. It also means you see the parentheses, for example ('headline' '\u200e1 hour ago')
If you display the elements of the tuple separately, then you will get in the template instead. For example, you could do:
{% for headline, timeago in list %}
<div class="col-md-15">
<li class="list-group-item">{{ headline }} {{ timeago }}
</li>
</div>
{% endfor %}
Need achieve some features like [http://webonise.co.uk/][1] when click on contact,resume,resources link will update (location URL&div content) but without refresh the page.
Flask view function
#app.route('/')
def index():
flash('Welcome')
return render_template('index.html')
Under index.html is extends base.html
{% block content %}
{{super()}}
<section class="content">
<i class="mdi-event"></i>Event
<i class="mdi-contact"></i>Contact
<div class="board">
{# dynamic template #}
{# without using {{% include 'event.html' %}} #}
</div>
</section>
{%- endblock %}
How can i dynamic rendar event.html / contact.html content when different link is click and rendar under {# dynamic template #} without refresh the page ?
<!--event.html-->
<ul class="list">
<li>
<h3>123</h3>
<p>abc</p>
</li>
</ul>
What I try
import jinja2 Environment but still no idea how to achieve this
env = Environment(autoescape=True,
loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
#app.route('/')
def index():
board = env.get_template('event.html')
flash('Welcome Home Tyler')
return render_template('index.html', board=board)
Is there really need ajax technique get/post method to achieve all this?
You can use Flask-Sijax which helps you add Sijax support to your Flask app. Sijax is a python/jquery library that makes AJAX easy to use on your web applications. Alternatively you could do this:
<script>
$(document).ready( function() {
$('#next').click(function() {
$.ajax("{{ url_for('yourroute') }}").done(function (reply) {
$('#container').html(reply);
});
});
});
</script>
<input type="button" id="next" value="Next" />
<div id="container"></div>