I want something to be executed through django - python

I know this question was asked before, but none worked for me. I have this code that I want it to be executed when a button is clicked and a message is passed
import time
from sinchsms import SinchSMS
number = '+yourmobilenumber'
message = 'I love SMS!'
client = SinchSMS(your_app_key, your_app_secret)
print("Sending '%s' to %s" % (message, number))
response = client.send_message(number, message)
message_id = response['messageId']
response = client.check_status(message_id)
while response['status'] != 'Successful':
print(response['status'])
time.sleep(1)
response = client.check_status(message_id)
print(response['status'])
Basically, what I need is to add an input in a template "HTML File", this input get passed to the message variable in the code above, same with the number. I can easily do that with instances, but how can the below get executed when a button is clicked from the form in the template?
I'm kinda newbie in Django and still finding my way
Here is the tutorial that explains how to make the python file, but execute it from the shell, not a django application.
I hope I was clear describing my problem and any help would be appreciated!

All you need is a form with a message field. In a view, you want to show that form and when the user press submit, you want to execute your script.
Here is some pseudo-code:
urls.py
url('^my-page/' my_views.my_view, name='my-page'),
forms.py
SmsForm(forms.Form):
message = fields.CharField(...)
my_views.py
def my_view(request):
form = SmsForm(data=request.POST or None)
if request.method == 'POST':
if form.is_valid():
send_sms(form.cleaned_data['message']) # do this last
messages.success(request, "Success")
return HttpResponseRedirect(request.path)
else:
messages.warning(request, "Failure")
return render(request, 'my_template.html', {'form': form})
Check the Django documentation about urls, views, forms and messages and proceed step by step:
get the page to load
get the form to load
get the form submission to work and simply show "Success" or "Failure"
finally, write the send_sms function (you've almost done it)

Lets start from the dust cloud.
What you are asking is mostly about how the web pages work. You need to know how to pass parameters using HTML. There are lots of ways to do it. But with django there is a pattern.
You need a url, and a view to catch any requests. Then you need to create a template and a form inside it. With this form you could create some requests to send data to your view.
To create you need to edit urls.py inside your project add an url:
urls.py
from django.conf.urls import url
from my_app.views import my_view
urlpatterns = [
...
url(r'^my_url$', my_view, name='my_view')
...
]
For more about urls please look at URL dispatcher page at documentation.
Then create your view inside your app which is my_app in my example. Edit my_app/views.py
my_app/views.py
from django.http import HttpResponse
def my_view(request):
return HttpResponse('IT WORKS!')
This way you get a working view which could be accessed with path /my_url. If you run ./manage.py runserver you could access your view from http://localhost:8000/my_url.
To create a form you need to create a template. By default django searches app directories for templates. Create a templates directory in your app, in our case my_app/templates and create an HTML file inside. For example my_app/templates/my_form.html. But i advice to create one more directory inside templates directory. my_app/templates/my_app/my_form.html. This will prevent template conflicts. You can check Templates page at documentation for more.
my_app/templates/my_app/my_form.html
<html>
<body>
<form action="/my_url" method="POST">
{% csrf_token %}
<input type="text" name="number">
<input type="text" name="message">
<input type="submit" value="Run My Code">
</form>
</body>
</html>
This is the one of the ways of creating your form. But I do not recommend it. I will make it prettier. But first lets "Make it work", edit your views.py:
csrf_token is a django builtin template tag, to put CSRF token into your form. By default django requires CSRF tokens at every post
request.
my_app/views.py
from django.http import HttpResponse
from django.shortcuts import render
def my_view(request):
if request.method == 'GET':
return render('my_app/my_form.html')
elif request.method == 'POST':
# get post parameters or None as default value
number = request.POST.get('number', None)
message = request.POST.get('message', None)
# check if parameters are None or not
if number is None or message is None:
return HttpResponse('Number and Message should be passed')
# your code goes here
...
return HttpResponse('Your code result')
Till this point the purpose of this answer was "Making it work". Lets convert it nice and clean. First of all we would create Form. Forms are like models, which helps you create forms as objects. It also handles form validations. Forms are saved inside forms directory generally. Create my_app/forms.py and edit it:
my_app/forms.py
from django import forms
class MyForm(forms.Form):
number = forms.CharField(max_length=15, required=True)
message = forms.CharField(max_length=160, required=True)
Put your form inside your template:
my_app/templates/my_app/my_form.html
<html>
<body>
<form action="{% url 'my_view' %}" method="POST">
{% csrf_token %}
{{ form }}
</form>
</body>
</html>
Besides the form, the action of the HTML form tag is also changed.
url template tag is used to get url form url name specified in urls.py.
Instead of url tag, {{ request.path }} could have been used.
Create a form instance and pass it to the template rendering:
my_app/views.py
from django.http import HttpResponse
from django.shortcuts import render
from .forms import MyForm
def my_view(request):
if request.method == 'GET':
form = MyForm()
return render('my_app/my_form.html', {'form': form})
elif request.method == 'POST':
form = MyForm(request.POST)
# check if for is not valid
if not form.is_valid():
# return same template with the form
# form will show errors on it.
return render('my_app/my_form.html', {'form': form})
# your code goes here
...
return HttpResponse('Your code result')
You can use class based vies to write your view, but it's not necessary. I hope it helps.

You can create a view that takes up query parameters from the url and use it for further implementation. Then you can create a link/button in the html template which can redirect you to that url. For example:
in urls.py:
url(r'^run_a/(?P<msg>\w{0,25})/(?P<num>\w{0,25})/$', yourcode, name='get_msg'),
in template:
submit
in views.py:
def get_msg(request,msg,num):
message=msg
number=num
#rest of the code
Hope this helps :)

