So I'm using Django framework to display the console output to the HTML. To execute the command, I'm using the check_output of subprocess module in Python. Which receives the input from the HTML input form. The problem is that I only see "None" on the HTML page, which is the default value of output in views file.
Below is the code of the views file and HTML file. I'm a novice in this so I'd appreciate your assistance.
Views.py
from django.shortcuts import render
from django.shortcuts import redirect
from .forms import command_form
import subprocess as sp
# Create your views here.
def welcome_page(request):
output=""
if request.method == "POST":
myform = command_form(request.POST)
if (myform.is_valid()):
execute_command = myform.cleaned_data['cmd_string']
output = sp.check_output(execute_command, shell=True)
else:
myform = command_form()
return render(request, 'ovs/welcome.html', {'output': output})
else:
return render(request, 'ovs/welcome.html', {})
welcome.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>welcome to ovs GUI</title>
</head>
<body>
<h3>Choose the option:</h3>
<form method="POST">{% csrf_token %}
Enter the command: <input type="text" name="cmd_string" id="cmd_string"/>
<input type="submit" value="Run"/>
</form>
<h3>{{ output }}</h3>
</body>
</html>
forms
from django import forms
class command_form(forms.Form):
command = forms.CharField(max_length=200)
You are not rendering the form field correctly to your HTML. You have created a command_form form and you never exploit it. However, you should use camel case name for python classes, like this CommandForm.
Inside your HTML, write this:
<form method="POST">{% csrf_token %}
Enter the command: {{ myform }}
<input type="submit" name="submit_cmd" value="Run" />
</form>
{% if output %}<h3>{{ output }}</h3>{% endif %}
{% if exit_code %}<h3>Your command returned an error: {{ error_msg }}</h3>{% endif %}
{{ my_form }} will expand, automatically, to <input type="text" ...>
Now, write your welcome_page view like this:
def welcome_page(request):
output = ""
# Initialize the form. At this point you have an unbound/invalid form
myform = command_form() # better write it as CommandForm
if request.method == "POST":
myform = command_form(request.POST)
if myform.is_valid():
# execute_command variable, should now contain the command typed by the user in the text box
execute_command = myform.cleaned_data['command']
try:
# If the return code is non-zero, CalledProcessError will be raised
output = sp.check_output(execute_command, shell=True)
except sp.CalledProcessError:
exit_code, error_msg = output.returncode, output.output
else:
# Do something when the form is not valid. Maybe add a message or something, or not implement else clause at all.
return render(request, 'ovs/welcome.html', locals())
Warning! As per the docs say:
Using shell=True can be a security hazard.
You can use REST framework to return a Response so you don't have to worry about handling it in HTML. Just install the rest_framework and do this:
from rest_framework.response import Response
return Response(data)
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from test.forms import CommadForm
import subprocess as sp
def welcome_page(request):
if request.method == "POST":
myform = CommadForm(request.POST)
if myform.is_valid():
execute_command = myform.cleaned_data['command']
try:
output = sp.check_output(execute_command, shell=True)
except sp.CalledProcessError:
output = 'No such command'
else:
myform = CommadForm()
return render(request, 'ovs/welcome.html', {'output': output})
else:
return render(request, 'ovs/welcome.html')
forms.py
class CommadForm(forms.Form):
command = forms.CharField(max_length=200)
Related
I am not sure if I am going about this correctly, but I am not getting any errors it just reloads the page without displaying anything.
The issue could be with me trying to format the api string and input the users input there?
I also tried returning the variable as an HttpResponse, still made no difference.
Sorry just getting back into python, and just starting with Django.
Correct code should go something like this:
1.User inputs their name into the form
2. Page then displays the usersid.
Code:
views.py:
from urllib import response
from django.shortcuts import render
from django.http import HttpResponse
import requests
from .forms import SearchUser
import json
# Create your views here.
def home(response):
# data = requests.get(
# 'https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/ReallyBlue/NA1?api_key=RGAPI-6c5d9a2c-3341-4b0c-a0a5-7eafe46e54cf')
# userid = data.json()['puuid']
return render(response, "main/home.html", {
'form': SearchUser(), # include reference to your form
'userid': search,
# 'mmr':NA,
})
def search(response):
if response.method == "POST":
form = SearchUser(response.POST)
if form.is_valid():
n = form.cleaned_data["name"]
user = n(name=n)
user.save()
data = requests.get(
f"https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/'{user}'/NA1?api_key=RGAPI-6c5d9a2c-3341-4b0c-a0a5-7eafe46e54cf")
userid = data.json()['puuid']
return HttpResponse(userid)
else:
form = SearchUser()
return render(response, "main/home.html", {"userid": userid})
forms.py:
from django import forms
class SearchUser(forms.Form):
name = forms.CharField(label="Name", max_length=200)
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("", views.home, name=""),
path("", views.search, name=""),
]
home.html:
{% extends 'main/base.html'%}
{% block content %}
<h2>Valorant Ranked Checker</h2>
<form method="post" action="">
{% csrf_token %}
{{form}}
<button type="submit" name="search">
Get rank
</button>
</form>
<p><strong>{{userid}} - {{mmr}}</strong></p>
{% endblock %}
base.html:
<!DOCTYPE html>
<head>
<title>Blue's Valorant Ranked Checker</title>
</head>
<body>
<div id="content" name="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
So what you have to do is, use a single view for the url and then do the API querying inside that view. So something like:
urlpatterns = [
path("", views.search, name=""),
]
and then inside your view, you need to send the form with the context dictionary to show it in the HTML.
def search(response):
if response.method == "POST":
form = SearchUser(response.POST)
if form.is_valid():
name = form.cleaned_data["name"]
data = requests.get(
f"https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/{user}/NA1?api_key=*******")
userid = data.json()['puuid']
return HttpResponse(userid) # Or preferably pass onto a different view
else:
return HttpResponse("Form is not properly filled")
else:
form = SearchUser()
return render(response, "main/home.html", {"form": form})
I am writing a webpage that can run a python script by clicking a button on html. Here is what I have:
views.py
from django.shortcuts import render
import requests
import sys
from subprocess import run,PIPE
def external(request):
inp= request.POST.get('param')
out= run([sys.executable,'test.py',inp],shell=False,stdout=PIPE)
print(out)
return render(request,'home.html',{'data1':out.stdout})
urls.py
from django.urls import path
from . import views
# urlconf
urlpatterns = [
path('external/', views.external)
]
home.html
<html>
<head>
<title>
Python button script
</title>
</head>
<body>
<form action="/external/" method="post">
{% csrf_token %}
Input Text:
<input type="text" name="param" required><br><br>
{{data_external}}<br><br>
{{data1}}
<br><br>
<input type="submit" value="Execute External Python Script">
</form>
</body>
</html>
directory screenshot
The problem is with this line of code: out= run([sys.executable,'test.py',inp],shell=False,stdout=PIPE) from views.py. How can I fix this? Thanks!
You are probably using this view(external) for both the POST method and the GET method, and you do not have data in the get method, so you get an error.
try this:
def external(request):
if request.method == "POST":
inp= request.POST.get('param')
out= run([sys.executable,'test.py',inp],shell=False,stdout=PIPE)
print(out)
return render(request,'home.html',{'data1':out.stdout})
else:
return render(request,'home.html')
I need to get data from input and write it to query variable. When I click to search button I need write data in query variable. How can I do that? I mean click event and write data in query.
This is my code:
views.py:
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
if request.method == 'GET':
return render(request, 'index.html', context={})
# Handles the search once the submit button in the form is pressed
# which sends a "POST" request
if request.method == 'POST':
# Get the input data from the POST request
search_query = request.POST.get('search', None)
# Validate input data
if search_query and search_query != "":
try:
from googlesearch import search
except ImportError:
print("No module named 'google' found")
for j in search(search_query, tld="co.in", num=10, stop=1, pause=2):
print(j)
else:
return HttpResponse('Invalid input.')
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<form method="POST">
{% csrf_token %}
<input type="text" name="search" placeholder="some text"><br>
<button class="button" name="submit" type="submit">Search</button>
</form>
</body>
</html>
urls.py
from django.urls import path
from firstapp import views
urlpatterns = [
path('', views.index, name='home')
]
All files are in hello folder. My app namely firstapp path: C:\Users\user\Desktop\hello\firstapp
index.html path is:
C:\Users\user\Desktop\hello\firstapp\templates
We will need to change the index() function to handle POST or GET methods (refer to https://www.w3schools.com/tags/ref_httpmethods.asp for more information on GET and POST requests), by default django always listens to a GET request. You can know whether or not a method is GET by using request.method == 'GET' and request.method == 'POST' for POST.
To access the data inside the method, use request.POST.get("search", None), which basically says find the input with the name attribute from the form or if the input does not exist, return None.
So, all in all, your code should now look like this
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
if request.method == 'GET':
return render(request, 'home/home.html', context={})
# Handles the search once the submit button in the form is pressed
# which sends a "POST" request
if request.method == 'POST':
# Get the input data from the POST request
search_query = request.POST.get('search', None)
# Validate input data
if search_query and search_query != "":
# Implement search functionality....
# ...
return HttpResponse(search_query)
else:
print("Invalid input")
return render(request, 'home/home.html', context={})
Now inside the app, make a folder named templates and add index.html
The index.html file should look like (to learn more about templates refer to: https://docs.djangoproject.com/en/2.2/topics/templates/):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="POST">
{% csrf_token %}
<input type="text" name="search" placeholder="some text"><br>
<button class="button" name="submit" type="submit">Search</button>
</form>
</body>
</html>
my_app/templates/index.html
Also, if you look at the <form> tag, you can find a method tag which says POST. This indicates whether the data that is being submitted is a POST request.
A little description of what i m trying to do.
I want to make a User Interface (web/HTML) through which i can send the commands to router and display the result on the Webpage/HTML.
Here's the code i m using:-
Views.py
from django.shortcuts import render
from first_app.forms import CmdForm
from django.http import HttpResponse
def index(request):
my_dict = {'insert_me': ""}
return render(request,'first_app/index.html',context=my_dict)
def form_name_view(request):
if request.method == "POST":
form = CmdForm(request.POST)
if form.is_valid():
from netmiko import ConnectHandler
devices = {
'device_type':'cisco_ios',
'ip':'192.168.50.145',
'username':'me',
'password':'12345',
'secret':'12345',
'port':'22'
}
cmd = request.POST.get('command', '')
netconnect = ConnectHandler(**devices)
#print("connection established with", devices['ip'])
output = netconnect.send_command(cmd)
return render(request,'first_app/forms.html', {'form': form,
'output':output})
else:
form = CmdForm()
return render(request,'first_app/forms.html', {'form': form})
forms.py
from django import forms
class CmdForm(forms.Form):
command = forms.CharField(label='Command to execute')
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from first_app import views
urlpatterns = [
path('Automation_page/', views.form_name_view,name='IP form'),
path('admin/', admin.site.urls),
path('', views.index,name='first'),
path('first_app/',include('first_app.urls')),
]
forms.html
<!DOCTYPE html>
{% load staticfiles %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>FORMS</title>
</head>
<body>
<h1> IP address form </h1>
<p>Run command:</p>
<form method="POST"> {% csrf_token %}
{{ form }}
<input type="submit" value="Run command!" />
</form><br>
{% if request.POST %}
<p>Command output:</p>
<pre>{{ output }}</pre>
{% endif %}
</body>
</html>
i am getting the error when i visit the Automation_page/
ValueError at /Automation_page/
The view first_app.views.form_name_view didn't return an HttpResponse object. It returned None instead.
Request Method: GET
Request URL: http://127.0.0.1:8000/Automation_page/
Django Version: 2.2.3
Exception Type: ValueError
Exception Value:
The view first_app.views.form_name_view didn't return an HttpResponse object. It returned None instead.
Exception Location: K:\Work\DevNet\ENV1\lib\site-packages\django\core\handlers\base.py in _get_response, line 126
Python Executable: K:\Work\DevNet\ENV1\Scripts\python.exe
Python Version: 3.7.3
Python Path:
['K:\Work\DevNet\first_project',
'K:\Work\DevNet\ENV1\Scripts\python37.zip',
'K:\Work\DevNet\ENV1\DLLs',
'K:\Work\DevNet\ENV1\lib',
'K:\Work\DevNet\ENV1\Scripts',
'c:\users\karti\appdata\local\programs\python\python37-32\Lib',
'c:\users\karti\appdata\local\programs\python\python37-32\DLLs',
'K:\Work\DevNet\ENV1',
'K:\Work\DevNet\ENV1\lib\site-packages']
Need help on this.
thanku who are willing to help
The last line needs to be moved one indent to the left, so it is hit if the form is invalid.
else:
form = CmdForm()
return render(request,'first_app/forms.html', {'form': form})
I was able to figure out the solution of my problem.
sharing it for others if they can relate. :-)
In views.py
Add the following code, with indent to first if statement.
else:
return render(request,'first_app/forms.html', {})
The example in https://docs.djangoproject.com/en/1.6/topics/forms/ demonstrates usage of form and has the following code:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render(request, 'contact.html', {'form': form,})
and contact.html template is
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I am wondering if it's possible in render(request,...,{'form':form,}) instead of specifying template file contact.html to pass variable with the contents of template, something like this:
html = """
<html>
<head> bla bla bla</head>
<body>
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</body>
"""
return render(request, html, {'form': form,})
If it's possible what could be the drawbacks and risks associated with such approach?
Thanks in advance!
Not with render, which is a shortcut for loading a template, rendering it and returning a response. But you can do it with separate calls:
from django.template import RequestContext, Template
tpl = Template(html)
rendered = tpl.render(RequestContext(request, {'form': form}))
return HttpResponse(rendered)
The main drawback is that you're mixing the HTML in the python file, which makes it hard to read. Buy you could use this technique to load templates from the database or an api, for example.