Using Vue.js inside Django template - python

What I would like to accomplish is to set a django block content inside a vue app. I used vue cli to create a vue app but I am not able to do the following.
views.py
def login(request):
template_name = 'login.html'
return render(request, template_name)
base.html
{% load static %}
<html>
<body>
<div id="app">
{% block component %}{% endblock %}
</div>
</body>
</html>
<script src="{% static 'assets/js/app.js' %}"></script>
login.html
{% extends 'base.html' %}
{% block component %}
<myComponent />
{% endblock %}
What kind of setup do I need to build app.js in way that I can put whatever component I want in the templates?
below is the NOT working vue files
main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div id="app">
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
</style>
Currently if I add tags within the component block in login.html nothing changes.
If I add a tag inside App.vue it will show up in login.html but I want to be able to choose which components will be displayed.
EDIT:
I have made some progress and kind of accomplished what I want but not 100%
I copied files over from a laravel project that uses vue in the way I have described.
package.json
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run development -- --watch",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.19",
"bootstrap": "^4.0.0",
"cross-env": "^7.0",
"jquery": "^3.2",
"laravel-mix": "^5.0.1",
"lodash": "^4.17.19",
"popper.js": "^1.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.20.1",
"sass-loader": "^8.0.0",
"vue": "^2.5.17",
"vue-template-compiler": "^2.6.10"
}
}
webpack.mix.js
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
This configuration accomplishes what I want but I do not want to use the laravel-mix. I tried removing it from the package.json and webpack.mix.js and I receive build fails. The laravel-mix is described as a configuration layer on top of webpack so I'm assuming if I can get pointed in the right direction with how to set that up properly, I will be good to go.

Related

Django - django-privacy-mgmt package not displaying html

I need help implementing this package into this django project:
When viewing the page source, I see the app's HTML loaded from the render tags. But on the actual page, I am not seeing any of the outputted HTML from those render tags.
Can someone please summarize a step by step set of instructions to get this package to work? The instructions provided can be confusing sometimes.
I did not do the following and am not sure how to do these parts:
1) install the add-on on divio.com or via pypi (would rather not install this since it seems to costs money - unless there is a way to use it for free)
2) update your templates/django_privacy_mgmt to reflect your frontend toolchain situation (not sure where in my project to put these files.
3) Then check what kind of tracking items your website is using (either in the templates or via Google Tag Manager or in any imaginable other way) and add them in the "Django Privacy Mgmt" section of the Django Admin interface to the list of 'Tracking Items'. This is necessary so that we can show a list of tracking items to the user in the 'privacy settings' modal.
4) Then implement conditional logic that enables or disables the tracking items that you identified in the previous step (see next chapter).
Here are the steps I followed:
pip3 install django-privacy-mgmt
pip3 install django-parler
pip3 install django-sekizai
python3 manage.py migrate
​TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,"templates")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'sekizai.context_processors.sekizai',
],
},
},
]
​
SITE_ID = 1
INSTALLED_APPS = [
'django.contrib.sites',
'sekizai',
'django_privacy_mgmt',
'parler',
]
{% load privacy %}
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
{% render_privacy_api %}
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<body>
{% render_privacy_banner %}
{% render_privacy_settings_modal %}
{% render_privacy_settings_modal_link %}
</body>
I just started using django two weeks ago and stumbled over the django-privacy-mgmt package. I wanted to use it in my project as well and had some trouble in the beginning. That's why I think I might be able to help you out here.
I had a look at your project, checked it out and integrated the package successfully.
I did the following steps:
Installed the package with pip pip install django-privacy-mgmt
Add the installed apps as you did
INSTALLED_APPS = [
...
'django.contrib.sites',
'sekizai',
'django_privacy_mgmt',
'parler',
...
]
And the django.contrib.messages.context_processors.messages to the context-processors
Added the privacy definitions to your base.html in ./courses/templates
{% load privacy %}
{% load sekizai_tags %}
<!DOCTYPE html>
<html>
<head>
<title>Django Video Membership</title>
{% render_privacy_api %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" ...
{% render_block 'css' %}
</head>
<body>
{% include 'courses/messages.html' %}
<div class="container">
<ol class='breadcrumb'>
<li>Profile</li>
{% block post_detail_link %}
{% endblock %}
{% if not request.user.is_authenticated %}
<li class='pull-right'><a href='/register'>Register</a></li>
<li class='pull-right'><a href='/login'>Login</a></li>
{% else %}
<li class='pull-right'><a href='/memberships'>Memberships</a></li>
{% endif %}
{% render_privacy_settings_modal_link %}
</ol>
</div>
{% block content %}
{% endblock content %}
<script
src="https://code.jquery.com/jquery-3.3.1.js" ...
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ...
{% render_privacy_banner %}
{% render_privacy_settings_modal %}
{% render_block "js" %}
</body>
</html>
python manage.py migration
python manage.py runserver and login with any user will show the link in the navigation, if you click on it the popup appears
Explanations:
In the first step, we install the package. You don't need to install the django-parler and django-sekizai, they are dependencies of the django-privacy-mgmt and will be automatically installed by pip
After the package is successfully installed, we can use the tags in your base.html file, which is situated in ./courses/templates/courses/base.html. First, we include the load privacy in order to be able to use the tags from the django-privacy-mgmt package. Afterward, we load sekizai_tags. This is not described in the documentation, but it is necessary to add the render_block tags for 'js' and 'css', which are used by the package to add javascript and css to your base.html. The creator of the package plans to remove it in the future, please have a look here. You need to put the render_privacy_settings_modal_link where you want to show the link for the user, probably the footer is the best place. I put it in your navigation.
I added the render_privacy_api, render_privacy_banner and render_privacy_settings_modal according to the documentation into your base.html. Please note that the banner is optional.
In step number 5, I migrate the SQL scripts, which will create the tables necessary to create the TrackingItem's.
After you started your local server and you logged in with any user, you should be able to see the 'privacy-setting'-link in the navigation.
1) install the add-on on divio.com or via pypi
I didn't use it. As described here installing with pip works
2) update your templates/django_privacy_mgmt to reflect
What the creator of the package means by that is that you can override his templates. He has for templates, these are the render-tags you are including in you application. I needed to do this in my project, because I use Django 3 and staticfiles are not supported anymore. You don't need to worry about that, everything works fine in your project, but if you want to change the layout of the banner, or the link or the popup, than you have to override the template. you can do this by creating a folder called django_privacy_mgmt in your ./courses/templates and create HTML-files with the names as you find here. Copy the content from the repository and adjust it to your needs.
3) + 4) Then check what kind of tracking items your website is using
If you log into the admin-area by using localhost:8000/admin you should see the model TrackingItem, where you can create items for the django-privacy-mgmt.
In order to exclude scripts depending on the privacy-setting of a user, you have to follow the explanation here. As you can see in the example, it does not load the googletagamanager if the user denied the statistics in the cookie-settings.
Hope this helps!