Related

How to execute script python when i click button in form html?

hello how can i run script that i build on python when i click button on form html
i saw examples like this but i dont get it:
Html code: index.html
<form action="{% url my_view %}" method="post">
<input type="submit" value="Ok">
</form>
views.py
import django.shortcuts import render
def my_view(request):
if request.method == 'POST':
import set_gpio
#my url is "templates/load.py"
return #How can i return?
You need to return an HttpResponse object from your view. You can return one response inside your if statement, and another outside of it (so anything but a POST). Usually the render shortcut is used to render a response from a template. So your view would be something like:
import django.shortcuts import render
def my_view(request):
if request.method == 'POST':
# The user clicked the button (POST)
return render(request, "load.html")
# The user is just loading the view for the first time (GET)
return render(request, "index.html")
I highly suggest going through the django tutorial.
You have to realise that Django is a HTTP based framework meaning that when an HTTP request is sent to a url, Django will be allowed to perform an action. So, every function is actually a reaction to the HTTP requests that the user sends to your urls.
Also, if you are using Django template system, the html file should be rendered by Django in the first place. So, you cannot have a standalone html file with {% url my_view %} in it.
First, you have to configure the main urls.py which is in a folder with the same name as your project.
Second, in your app, create an urls.py file and configure it.
At the end, you connect your my_view to a specific or set of urls and will be triggered when a request is sent to that url, whether GET or POST.
These are somewhat large (and easy) topics for which you have to watch a tutorial or read the Django documentations.

DJANGO - Redirect to different page from POST with data

