I would like to use gulp-liveReload with Django, is it possible? I have read that there is an alternative for Grunt, but I would prefer work with Gulp, it is easier for me.
Thanks,
I wrote up how to do it in a recent blog post here:
http://www.revsys.com/blog/2014/oct/21/ultimate-front-end-development-setup/
Basically you just need to write gulp tasks that watch what files you want to trigger livereloads, so for me that's templates:
/* Trigger a live reload on any Django template changes */
gulp.watch('**/templates/**').on('change', livereload.changed);
But you could also trigger it on models.py, views.py, or anything else you want really.
have you try this django-livereload ?
I also was struggling to find an answer howto to start a django server and get the browser live reloading working at the same time, however it turned out that it is easy to achieve (even when working cross platform on windows and linux):
//jshint node:true
'use strict';
var gulp = require('gulp'),
....
gutil = require('gulp-util');
var browserSync = require('browser-sync').create();
var serverUrl = 'localhost:8000';
var exec = require('child_process').exec;
var isProd = gutil.env.type === 'prod';
....
gulp.task('sass', function() {
return sass(sources.sass, {
compass: true,
sourcemap: true,
style: isProd ? 'compressed': 'expanded',
})
....
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(targets.css))
.pipe(browserSync.stream());
});
....
gulp.task('watch', function() {
gulp.watch(sources.sass, ['sass']);
gulp.watch(sources.pug, ['html'])
.on('change', browserSync.reload);
gulp.watch(sources.ts, ['typescript'])
.on('change', browserSync.reload);
// update browser on python change
gulp.watch('website/**/*.py')
.on('change', browserSync.reload);
});
// start django server
gulp.task('webserver', function() {
var isWin = /^win/.test(process.platform);
var cmd = '. venv/bin/activate && PYTHONUNBUFFERED=1 ';
if (isWin) { //for Windows
cmd = 'venv\\Scripts\\activate.bat && set PYTHONUNBUFFERED=1 && ';
}
var proc = exec(cmd + 'python manage.py runserver ' + serverUrl);
proc.stderr.on('data', function(data) {
process.stdout.write(data);
});
proc.stdout.on('data', function(data) {
process.stdout.write(data);
});
});
// start livereload
gulp.task('browser-sync', ['typescript', 'html', 'sass', 'webserver'], function() {
browserSync.init({
proxy: serverUrl,
port: 8080,
reloadDelay: 300,
reloadDebounce: 500
});
});
I assumed that you are talking about the static assets (stuff under static) in your django project.
The key step is to make the pages served by python manage.py runserver be aware of changes from the livereload server (usually implemented by tiny-lr)
A simple way to do so is to inject the following code to your base.html (assuming it as the parent template for the rest of html templates in django project)
# views.py
from django.conf import settings
# other imports ...
def index(request):
ctx = {'debug': settings.DEBUG, }
# other context setup...
return render(request, 'index.html', ctx)
# other views' definitions...
<!-- base.html -->
{% if debug %}
<!--
assuming your livereload server runs at localhost:35729
(default host:port for livereload )
-->
<script src="//localhost:35729/livereload.js"></script>
{% endif %}
// gulpfile.js
var gulp = require('gulp'),
gutil = require('gulp-util'),
coffee = require('gulp-coffee'),
livereload = require('gulp-livereload'),
debug = require('gulp-debug'),
watch = require('gulp-watch');
// other tasks definitions...
gulp.task('watch', function(){
livereload.listen(); // starts a tiny-lr server,
// default livereload server port is 35729
gulp.src('static/src/**/*.coffee')
.pipe(watch('static/src/**/*.coffee'))
.pipe(coffee())
.pipe(gulp.dest('static/dist'))
.pipe(livereload()); // send a signal to tiny-lr server
// to make the page with livereload.js
// to perform a reload action
})
I tried Frank Wile's answer, but I was having issues with it. The only way it worked for me with templates is if I saved a .py file and then made a change to a template.
I extended Frank's approach with a function that essentially touches a .py file before calling livereload.changed():
function touchPy() {
gulp.src(appName + '/__init__.py')
.pipe(gulp.dest(appName));
}
gulp.task('watch', function() {
livereload.listen();
// Changes to .css files works fine w/ Frank's approach
gulp.watch(paths.static).on('change', livereload.changed);
// Changes to .html files don't trigger a runserver refresh w/o touching a .py file
gulp.watch(paths.templates).on('change', function(file) {
touchPy();
livereload.changed(file);
});
});
You must include:
<script type="text/javascript" src="http://127.0.0.1:32700/livereload.js" />
to django main template. See http://argskwargs.io/blog/javascript/django-typescript-gulp-part-three/ . This is example for js and css files:
var gulp = require('gulp');
var watch = require('gulp-watch');
var livereload = require('gulp-livereload');
var gzip_options = {
threshold: '1kb',
gzipOptions: {
level: 9
}
};
gulp.task('css', function() {
return gulp.src('static/css/*.css')
.pipe(livereload());
});
gulp.task('js', function() {
return gulp.src('static/js/*.js')
.pipe(livereload());
});
/* Watch Files For Changes */
gulp.task('watch', function() {
livereload.listen(32700);
gulp.watch('static/css/*.css', ['css']);
gulp.watch('static/js/*.js', ['js']);
gulp.watch('static/css/*', 'static/js/*').on('change', livereload.changed);
});
gulp.task('default', ['css', 'js', 'watch']);
Related
I am trying to develop a blog application using react and django and for description section i choose django ckeditor.
when i upload a image using ck editor it's showing in adminpanel section no warnings because i double checked every path of django ckeditor . but those images are not displaying in the front end it's just showing a blank image field. but it's working on a simple html file not working with React . images are totally blank where i am missing ? if i do a quick F12 to check if the image is coming from backend or not . it is coming there but just not showing, Text is showing just not image
import React,{useState,useEffect} from 'react';
import {Link} from 'react-router-dom';
import axios from 'axios';
const BlogDetail =(props)=>{
const [blog,setBlog]=useState({});
useEffect(()=>{
const slug=props.match.params.id;
const fetchFata=async()=>{
try{
const res=await axios.get(`${process.env.REACT_APP_API_URL}/api/blog/${slug}`);
setBlog(res.data);
}
catch (err){
}
};
fetchFata();
},[props.match.params.id]);
const createBlog = () => {
return {__html: blog.content}
};
const capitalizeFirstLetter = (word) => {
if (word)
return word.charAt(0).toUpperCase() + word.slice(1);
return '';
};
return(
<div className='container'>
<h1 className="display-2">{blog.title}</h1>
<h2 className='text-muted mt-3'>Category: {capitalizeFirstLetter(blog.category)}</h2>
<h4>Last commit {blog.updated}</h4>
<div className='mt-5 mb-5' dangerouslySetInnerHTML={createBlog()}/>
<hr/>
<p className='lead mb-5'><Link to='/blog' className='font-weight-bold'>Back</Link></p>
</div>
);
};
export default BlogDetail;
I have an application in Electron JS that is calling a python function to execute a python script.
When the script executes it should send the data back to the Electron JS GUI and display it.
The issue I am having is that it is saying that join is undefined:
weather.js:9 Uncaught TypeError: Cannot read property 'join' of
undefined
at get_weather (weather.js:9)
at HTMLButtonElement.onclick (weather.html:14)
here is my JavaScript file:
let {PythonShell} = require('python-shell')
var path = require("path")
function get_weather() {
var city = document.getElementById("city").value
var options = {
scriptPath : path.join(__dirname, '/../engine/'),
args : [city]
}
let pyshell = new PythonShell('weatherApp.py', options);
pyshell.on('message', function(message) {
swal(message);
})
document.getElementById("city").value = "";
}
The line "scriptPath : path.join(__dirname, '/../engine/')," seems to be the offending piece of code.
My gui.html file is as follows:
<html>
<head>
<title></title>
<meta charset="UTF-8">
</head>
<body>
<h1>Get your local weather ...</h1>
<br>
<br>
<label>Enter city name here: <label>
<input id="city" type = "text" placeholder="City">
<button type = "button" value="clickme" onclick="get_weather()">Get Weather</button>
<!--- <button class="btn btn-success" onclick="get_weather();">Go!</button> -->
<br>
<br>
<br>
<script src="/home/ironmantis7x/Documents/BSSLLC/projects/node_electron/electronDemoApps/guiApp/gui/linkers/weather.js"></script>
<p><button type="button">Back to Main Page</button>
</body>
</html>
What error(s) do I need to fix to get this working correctly?
Thank you.
The Problem
Since Electron 5 nodeIntegration is disabled by default in the window. Since normal browser API does not know require or join, you get errors when you try.
Reenabling nodeIntegration
You could enable nodeIntegration again, but it was disabled for a reason. Be sure you read and understand the electron security tutorial.
Using a preload script
Another way is to use a preload script. Let's have a look at the BrowserWindow documentation.
When creating a new BrowserWindow you can add several options. For this case we need the webPreferences.preload option:
Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope.
Be aware that the preload script is run in the renderer process.
Example
Following is an example app, that opens a window with a button that uses the electron dialog to select files. This would not work with disabled nodeIntegration but thanks to our preload script, we reintroduced dialog.showOpenDialog() to our window.
main.js
const { app, BrowserWindow } = require("electron");
const { join } = require("path");
let win;
app.on("ready", () => {
win = new BrowserWindow({
webPreferences: {
//this is the default since electron 5
nodeIntegration: false,
//here you load your preload script
preload: join(__dirname, "preload.js")
}
});
win.loadURL(join(__dirname, "index.html"));
});
preload.js
const { dialog } = require("electron").remote;
window.mystuff = {
selectFile
};
async function selectFile() {
const files = await dialog.showOpenDialog({
properties: ["openFile", "multiSelections"]
});
return files;
}
index.html
<html>
<body>
<main>
<button onclick="myFunction()">select file</button>
<ul id="foo"></ul>
</main>
<script>
async function myFunction() {
//the function provided by the preload script
const files = await window.mystuff.selectFile();
const list = document.getElementById("foo");
for (const file of files) {
const node = document.createElement("LI");
const textNode = document.createTextNode(file);
node.appendChild(textNode);
list.appendChild(node);
}
}
</script>
</body>
</html>
Sending events via IPC
If you are unsure your functionality should be exposed in the window, you can also send events via ipcRenderer.
preload.js
const { ipcRenderer } = require("electron");
window.mystuff = {
selectFile
};
function selectFile() {
return new Promise(resolve => {
ipcRenderer.on("selected-files", (e, files) => {
resolve(files);
});
ipcRenderer.send("select-files");
});
}
Additional part in main.js
ipcMain.on("select-files", async () => {
const files = await dialog.showOpenDialog({
properties: ["openFile", "multiSelections"]
});
win.webContents.send("selected-files", files);
});
I am trying to upload a file to a cherrypy server, but without changing the displayed page.
A simple alert will be enough for my needs to tell the user that the upload is done.
I am trying this with a simple file input type and a button:
<div>
<label>Upload Sound:</label>
<input id="pathSound" style="width: 80%" type="file" accept=".mp3"/><br>
<button id="uploadSound">Upload</button>
</div>
and a script for the button click:
$("#uploadSound").click(function(e) {
if (document.getElementById("pathSound").value=='') {
alert("No file selected!");
e.preventDefault();
return;
}
var cardID = $('#tagID').html();
var file = document.getElementById("pathSound").files[0];
alert( "Tag: " + cardID + " File: " + file);
$.post("/uploadSound", {"cardID": cardID, "myFile": file})
.done(function(res) {
alert("File Saved!");
});
});
on the server side i have this function so far, but it is never called:
import os, os.path
import cherrypy
from cherrypy.process import plugins
class MagicBoxInterface(object):
#cherrypy.expose
def index(self):
return file('index.html')
#cherrypy.expose
def uploadSound(self, cardID='', myFile=None):
print 'uploadSound : ', cardID
print 'uploadSound : ', myFile
return ''
if __name__ == '__main__':
conf = {
'/': {
'tools.sessions.on': True,
'tools.staticdir.root': os.path.abspath(os.getcwd())
},
'/static': {
'tools.staticdir.on': True,
'tools.staticdir.dir': './public'
}
}
interface = MagicBoxInterface()
cherrypy.quickstart(interface, '/', conf)
All the examples i find use normal post and show a result page after the upload, but this is not what i want to do! The displayed page must not change.
On a side note, i don't need to consider large files, because it will only handle files below 1-2 MB.
I have found some examples using frames, but i am not that familiar with html/javascript to fully understand how i can apply those to my needs.
And help on a simple solution is greatly appreciated.
Ok do this...
$("#uploadSound").click(function(e) {
if (document.getElementById("pathSound").value=='') {
alert("No file selected!");
e.preventDefault();
return;
}
var cardID = $('#tagID').html();
var file = document.getElementById("pathSound").files[0];
alert( "Tag: " + cardID + " File: " + file);
$.post("/MagicBoxInterface/uploadSound", {"cardID": cardID, "myFile": file})
.done(function(res) {
alert("File Saved!");
});
});
You just need to include the class in your post request path.
hope this helps!
I'm writing a web crawler, but I only care about pages with responsive web design (RWD). Is there a tell-tale sign that the site is responsive? I am using the mechanize module in python.
The only thing I can think of is grepping the html for something like
href="css/bootstrap.min.css"
or
class="row-fluid"
or something that indicates percentages instead of pixels.
Any help would be appreciated.
My vote would be to search the page head for
<meta name="viewport" content="width=device-width, initial-scale=1.0" *** wildcard-selector-here *** >
I think it would be easier and more acurate than searching for the presence of CSS media queries.
Good luck!
I had a project where I needed to make the website responsive without touching any html markup and no programming code, the only thing I could modify was a stylesheet and a javascript file. I didn't even know which were all the pages of the website because it was a new project to me.
So the goal was to make it responsive so Google crawler won't penalize the site.
So I knew I could use https://www.google.com/webmasters/tools/mobile-friendly/ manually for the pages I wanted to test. But how could I test the whole site?
Well what I've done is to ask for a Webmaster Tools export of the most important links of the site, hundreds of them.
Then I've built a small "tool" that would do exactly what I think Google Responsive Test does, but this tool would accept a list of urls and would loop and test each of them if they fit on a 320px screen (iframe).
This is the HTML tool that you just open, type the urls in a text box, and hit Start! (responsiveChecker.html)
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>Responsive Checker</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://www.google.com/jsapi"></script>
<script>
var urls;
var delay=3000;
google.load("jquery", "1");
google.setOnLoadCallback(function() {
// Place init code here instead of $(document).ready()
console.log('jquery loaded');
$('#responsiveFrame').load(function(){
if (urls.length > 0) {
setTimeout(function(){ checkUrl(); }, delay);
}
});
});
function startChecking() {
var textUrls=$('#urls').val();
urls= textUrls.match(/[^\r\n]+/g);
checkUrl();
}
function checkUrl() {
var url;
if (urls.length > 0) {
url=urls[0];
console.log("checking: "+url);
$('#responsiveFrame').attr('src',url+'#rc=1');
urls.splice(0, 1);
} else {
console.log("no more urls");
}
}
</script>
</head>
<body>
<iframe id="responsiveFrame" width="320" height="480" src="about:blank" style="border: 1px solid red;" scrolling="no"></iframe>
<p>
<label for="urls">Enter URLs to check, one per line:</label><br />
<textarea id="urls" rows="30" cols="100"></textarea>
</p>
<p>
<input type="button" value="Start checking!" onclick="startChecking();">
</p>
</body>
</html>
This a script that must be loaded and run on the website you want to check:
var responsiveChecker = new function () {
this.width = 320;
this.hashParams={};
this.check = function () {
this.hashParams=this.parseHashBangArgs();
// this.log('responsiveChecker');
// this.log(this.hashParams);
if (!this.mustCheck()) {
return;
} else {
this.updateParams();
this.log('must check!');
var that = this;
var counter=0;
var visibleCounter=0;
jQuery("*").each(function() {
if (jQuery(this).width() > that.width) {
if ('SCRIPT' === this.tagName) {
// ignore script tags
} else {
that.log(this.tagName + "#" + this.id);
counter++;
if (jQuery(this).is(":visible")) {
visibleCounter++;
that.log(this.tagName + "#" + this.id);
}
}
}
});
var page=window.location.href;
if (visibleCounter > 0) {
this.log('[ERROR] page not responsive, there are elements bigger than screen size: '+page);
} else {
if (counter > 0) {
this.log('[WARNING] hey check the above list, there are some hidden elements with size bigger than the screen: '+page);
} else {
this.log('[SUCCESS] ¡todo bien! looks like all elements fit on the screen: '+page);
}
}
}
};
this.updateParams = function () {
if (typeof(this.hashParams.width) !== 'undefined') {
this.width=parseInt(this.hashParams.width);
}
};
this.mustCheck = function () {
if (typeof(this.hashParams.rc) !== 'undefined') {
return true;
}
return false;
};
// https://gist.github.com/miohtama/1570295
this.parseHashBangArgs = function() {
var aURL = window.location.href;
var vars = {};
var hashes = aURL.slice(aURL.indexOf('#') + 1).split('&');
for(var i = 0; i < hashes.length; i++) {
var hash = hashes[i].split('=');
if(hash.length > 1) {
vars[hash[0]] = hash[1];
} else {
vars[hash[0]] = null;
}
}
return vars;
};
this.log = function (msg) {
console.log(msg);
};
};
Place this at the end of a jquery ready:
responsiveChecker.check();
So finally how does it work:
You add the responsiveChecker javascripts on the website you want to check
You open the responsiveChecker.html file, add the urls of the site in the textarea and hit Start
It will start to load the urls in the iframe one by one, and on the Console tab of your browser it will log a "success", "warning" or "error", that means that either it is responsive, or maybe, or not responsive.
Let me know what you think!
By the way, does anybody think this could be useful if we clean it and build a real live tool/service that people could use to test their websites for responsiveness?
Oh btw: The actual checking is done with jQuery, by testing all the elements of the page that have a width smaller or equal to 320px. Indeed this is not 100% guarantee but I think Google's bot might be doing something like this but I'm sure it is more sophisticated.
I have an app made in Python, which accesses a Linux server's command prompt with os.system([string])
Now I'd like to transfer this away from Python, into some language like ASP.NET or something.
Is there a way to access the server's command prompt and run commands with ASP.NET or any technology found in Visual Studio?
This needs to run in a web app, where a user will click a button, and then a server-side command will run, so it's important that the technology suggested is compatible with all that.
Well it isn't ASP.net specific but in c#:
using System.Diagnostics;
Process.Start([string]);
Or With more access to the specific parts of running a program (like arguments, and output streams)
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c dir *.cs";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
here is how you could combine this with an ASPx Page:
First Process.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Process.aspx.cs" Inherits="com.gnld.web.promote.Process" %>
<!DOCTYPE html>
<html>
<head>
<title>Test Process</title>
<style>
textarea { width: 100%; height: 600px }
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:Button ID="RunCommand" runat="server" Text="Run Dir" onclick="RunCommand_Click" />
<h1>Output</h1>
<asp:TextBox ID="CommandOutput" runat="server" ReadOnly="true" TextMode="MultiLine" />
</form>
</body>
</html>
Then the code behind:
using System;
namespace com.gnld.web.promote
{
public partial class Process : System.Web.UI.Page
{
protected void RunCommand_Click(object sender, EventArgs e)
{
using (var cmd = new System.Diagnostics.Process()
{
StartInfo = new System.Diagnostics.ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = "/c dir *.*",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true
}
})
{
cmd.Start();
CommandOutput.Text = cmd.StandardOutput.ReadToEnd();
};
}
}
}