Django: Inject a string variable from Views.py with HTML and Django template tags into HTML file

So this is my issue: I have a Python string that contains both HTML and Django Template Tags and want to inject it into a base HTML file when I go to that page. Although, when I go to the page, all the HTML renders, but the Django Template Tags do not, and are treated literally as strings?
Here is a simplified example of the issue:
Views.py
def page(request, code):
html = {
'code': code
'html': """<p>Hello world {{ code }}</p> <script src="{% static 'appName/javascript_code_example.js' %}"></script>"""
}
return render(request, 'base.html', html)
base.html
{% load static %}
...
{{ html | safe }}
...
And all I will see when I run the app on my local machine with python3 manage.py runserver and go to the URL that renders base.html is Hello world {{ code }}, and the Javascript code is not executed. Instead of {{ code }} I'd like to see the actual value of the 'code' key in the html dictionary in the Views.py file.
If my base.html file is as follows:
{% load static %}
...
<p>Hello world {{ code }}</p>
<script src="{% static 'appName/javascript_code_example.js' %}"></script>
...
Then the Javascript will be enabled and I will see Hello world value_of_code_variable on the screen.
you have to load the python script that has the template library functions.
Also, Why are you rendering a string into html as opposed to creating an html template? (html file with template syntax)?
The Django template engine will not render (parse) template code inside injected strings. For this to happen, you have to manually render the template code by either:
instantiating a Template object and passing the resulting string to your base.html,
or ideally by moving the value of your html context variable to a template file, and using render_to_string().
If you decide to go for the last one, you should definitely consider using the include template tag in your base.html (instead of manually rendering using render_to_string()), as it reduces the amount of manual work and is the preferred way of rendering template code inside another template.
You can use file writing to do this task.
Make a newfile.html in templates folder and you can do thusly
Views.py
html_tag = "{% extends \"yourapp/base.html\"%}"+"{% block content %}"
html_tag +="<p>Hello world {{ code }}</p> <script src=\"{% static \"appName/javascript_code_example.js\" %}\"></script>"
html_tag +="{% endblock content %}"
html_file = open('yourapp/templates/yourapp/newfile.html', "w")
html_file.write(html_tag)
html_file.close()
html = {
'code': code
}
return render(request, r'yourapp\newfile.html', html)
In base.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>Your base code</p>
<!--The part of code you want to retrieve from views.py file-->
{% block content %}{% endblock content %}
</body>
</html>

