How can I pass a variable via jinja to a litelement? - flask

I'm using flask to serve this html file. It is using jinja to display the provided data from flask. I can tell that the data is there, but I'm not sure how to pass it to my lit element.
<head>
<meta charset="utf-8">
<title>title</title>
<script type="module" src="{{ bundle }}"></script>
<script>
var data = {{ data|tojson }};
</script>
</head>
<body>
User: {{ data.user }}
<app-home .user="${data.user}" ></app-home>
</body>
</html>
The jinja code User: {{ data.user }}, works as expected.
But, in the litelement (AppHome), user is undefined.
I tried a few different variations on the formatting like .user="{{data.user}}", but I haven't been successful in passing the data to the litelement.
Edit to add lit code
import { html, LitElement, property, customElement } from 'lit-element/lit-element.js';
#customElement('app-home')
export class AppHome extends LitElement {
#property({type: String}) user?: string;
render() {
return html`
<p>user: ${this.user}</p>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
'app-home': AppHome;
}
}
The litelement works as expected, and can even render the user if I fetch it separately.

Related

django how to set background colour in html based on context

I am trying to change the background colour in a django project based on some information sent via the context
body base {
}
body alert {
background-color: #FCFF33;
}
def check_alert() -> bool:
return ...
def index(request):
template = 'proj/index.html'
...
context['alert'] = check_alert()
return render(request, template, context)
How can I select the body class in the proj.html based on the field alert in
html looks like
{% load static %}
<html>
<link rel="stylesheet" href="{% static 'css/proj.css' %}" />
<body>
...
</body>
</html>
I am wondering there is a solution like
<html>
<link rel="stylesheet" href="{% static 'css/proj.css' %}" />
<body class={% alert %}>
...
and changing my view.py
context['alert'] = 'alert' if check_alert() else 'base'
EDIT:
When trying art06's solution, I realized that my template would not take any format for the body. Even If I dont class it and just have a simple css
body {
background-color: #FFD9D9;
}
Any suggestions why that is?
Other formats in that css for example for tables created via
{% render_table table%}
are implemented correctly based on the css content.
Css
body.alert{...}
body.base{...}
Template
<body class="{{alert}} ...
If you want to reference alert....Reference it like {{alert}} instead of {% alert %}.

How can i send a post request using vue to django without getting a 403 error?

Im trying to send information using a post request of Vue, but every time i try i get an error 403 58
my django service is ok , i think that the problem is for the csrf token but i dont know how to send it with vue
var vue = new Vue({
el:"#app",
data: {
nombre:"",
apellido:"",
password:""
},
methods:{
enviar:function () {
data = {
"nombre":this.nombre,
"apelldio":this.apelldio,
"password":this.password
};
this.$http.post("http://localhost:8000/usuarios\\",data).then(function (data, status, request) {
if(status ==200){
console.log(data);
}
},function () {
console.log("Error");
});
}
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://bootswatch.com/4/flatly/bootstrap.min.css">
</head>
<body>
<h1>Insertar un nuevo usuario </h1>
<table id = "app">
<tr><td>Nombre:</td><td><input type="texte" class="form-control" v-model="nombre"></td></tr>
<tr><td>Apellido:</td><td><input type="texte" class="form-control" v-model = "apellido"></td></tr>
<tr><td>Password:</td><td><input type="texte" class="form-control" v-model="password"></td></tr>
<tr> <td> <button type="button" id = "enviar" class="btn btn-info" #click="enviar">Enviar</button></td></tr>
</table>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.13/vue-resource.min.js"></script>
{% csrf_token %}
<!-- here goes the scripts of vue and vue resource!>
You could use a method that involves fetching the csrf token with javascript and then passing it to the POST request as a header as mentioned here in Django documentation. In that link there is also examples about fetching the csrf token value.
Also, if the endpoint does not require this kind of protection you can disable it like in this example.
You can use something like this:
{% csrf_token %}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.13/vue-resource.min.js"></script>
<script>
var csrf = document.querySelector('[name="csrfmiddlewaretoken"]').value;
Vue.http.interceptors.push(function (request, next) {
request.headers['X-CSRF-TOKEN'] = csrf;
next();
});
// Or maybe
Vue.http.headers.common['X-CSRF-TOKEN'] = csrf;
</script>
You can also use it like this, for example:
<script>
var csrf = '{{ csrf_token }}';
Vue.http.headers.common['X-CSRF-TOKEN'] = csrf;
// Or other way
// Vue.http.interceptors.push(...);
</script>
Note: I'm no django developer but gave you the basic idea, so check the doc for more info.

Why doesn't the curly braces work for a Vue app within a Django template?

Basically, Im trying to integrate Vue with Django. I have the following template:
<!DOCTYPE html>
<html>
<head>
<title>Django Vue</title>
</head>
<body>
{% verbatim %}
<div id="components-demo">
<button-counter></button-counter>
</div>
{% endverbatim %}
<!-- Vuejs -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- App -->
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">You clicked me {{ count }} times.</button>
`
});
// App definition
new Vue({ el: '#components-demo' });
</script>
</body>
</html>
Everything is very simple, CDNs are used, not webpack. The component shows up, but the count does not. In other words, the curly braces are not functioning properly within my template. Why is that? I have the verbatim tag up and running.
It looks like this:
Any help?
You didnt wrap the {{count}} with a {% verbatim %} tag, which means {{count}} is being interpreted by Django, not by Vue (you should be able to see that this is the case if you inspect the template that is being rendered).
This should work:
<!-- App -->
{% verbatim %}
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">You clicked me {{ count }} times.</button>
`
});
// App definition
new Vue({ el: '#components-demo' });
</script>
{% endverbatim %}
The {% verbatim %} tag you used is not really necessary, because the reason you want to use it (in this case) is because both Django and Vue use the same mustache {{}} syntax, which is causing the conflict. This means you should use {% verbatim %} only if there would otherwise be a conflict of syntax (for example, the mustache syntax).

django webpack loader setting to load css

It works when I set up like below. I am using django-webpack-loader
index.html
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Jayground</title>
{% render_bundle 'main' 'css' %}
</head>
<body>
<div id="react-app"></div>
{% render_bundle 'main' 'js' %}
</body>
</html>
Header.js
import styles from './header.css';
export default class Header extends React.Component {
render(){
<div className="header">
hello
</div>
}
}
webpack.config.js (I made styles.css separately and then load css file in html separately so that className="header" works.)
config.plugins = config.plugins.concat([
new ExtractTextPlugin('styles.css'),
]);
config.module.rules.push(
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader'
})
}
)
According to what I understood, code below should work too. If I don't separate css file by using ExtractTextWebpackPlugin, bundle js file have css information in it like this.
exports.push([module.i, ".header {\r\n background-color: blue;\r\n}\r\n\r\n.extra {\r\n\tfont-size: 50;\r\n}", ""]);
css should be loaded properly.
Header.js
import styles from './header.css';
export default class Header extends React.Component {
render(){
<div className={styles.header}>
hello
</div>
}
}
webpack.config.js
config.module.rules.push(
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
)
Do I miss something to work properly?

typeahead autocomplete for Django

base.html
<html lang=en>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="/media/js/autocomplete.css">
<script type="text/javascript" src="/media/js/jquery-1.2.1.js"></script>
<script type="text/javascript" src="/media/js/dimensions.js"></script>
<script type="text/javascript" src="/media/js/autocomplete.js"></script>
{% block extra_css %}{% endblock extra_css %}
<title>{% block title %}books are social{% endblock title %}</title>
</head>
<body>
{% block body %}
{% endblock body %}
</body>
</html>
and the smaller template:
<script type="text/javascript" >
$(function(){
setAutoComplete("bookSearchField", "bookResults", "/lookup/?query=");
});
</script>
<label for="bookSearchField">Book: </label>
<input type="text" id="bookSearchField" name="bookSearchField">
urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('project.app.views',
(r'^/lookup/$', 'book_lookup'),
)
models.py
class Book(models.Model):
name = models.CharField(max_length=200)
views.py
from django.utils import simplejson
from django.http import HttpResponse
from project.app.models import Book
def book_lookup(request):
# Default return list
results = []
if request.method == "GET":
if request.GET.has_key(u'query'):
value = request.GET[u'query']
# Ignore queries shorter than length 3
if len(value) > 2:
model_results = Book.objects.filter(name__icontains=value)
results = [ {x.id :x.name,} for x in model_results ]
json = simplejson.dumps(results)
return HttpResponse(json, mimetype='application/json')
so is there any tutorial/solution to create bootstrap typeahead for elagent and responsive .
<input id="book_lookup" class="search-query typeahead" data-items="4" type="text"
placeholder="Select here....">
Edited:
<script type="text/javascript">
var typeahead_data = [];
function get_client_names() {
$.ajax({
url: "/lookup/?query=",
success: function (data) {
$.each(data, function (key, value) {
typeahead_data.push(value.toString());
});
// assign the array to my typeahead tag
$('.typeahead').typeahead({
source: typeahead_data,
});
}
});
}
$(function () {
get_client_names();
});
</script>
need something like
$("#book_lookup").tokenInput([{"id": 1, "name": "ddddd"},{"id": 2, "name": "ddffddd"}],{preventDuplicates: true,
hintText: "Type book name here...",
validateInputAjax: true,
validateInputObjectType: "book name",
validateInputNewObjectLink: function (value) {
$('#book_lookup').tokenInput(
'add', {'id': value, 'name': value});
return true;
},
validateInput: function (value) {
$.post("/lookup/", {validate_field_name: value},
function(data){
if (data.valid) {
$("#book_lookup").tokenInput('valid', value);
} else {
$("#book_lookup").tokenInput('invalid', value, 'is not a valid Book name');
};
});
}});
});
how to change data-source to book_lookup json view ?
I have used Bootstrap's typeahead before and what I did was create a method to get the dictionary via Ajax like this:
<script type="text/javascript">
var typeahead_data = [];
function get_client_names() {
$.ajax({
url: "/lookup",
success: function (data) {
$.each(data, function (key, value) {
typeahead_data.push(value.toString());
});
// assign the array to my typeahead tag
$('.typeahead').typeahead({
source: typeahead_data,
});
}
});
}
$(function () {
get_client_names();
});
</script>
The tag element is like this:
<input id="book_lookup" class="search-query typeahead" data-items="4" type="text"
placeholder="Select here....">
And basically the rest of your code is ok.
Note that here you're doing an ajax request (this requeires jquery) to the /lookup/ view which in turn returns a json object, that should look like this: [name1,name2,name3...]. You can test if the view is working ok by just accessing the view through the explorer like this: /lookup/ and if you see the dictionary displaying correctly there, the server side is ok.
Hope this works for you!
In Paulo's answer, he just has a static list of items to search from, that is why he calls the ajax on load, and gets the list and adds it to the source.
In your case, I think, you need to query whatever the user types, and send it to the server. This can be done by adding the function param in data-source, which gets 2 arguments, query and a callback.
Check here