I'm trying to learn to use Python to create dynamic web content. Problem I'm having right out the door, though, is that when I try to do a mySQL query, absolutely nothing happens. There's no error message... it looks like the script simply stops running when I import the module that enables connection to the database.
This does do exactly what I'd expect when I try to run it from the command line.
#!/usr/bin/python
print "Content-Type: text/xml"
print
#if I type, for example, print "<b>test</b>" here, it appears in the browser window
#msql contains the credentials for connecting to database
#it is NOT in public_html
import msql
#no print instructions after this point are followed
connex=msql.msqlConn()
db=msql.MySQLdb
cursor=connex.cursor(db.cursors.DictCursor)
cursor.execute("SELECT * FROM userActions")
#run the query
xmlOutput=""
rows=cursor.fetchall()
#output the results
for row in rows:
xmlOutput+="<action>"
xmlOutput+="<actionId>"+str(row["actionId"])+"</actionId>"
xmlOutput+="<userId>"+str(row["userId"])+"</userId>"
xmlOutput+="<actText>"+str(row["action"])+"</actText>"
xmlOutput+="<date>"+str(row["dateStamp"])+"</date>"
xmlOutput+="</action>"
xmlOutput="<list>"+xmlOutput+"</list>"
print xmlOutput
This would be my first stab at this, so it merely stands to reason that this should work. I've found nothing online that would suggest otherwise, though.
Please, take 24h to learn something like Django. Django has an ORM and a XML serializer that will make your life easier ensuring proper (and legal) xml, it really pays up.
You can enable cgi traceback to see what happens:
import cgitb
cgitb.enable()
(I don't think it causes your problem, and clients understand \n as well but it is better to use sys.write("...\r\n") instead of print to print HTTP headers)
Edited: try to add Content-length: XXXX\r\n to the header.
Related
EDIT:
In a similar vein, when I now try to log into their account with a post request, what is returned is none of the errors they suggest on their site, but is in fact a "JSON exception". Is there any way to debug this, or is an error code 500 completely impossible to deal with?
I'm well aware this question has been asked before. Sadly, when trying the proposed answers, none worked. I have an extremely simple Python project with urllib, and I've never done web programming in Python before, nor am I even a regular Python user. My friend needs to get access to content from this site, but their user-friendly front-end is down and I learned that they have a public API to access their content. Not knowing what I'm doing, but glad to try to help and interested in the challenge, I have very slowly set out.
Note that it is necessary for me to only use standard Python libraries, so that any finished project could easily be emailed to their computer and just work.
The following works completely fine minus the "originalLanguage" query, but when using it, which the API has documented as an array value, no matter whether I comma-separate things, or write "originalLanguage[0]" or "originalLanguage0" or anything that I've seen online, this creates the error message from the server: "Array value expected but string detected" or something along those lines.
Is there any way for me to get this working? Because it clearly can work, otherwise the API wouldn't document it. Many thanks.
In case it helps, when using "[]" or "<>" or "{}" or any delimeter I could think of, my IDE didn't recognise it as part of the URL.
import urllib.request as request
import urllib.parse as parse
def make_query(url, params):
url += "?"
for i in range(len(params)):
url += list(params)[i]
url += '='
url += list(params.values())[i]
if i < len(params) - 1:
url += '&'
return url
base = "https://api.mangadex.org/manga"
params = {
"limit": "50",
"originalLanguage": "en"
}
url = make_query(base, params)
req = request.Request(url)
response = request.urlopen(req)
Problem
I cannot manipulate (insert, delete, update) data on a mysql table from tkinter. EDIT: I have been trying to insert/change data on mysql tables using tkinter. Although there's no error when I run this code, I cannot see any changes made in the table on mysql.
Code
def delete_record():
code=tcode.get('1.0',END)
#DATABASE CONNECTION
if code.isdigit()==True:
import mysql.connector as sqltor
mycon=sqltor.connect(host="localhost",user="root",passwd=" ",database="iv")
tkcursor=connection.cursor(prepared=True)
tkcursor.executed("delete from salesperson where code=%s,(code)")
mycon.commit()
tkinter.messagebox.showinfo("Record Deleted")
tkcursor.close()
Your two errors are the use of get() with Text widget and also your sql command seems incorrect. So try this out:
def delete_record():
code=tcode.get('1.0','end-1c') #change made here
#DATABASE CONNECTION
if code.isdigit()==True:
import mysql.connector as sqltor
mycon=sqltor.connect(host="localhost",user="root",passwd=" ",database="iv")
tkcursor=connection.cursor(prepared=True)
tkcursor.execute("delete from salesperson where code=%s",(code,)) #also change made here
mycon.commit()
tkinter.messagebox.showinfo("Record Deleted",'The records have been successfully deleted') #also addded message into the messagebox
tkcursor.close()
Also its a good practice to do all the imports on top of your code. Why to use end-1c ? Bryan Oakley has explained it below, take a look there. You were not getting any errors because the if statement never got executed, so also make sure to say print(code) and make sure it is a digit.
code isn't going to be what you think it is, and will never pass the isdigit test. Because you are getting to the END index, the data will have a trailing newline because the tkinter widget guarantees that there will always be a trailing newline.
When you want to get out of the text widget exactly what the user entered, you need to use "end-1c" ("end" minus one character). That, or strip off the trailing newline after you get it.
code = tcode.get('1.0', 'end-1c')
The first step in debugging should always be to examine variables to see if they are what you're assuming they are.
I am using bottle and peewee as the framework in back end, sqlite3 as the DB. And the summernote is the text editor at the front. Succeed in saving the code into DB, but failed to display the text when retrieving from the DB.
DB data:
The Draft column is the html
Source code:
Front:
$('#summernote').summernote("code", "{{content}}");
Backend:
template('apps_post_editer', appName='Post New', pid=newPost.id, title=('' if newPost.title is None else str(newPost.title)), content=('' if newPost.draft is None else unicode(str(newPost.draft), "utf-8")))
I thought it was the coding problem at the beginning, so i use unicode to turn the value in utf-8, but does not work. And also failed only str(newPost.draft)
The result:
You can see that the html code is not converted
Question:
Why it happens like that? Is there any solution?
Thanks very much.
Update: sorry it is my first question, don't know why the picture don't display...Please click the link to get more details...
OK...need 10 reputation
When you want to render HTML that comes from the database with bottle, you have to tell the rendering engine that the content is safe to render in order to avoid XSS attacks.
With bootle you can disable escaping for expressions like this:
{{! summernotecontent}}
in your case that would be:
$('#summernote').summernote("code", "{{! content}}");
You can find the documentation on this topic in bottle here
I've been experimenting with a Python CGI script to send an e-mail (hosted with a comercial web host - 123reg), and the problem is whenever I run the script from my web browser, it sends two identical e-mails.
The code to send the mail is definitely only being executed once, there are no loops which could cause it to happen twice, I am definitely not clicking the button twice. No exceptions are thrown and the "success" page is sent to the browser as normal.
The strangest thing is that when I comment out the code to print the result page (which is very simple and has no side effects, just 3 print statements in a row) and replace it with a dummy print statement (print "Content-type: text/plain\n\ntest"), it works properly and only sends one e-mail.
I have tried googling the problem to no avail.
I am at my wit's end because this problem doesn't make any sense to me. I'm pretty sure it must be my script since inexplicably it works when you comment out those print statements.
I'd appreciate any help, thanks.
EDIT:
Here's the code which, when commented out, fixes the problem:
print "Content-type: text/html"
print
print page
EDIT:
The code to send the e-mail:
#send_email function: sends message from from_addr, assumes valid input
def send_email(from_addr, message):
#form the email headers/text:
email = "From: " + from_addr + "\n"
email += "To: " + TO[0] + "\n"
email += "Subject: " + SUBJECT + "\n"
email += "\n"
email += message
#return true for success, false for failure:
try:
server = smtplib.SMTP(SERVER)
server.sendmail(from_addr, TO, email)
server.quit()
return True;
except smtplib.SMTPException:
return False;
#end of send_email function
I'd post the code to format the page variable, but all it does is read from a file, format a string and return the string. Nothing unusual going on.
EDIT
OK, I've commented out the file IO code in the create_page function and it solves the issue, but I don't understand why, and I don't know how to modify it so that it'll work properly.
The create_page function, and therefore the file IO, was still being executed when I found that commenting out the print statements solved the problem.
This is the file IO code from before I commented it out (it's at the very start of the create_page function and the rest of the function simply modifies the page string, then returns it):
#read the template from the file:
frame_f = open(FRAME)
page = frame_f.read()
frame_f.close()
EDIT:
I have just replaced the file IO by copying and pasting the file text directly into a string in my source file, so there is no longer any file IO. This still hasn't fixed the problem. At this point my only theory is that computers hate me...
EDIT:
I'll have to post this here since stackoverflow won't let me answer my own question since I'm a newbie here...
EDIT:
OK, I posted it as an actual answer now.
PROBLEM SOLVED!
It turns out that it was the browser's fault all along. The reason I didn't notice this sooner was because I tested it in both Firefox and Chrome ages ago to rule the browser out, however it turns out that both Chrome and Firefox share this same bug.
I realised what was happening when the server logs finally updated, I realised that often GET requests were immediately (1 second later) followed by another GET request. I did some googling and found this:
What causes Firefox to make a GET request after submitting a form via the POST method?
It turns out that if you have an img tag with an empty src attribute e.g.
<img src=""/>
(I had some javascript which modified that tag), Firefox will send a duplicate GET request in place of a request for the image. It also turns out that Chrome has the same problem. This also explains why the problem was only happening when I was trying to include my html template.
It would help if you posted more code, but does the "page" variable contain code that would execute the email server a second time, or cause a page refresh that would trigger the email a second time.
The same thing will happen if you have a Javascript call with an empty src or "#" as src:
<script type="text/javascript" src="#"></script>
Perhaps also with an empty href for a css link. I haven't experienced that, but I'd expect the same behavior.
I have a CGI script for which I've successfully set a cookie (which I can see in Firefox/Chrome!) which has (say) the name uid and the content 1. I don't seem to understand how to access this cookie from another CGI script--and I'm working in Python 2.4 so a lot of the examples I've found may not apply.
This code prints "can't get uid" followed by the rest of the page:
c = Cookie.SimpleCookie(os.environ.get("HTTP_COOKIE"))
print("Content-Type: text/html")
print c.output()
print("\n\n")
uid = c.get("uid")
#uid = c["uid"].value # this would create an error and page would fail totally
if uid is None:
print("can't get uid")
uid = 1 # set manually to prevent the rest of the page from failing
I haven't done anything fishy with the domain the cookie applies to, so I don't understand why this doesn't grab the uid value. By the way, if I try to print c.output(), it's blank.
First thing is are you sure the webserver or the framework is setting the HTTP_COOKIE environment variable?
Otherwise, in one of your script you may want to store the cookies in the CookieJar file in the file system and access the set cookies from there.
import cookielib
COOKIEFILE = 'Cookies.lwp'
cookiejar = cookielib.LWPCookieJar()
cookiejar.load(COOKIEFILE)
cookiejar["uid"] = 1
cookiejar.save(COOKIEFILE)
Load the same cookiejar and do the get of uid in the other script.
Okay, I think I figured this out! I confirmed that os.environ.get("HTTP_COOKIE") was getting something, and then played with the order of the elements in my tiny test until it worked. Then I reproduced that order in my more complicated script. (Specifically: content type declaration, two newlines, get cookie, get value from cookie, everything else.)
The main thing I've learned about Python and CGI is that the order of elements (starting with the content type declaration) is very fussy. Thanks very much for the hints in the right direction.