How to render by Vue instead of Jinja

<template id="task-template">
<h1>My Tasks</h1>
<tasks-app></tasks-app>
<ul class="list-group">
<li class="list-group-item" v-for="task in list">
{{task.body|e}}
</li>
</ul>
</template>
This above is my html. I want to render the code by Vue instead.
<script>
Vue.component('tasks-app', {
template: '#tasks-template',
data: function() {
return {
list: []
}
}
created: function() {
$.getJson('/api/tasks', function(data) {
this.list = data;
})
}
})
new Vue({
el: 'body',
});
</script>
The above is my Vue code, and Jinja raise an exception that 'task' is undefined, what I hope for is that the html code rendered by Vue instead of Jinja, I know it could be done in Laravel with this:
"#{{task.body}}"
Since I am new to Jinja, could anyone help me out?
The other option is to redefine the delimiters used by Vue.js. This is handy if you have a lot of existing template code and you wish to start adding Vue.js functionality to a Flask or Django project.
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
delimiters: ['[[',']]']
})
Then in your HTML you can mix your Jinja and Vue.js template tags:
<div id="app">
{{normaltemplatetag}}
[[ message ]]
</div>
Not sure when the "delimiters" property was added, but it is in version 2.0.
You need to define parts of your template as raw so that Jinja escapes that portion instead of trying to fill it up with its own context.
Here is how you need to do it:
<template id="task-template">
<h1>My Tasks</h1>
<tasks-app></tasks-app>
<ul class="list-group">
<li class="list-group-item" v-for="task in list">
{% raw %}{{task.body|e}}{% endraw %}
</li>
</ul>
</template>
Ref: http://jinja.pocoo.org/docs/dev/templates/#escaping
If you're using Flask, you can redefine the delimiters used by Jinja:
class CustomFlask(Flask):
jinja_options = Flask.jinja_options.copy()
jinja_options.update(dict(
variable_start_string='%%', # Default is '{{', I'm changing this because Vue.js uses '{{' / '}}'
variable_end_string='%%',
))
app = CustomFlask(__name__) # This replaces your existing "app = Flask(__name__)"
You can either change default VueJS or Jinja delimiters. I actually prefer to change VueJS delimiters like below:
new Vue({
el: '#app',
delimiters: ['${', '}']
})
Then you can use ${variable} instead of conflicting {{ var }}, see docs.
This matches with ES6 template string style, so it is preferable I would say. Keep in mind that you will have to do same when you crate new components.
Alternatively, you could just bypass Jinja template rendering altogether. Just move your index.html from templates directory to static directory (next to css, js files), then:
#app.route("/")
def start():
return app.send_static_file("index.html")
If you are doing all view logic in VueJS, this can work.
Use {{ '{{ vue }}' }}
I had the same problem, and also got it solved.
Configure Vue v2 class instance with the 'delimiters' option:
<div id='myapp'> !{ message } </div>
<script>
let myapp = new Vue({ delimiters: ['!{', '}'], ...});
</script>
Source: https://v2.vuejs.org/v2/api/#delimiters
You can use directives
<h3 v-text="message"></h3>
Or you can use delimiters
const app = new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
message: 'a vue message'
},
});
In your html page
<h3>${ message }</h3>
you can use {% raw %} {% endraw %} in your html code
I know this is old post, and however #Nathan Wailes answer helped me. I further tried avoiding moustaches {{myVal}} and used v-text="myVar" for rendering text. And I did not need to override jinja delimiters. see example below:
<!--Vuetify-->
<v-btn class="ma-2" outlined color="indigo" v-text="connectToggleLabel"></v-btn>
<v-btn class="ma-2" outlined color="indigo"><span v-text="connectToggleLabel"/></v-btn>
<!-- basic -->
<input type="button" :value="connectToggleLabel"/>
Hope this help somebody