I am trying to have a simple form that once filled, will direct to a different webpage or remain on the same page if invalid. The page should have a text box and submit form and once a user enters anything it should direct you to a separate page.
My directory structure is as follows:
appName/
app/
forms.py
urls.py
views.py
templates/
app/
goodbye.html
name.html
library.html
thanks.html
appName/
settings.py
urls.py
My app/urls.py is as follows:
from django.conf.urls import url
from . import views
app_name = 'app'
urlpatterns = [
url(r'^$', views.index2, name = 'index'),
url(r'^hello/$', views.hello, name = 'hello'),
url(r'^goodbye/$', views.goodbye, name = 'goodbye'),
#url(r'^library$', views.library, name = 'library'),
url(r'^library/$', views.library, name = 'library'),
url(r'^library/(?P<book_id>[0-9]+)/$', views.book, name = 'book'),
url(r'^getname/$', views.get_name, name = 'get_name'),
url(r'^your-name/$',views.get_name, name='get_name'),
url(r'^thanks/$',views.say_thanks,name='thanks'),
#url(r'^thanks/(?P<name_id>[a-zA-Z]+)/$', views.say_thanks,name='thanks'),
]
My forms.py is :
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label = 'Your name', max_length=100)
My app/views.py is:
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.http import HttpResponseRedirect
#forms
from .forms import NameForm
# Create your views here.
def index2(request):
return HttpResponse("hello world")
def hello(request):
text = """<h1>Welcome to my app! </h1>"""
return HttpResponse(text)
def goodbye(request):
template = loader.get_template("app/goodbye.html")
context = {
'output' : 'This is output from goodby views.py request handler'
}
return HttpResponse(template.render(context,request))
def library(request):
template = loader.get_template("app/library.html")
context = {
'output' : 'Welcome to the libary!!'
}
return HttpResponse(template.render(context, request))
def book(request, book_id):
return HttpResponse("You're looking at book %s. " % book_id)
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
#process the data in form.cleaned_data as required
locationGo = "/thanks/"
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name':'name'},request))
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
def say_thanks(request):
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name': 'name'},request))
My templates include:
name.html :
<form action = "/getname/" method = "post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit" />
</form>
goodbye.html
<h1>Goodbye to Template Romance</h1>
Go Back
thanks.html
Thanks {{name}}!
What I would like is for:
A user to visit to : website.com/getname/ to show the name.html file (which it does)
If a user hits submit to stay on the same page (website.com/getname/) (which it doesn't - it gives: ValueError at /getname/ ->The view app.views.get_name didn't return an HttpResponse object. It returned None instead.
If a user enters in the submit field, to be redirected to website.com/thanks/ (which it sort of does. It currently loads the thanks.html template, but the URL stays on website.com/getname/)
Inside the get_name(request): function, the POST and GET if...else doesn't seem to be firing based on the Submit button, and it doesn't seem to be loading the correct page, OR change the current URL address once it gets processed. I have tried using HttpRedirect() which works, however, I would also like to pass the forms data (which is another issue).
Any suggestions would be a big help!
Your first problem is that you are not returning a response when the request method is post and the form is invalid. You can fix that by changing the indentation of your view, so that you always return a response at the end of your view.
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
...
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
If you want to redirect to the /thanks/ view, then you can use the redirect shortcut.
if form.is_valid():
return redirect('thanks')
Note that it isn't possible to redirect and pass the form data (see this question for an explanation). You should do any processing you want with the data before redirecting. You could use the messages framework to create a message 'Thanks <name>' before redirecting.
This works because you have name='thanks' in your url pattern.
You can simplify your views by using the render shortcut. Instead of
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
you can simply do:
return render(request, "app/name.html", context)
Remember to add the imports for the shortcuts:
from django.shortcuts import redirect, render

Do we need CSRF verification for every POST request?

I am just building a simple HTML form with POST method and unfortunately I am finding CSRF verification error.
This is just a simple html form using POST method on localhost. There are no cross sites involved. I could definitely fix it by using csrf_token but I still don't understand why django is asking me for that..
There are no re-directions/ iframes involved here...
So, why this is happening?? is this normal to all ??
# Also tried using RequestContext(request) but there isn't any change in the error
#settings.py
'django.middleware.csrf.CsrfViewMiddleware' in MIDDLEWARE_CLASSES
#views.py
# url for home page is "" i.e, http://127.0.0.1:8000/
def HomePage (request):
if request.method == "POST":
form = myForm(request.POST)
if form.is_valid():
data = form.cleaned_data
context = { "myForm" : myForm(choices),
"values" : data,
}
return render_to_response("home.html", context)
else:
form = myForm(choices)
context = {"myForm" : form}
return render_to_response("home.html", context)
# home.html
<div id="pingmeeForm">
<form action="" method="post">
<table>
{{myForm.as_table}}
</table>
<input name="enter" type="submit" value="enter"/>
</form>
{{values}}
</div>
# forms.py
class myForm (forms.Form):
def __init__(self, my_choices,*args, **kwargs):
super(myForm, self).__init__(*args, **kwargs)
self.fields['Friends'] = forms.ChoiceField(choices=my_choices)
message = forms.CharField()
If you do a post request, you typically change the state of the server. If you change the state of the server, you don't want to allow other sites to do so. To protect against other sites issueing post-requests on your server, you add csrf protection. Therefore the solution should (imho) never be to remove the Csrf protection. Depending on the situation, either of the following two is the case:
Your post request does not change the state. In that case, make it a get request.
Your post request changes the state. You need CSRF.
The error message you got but didn't show explains exactly what you are doing wrong: you should ensure that
the view function uses RequestContext
for the template, instead of Context.

How do I confirm a form has been submitted with django?

I'm submitting a form and instead of redirecting to a success url I would like to just show "Form has been submitted" in text on the page when the form has been submitted. Does anyone know how I can do so?
In your view:
if request.POST:
# validate form, do what you need
if form_is_valid():
message = 'Form has been submitted'
return render_to_response('path/to/template.html', {'message': message})
And then use code in your template like:
{% if message %}
<h4>{{ message }}</h4>
{% endif %}
Honestly, this isn't a Django-specific issue. The problem is whether you are doing a normal form submission or using AJAX.
The basic idea is to POST to your form submission endpoint using AJAX and the form data, and in the Django view, merely update your models and return either an empty 200 response or some data (in XML, JSON, small HTML, whatever you need). Then the AJAX call can populate a success message div on success, or display a failure message if it gets back a non-200 response.
Modify your view to return an HttpResponse object with the text you want as its parameter, after you have validated the request. See the example below.
from django.http import HttpResponse
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
# Process the data in form.cleaned_data
# ...
return HttpResponse('Form has been submitted.')

POSTing forms in Django's admin interface

I'm writing a Django admin action to mass e-mail contacts. The action is defined as follows:
def email_selected(self,request,queryset):
rep_list = []
for each in queryset:
reps = CorporatePerson.objects.filter(company_id = Company.objects.get(name=each.name))
contact_reps = reps.filter(is_contact=True)
for rep in contact_reps:
rep_list.append(rep)
return email_form(request,queryset,rep_list)
email_form exists as a view and fills a template with this code:
def email_form(request,queryset,rep_list):
if request.method == 'POST':
form = EmailForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get('email','noreply#localboast'),['redacted#email.com'],
)
return HttpResponseRedirect('thanks')
else:
form = EmailForm()
return render_to_response('corpware/admin/email-form.html',{'form':form,})
and the template exists as follows:
<body>
<form action="/process_mail/" method="post">
<table>
{{ form.as_table }}
</table>
<input type = "submit" value = "Submit">
</form>
</body>
/process_mail/ is hardlinked to another view in urls.py - which is a problem. I'd really like it so that I don't have to use <form action="/process_mail/" method="post"> but unfortunately I can't seem to POST the user inputs to the view handler without the admin interface for the model being reloaded in it's place (When I hit the submit button with , the administration interface appears, which I don't want.)
Is there a way that I could make the form POST to itself (<form action="" method="post">) so that I can handle inputs received in email_form? Trying to handle inputs with extraneous URLs and unneeded functions bothers me, as I'm hardcoding URLs to work with the code.
You can use django's inbuilt url tag to avoid hardcoding links. see...
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#url
Chances are you'd be better off setting up a mass mailer to be triggered off by a cron job rather than on the post.
Check out the answer I posted here
Django scheduled jobs
Also if you insist on triggering the email_send function on a view update perhaps look at
http://docs.djangoproject.com/en/dev/topics/signals/

Categories