Pelican i18n subsites menu items override

I am building a static site with Pelican and the i18n subsites plugin.
The way I understand it, you can override settings in pelicanconf.py with this plugin, but I don’t think the way I did it is working.
Pelicanconf.py:
I18N_SUBSITES = {
'nl': {
'SITENAME': 'Robin Berghuijs Design',
'INDEX_SAVE_AS': 'nieuws.html',
'MENUITEMS': [
('Nieuws','nieuws.html'),
],
},
'en': {
'SITENAME': 'Robin Berghuijs Design',
'INDEX_SAVE_AS': 'news.html',
'MENUITEMS': [
('News','news.html'),
],
}
}
Index.html output:
<nav id="menu"><ul>
<li>Contact</li>
</ul></nav><!-- /#menu -->
base.html template:
{% for title, link in MENUITEMS %}
<li>{{ title }}</li>
{% endfor %}
I get no errors upon site generation. More detail here.
Running pelican with --debug gives this.
As it turns out, the i18n subsites plugin was creating two new sites, with the old one left in the output folder. So there was a site in output/, one in output/nl/, and one in output/en/. Adding DELETE_OUTPUT_DIRECTORY = True and 'OUTPUT_PATH': '', to the Dutch i18n subsites settings solved the issue.

Can anyone describe how I implement the ckeditor in django.contrib.flatpages?

Can anyone describe how I implement the ckeditor in django.contrib.flatpages?
Few steps to get this done. First, make sure ckeditor.js is being served up in some way from django. Info on this can be found at http://docs.djangoproject.com/en/1.2/howto/static-files/#howto-static-files. For this example, I will be serving it from 127.0.0.1:8000/js/ckeditor/ckeditor.js.
You'll need to override the standard flatpage change form template. In your templates directory, create a file in the following subdirectory: <your templates dir>/admin/flatpages/flatpage/change_form.html
Create the following text inside:
{% extends "admin/change_form.html" %}
{% block extrahead %}
{{ block.super }}
<script type="text/javascript" src="/js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" charset="utf-8">
var $ = jQuery = django.jQuery.noConflict(); // Use djangos jquery as our jQuery
</script>
<script type="text/javascript" src="/js/ckeditor/adapters/jquery.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready( function(){
$( 'textarea' ).ckeditor({
"skin":"kama",
"width" : 850,
// "toolbar" : "Basic", // uncomment this line to use a basic toolbar
});
});
</script>
{# Adding some custom style to perty thing up a bit. #}
<style type="text/css">
div>.cke_skin_kama{
width: 100%;
padding: 0!important;
clear: both;
}
</style>
{% endblock %}
The first few lines contain django's default text for the extrahead block. The rest of the script imports the ckeditor javascripts and uses django's already-imported jQuery with the ckeditor jQuery adapter. Finally, we end up forcing some style upon the page, as by default, things look a bit messy.
From here, you can quickly change the toolbar by implementing different options in the ckeditor call. Going to a simple toolbar is likely something you'll need if non-technical people are going to edit these flatpages. You can just uncomment that line in the above code to implement that.
Found good solution:
This is a little tricky. I've got admin.autodiscover() in my urls.py,
so it's automatically going to create an admin for flatpages as
defined in django.contrib.flatpages. I certainly don't want to go
hacking apart something that came with Django, nor do I want to give
up the convenience of autodiscover.
http://www.elidickinson.com/story/django-flatpages-and-ckeditor/2011-11
For a solution without template hacking check this page:
http://johansdevblog.blogspot.it/2009/10/adding-ckeditor-to-django-admin.html
I report here the example if the link goes down.
This is a simple model.
from django.db import models
class SampleModel(models.Model):
title = models.CharField(max_length=50)
text = models.TextField()
def __unicode__(self):
return self.title
This is how to add ckeditor support to a specific type of field, in this case a TextArea.
from sampleapp.models import SampleModel
from django.contrib import admin
from django import forms
from django.db import models
class SampleModelAdmin(admin.ModelAdmin):
formfield_overrides = { models.TextField: {'widget': forms.Textarea(attrs={'class':'ckeditor'})}, }
class Media:
js = ('ckeditor/ckeditor.js',) # The , at the end of this list IS important.
admin.site.register(SampleModel,SampleModelAdmin)
At this point the ckeditor.js will check for all the textarea with the class attribute set to "ckeditor".

Categories