mysql % python

otherside3

New member
mysql % python

הי.
מנסה להתחיל ללמוד קצת לעבוד עם google cloud app ב-webapp2.
יש לי טופס שבניתי ב-html ואני רוצה להכניס את המידע ממנו לתוך טבלה שבניתי במסד.
לפי מה שקראתי, הבנתי שאני צריך לשמור את המידע מהשדה בתוך משתנה כלשהוא, ואז להשתמש ב-insert to.
בינתיים התהליך לא ממש עובד לי אז אני מנסה להבין אותו בחלקים...

בתמונה המצורפת יש הסבר שקראתי על הפונקציה get, שאמורה לשמור לי בתוך המשתנה שלי את המידע שהוזן ב-form.

א. מה ההבדל בין החלק העליון, שבו שם השדה הוא ב ' ', לבין החלק התחתון בו שם השדה הוא ב " " ?
ב. ניסיתי לעשות את זה אצלי בקוד, ואני לא בטוח אם ה"משתנה" שלי באמת מאותחל למידע כפי שהוזן ע"י המשתמש באתר או לא, איך אני יכול לבדוק את זה?
ג. נניח והמשתנה הזה מאותחל לתוכן שהוזן ע"י המשתמש באתר - איך אני משתמש בפונקציה insert to?
כי כשחיפשתי באינטרנט ראיתי מלא אפשרויות (עם ' ', עם " ", עם / / , ושאר סימנים מוזרים, שאף אחד מהם לא עבד לי..)
קוד:
sql = 'insert into <table> (attribute_1) values (?????????);'
cursor.execute(sql)
db.commit()


תודה רבה!

 

BravoMan

Active member
לא מכיר את webapp או cloud app אבל:

א. אין הבדל בין שימוש ב-" (גרש כפול) לשימוש ב-' (גרש בודד) בשפת Python.
שניהם מציינים מחרוזת.
&nbsp
ב. תלוי איך אתה מריץ את הקוד, אתה יכול להדפיס את תוכן המשתנה עם print.
אני רק לא יודע היכן תראה את התוצאה.
&nbsp
ג. לפי הדוגמה שהצגת, אתה צריך לדעת קצת SQL כדי לענות על השאלה הזו.
&nbsp
בגדול, מה שקורה כשהמשתמש לוחץ על כפתור "שלח" בטופס שלך, זה שהדפדפן בונה תשובה מכל השדות בטופס ושולח אותה לשרת.
&nbsp
ב-Cloud App יש קוד שמפרסר את התשובה, ומארגן את השדות בתוך אובייקט, שבסוף אתה מקבל בפונקציה post.
לאובייקט הזה יש מתודה get (השם טיפה מבלבל בהתחשב בנסיבות) שאתה אומר לה איזה שדה אתה רוצה (לפי שם שדה) והיא מחזירה לך את מה שהמשתמש הכניס שם, או כלום אם המשתמש לא הכניס שום דבר, או שלא היה בכלל שדה כזה בתופס.
&nbsp
אתה יכול להכניס את התוצאה למשתנה ולעשות איתה דברים, אבל לא חייב.
אתה יכול גם להשתמש בה ישירות, אם אתה בטוח שהתוצאה בסדר ולא רוצה לבדוק אותה.
&nbsp
אני לא בטוח אלו אפשרויות יש לך להכניס את המידע ל-DB, אבל בדוגמת קוד שהבאת נראה שאתה מנסה לבנות ישר שאילתת SQL מסוג INSERT.
&nbsp
יש עם זה בעיה גדולה:
אסור לעשות את זה אם אתה לא מנקה את הנתונים שקיבלת מהמשתמש.
&nbsp
אבל בוא נניח לזה בינתיים, אתה הרי רק מתחי ללמוד.
כדי לדעת מה למלא בשאילתה אתה צריך לדעת איך בנוי ה-DB שלך.
&nbsp
למשל, האם יצרת בו כבר טבלה, ואם כן מה השם שלה?
אלו עמודות יש בטבלה, והאם הן תואמות לשדות בתופס שאתה רוצה לשמור?
 

otherside3

New member
הי

תודה על התגובה.
&nbsp
לגבי השאילתא של ה-insert, יכול להיות שהכוונה לא הייתה ברורה.
אני מכיר את הפקודה insert ומבחינת הטבלה במסד - הכל תקין (כלומר הטבלה מוקמת, מכיר את שמות כל השדות וכו'..)
השאלה התמקדה ב-"?????" שהכנסתי לתוך ה-VALUE, כיוון שהבעיה הייתה כך:
נניח ויש לי משתנה id שאותחל על get וכעת מכיל את מספר תעודת הזהות שהמשתמש הכניס באתר, ונניח ואני רוצה להכניס את זה לתוך טבלה person לתוך השדה ID של הטבלה.
&nbsp
אז לא הצלחתי למצוא מהו הסינטקס שאיתו אני מכניס את id (מהאתר) לתוך ID של הטבלה.
כלומר
zz INSERT INTO person (ID) VALUE (id???) zz;
כיוון שראיתי תצורות סינטקס שונות של כתיבה בתוך ה-VALUE, לדוגמא:
כתיבת ערך בתוך:
zz '\ something \' zz
zz ' + something + ' zz
וכדומה, ואני לא ממש הצלחתי להבין את מהות הסינטקס הזה, ומהי צורת הכתיבה במידה ואני רוצה להכניס לתוך VALUE ערך שנשמר בתוך משתנה שאיתחלתי קודם (לדוגמא, להכניס את id כ-VALUE)
 

BravoMan

Active member
אז השאלה שלך היא איך מחברים מחרוזות ב-Python?

התשובה היא עם אופרטור חיבור +.
שים לב שבדוגמת קוד, משפט ה-SQL הוא בסה"כ מחרוזת שמאוחסנת במשתנה ואז נשלחת לפונקציה.

הדבר היחיד שאתה צריך לשים לב אליו, זה שערכים ב-SQL צריכים מעטפת של גרש בודד.
כאן, Python חוסך לך עבודה כי אתה יכול להשתמש בגרשיים לציון מחרוזת, ואז יהיה חוקי לשים גרש בודד בתוך המחרוזת עצמה.

לכן, הקוד שלך צריך להיראות משהו כזה:
sql = "INSERT INTO person (ID) VALUE ('" + id + "');"
אני יוצא כאן מנקודת הנחה ש-get מחזירה את כל השדות בתור מחרוזת ולא מנסה לנתח אותם.
זה לא יעבוד עם id הוא מטיפוס int או אחר.

אם אתה רוצה משהו יותר אוניברסלי ובטוח, תצטרך להשתמש בפרמוט מחרוזות, שיטה דומה למה ש-printf עושה ב-C (ראיתי משרשור למעלה שאתה מכיר C):
sql = "INSERT INTO person (ID) VALUE('%s');" % id
 

BravoMan

Active member
נ.ב.

בניגוד ל-C, שם יש להתאים את הטיפוס של הפרמטר למציין שאחרי %, ב-Python ההתאמה תבוצע אוטומטית, והאות אחרי % רק מציינת איך אתה רוצה להציג את המידע.
 

BravoMan

Active member
בעברית: לך תדע מה המשתמש הכניס.

יש שיטה מאוד פשוטה לפרוץ אתרים: היא נקראת SQL injection.
היא כ"כ פשוטה ומוכרת, שאפילו עשו עליה קומיקס:
https://xkcd.com/327
&nbsp
אם אתה לא בודק מה המשתמש הכניס, וישר דוחף את זה לתוך שאילתת SQL שלך, משתמש זדוני יכול בלי שום מאמץ מיוחד לכתוב קוד SQL משלו במקום ת.ז. או שם שלו, ולעשות כל מה שהוא רוצה ל-DB שלך.
&nbsp
לא התעקשתי על נקודה זו כי אני מבין שאתה רק לומד, ולכן הקוד שכתבת הוא לניסיון בלבד, אבל כמובן זה משהו שצריך לשים לב אליו כמה שיותר מוקדם.
&nbsp
אני לא מכיר כאמור את Web App, אבל בד"כ יש כל מיני פונקציות שמייצרות את השאילתות במקומך, במקום שתבנה אותן ישירות ידנית, ואז על הדרך דואגות שהקלט שאתה מספק לא יתפרש לעולם כחלק מפקודת SQL.
&nbsp
לחלופין, יש פונקציות "snitize" שבודקות קלט ועושות escaping לכל תו בעייתי.
&nbsp
בכלל, א-ב של תכנות בכל שפה ובכל תחום זה לבדוק טוב טוב את הקלט של המשתמש ולא להסתמך שהוא הכניס מה שציפית שהוא יכניס.
 

otherside3

New member
אה כן, ברור....

זה יכנס לתוך הקוד, פשוט רציתי קודם כל לראות שאני מצליח (ברמה העקרונית) לקלוט נתונים מהאתר ולהכניס אותם ל-DB, ועכשיו אחרי שהתהליך פחות או יותר עובד, אני אמשיך עם בדיקות המעטפת...
&nbsp
תודה!
 

otherside3

New member
הי (שוב
)

שאלת המשך קטנה.
באחת הטבלאות יש לי שדה מסוג longblob, בו אני ארצה לשמור תמונות..

חיפשתי באינטרנט איך מתנהלים עם תמונה, וקראתי כי ניתן לשמור אותה בטבלה ע"י
קוד:
thedata = open('pic1.jpg', 'rb').read()
			sql = "UPDATE mytable (picture) VALUES (%s)"
			cursor.execute(sql, (thedata,))

הבעיה - כשאני מנסה להריץ את זה אני מקבל את הודעת השגיאה:
No such file or directory: 'pic1.jpg'

אחת ההצעות באינטרנט הייתה לספק את הנתיב המלא, אך גם כאשר אני מבצע זאת אני מקבל הודעת שגיאה דומה:
קוד:
thedata = open('C:\Users\User\Desktop\pictures\pic1.jpg', 'rb').read()
			sql = "UPDATE mytable (picture) VALUES (%s)"
			cursor.execute(sql, (thedata,))
..........

No such file or directory: 'C:\\Users\\User\\Desktop\\pictures\\pic1.jpg'
אגב, מצאתי במקום נוסף באינטרט את קטע הקוד הבא:
קוד:
def read_file(filename):
	with open(filename, 'rb') as f:
		photo = f.read()
	return photo

**************************************************

//this section is inside another function

data = read_file("C:\Users\User\Desktop\pictures\pic1.jpg")
			query = "UPDATE mytable " \
			        "SET picture = %s " \
			        "WHERE catalog_num  = %s"
			args = (data, catalog_num)
			cursor.execute(query, args)
אך גם כאן אני מקבל את הודעת השגיאה כמו למעלה ולא כ"כ יודע איך להתקדם מכאן


סוף שבוע טוב!
 

BravoMan

Active member
הסקריפט שלך רץ מקומית על המחשב שבו יושב קובץ תמונה?

 

otherside3

New member
אממ..אני לא בטוח אם התשובה היא "כן" כמו שחשבתי להגיד

כי הקוד כתוב ב-google cloud app, אז אני מניח שזה לא בדיוק לוקלי
(אבל בגדול, אני משתמש במחשב שלי כדי לנסות לבדוק את הסריפקט, כאשר התמונה כרגע היא פיזית על המחשב שלי...אם זה עוזר...למרות שהכוונה הסופית היא שזה יהיה נגיש מכל מחשב כי הכיוון הוא שמתמש (כלשהוא) יכניס לאתר את התמונה והיא תאוחסן במסד..)
 

BravoMan

Active member
אוי ואובוי!

אם אתה לא מבין את ההבדל בין לוקלי למרוחק, אתה מקום מאוד מוקדם!
אתה חייב להיסגר מה הסביבה שהקוד שלך חי בה, אחרת תתקל בעוד הרבה בעיות.
&nbsp
לוקלי, זה אומר שהסקריפט רץ על המחשב שלך ממש:
אתה מפעיל אותו ע"י הרצת python.exe במחשב שלך.
&nbsp
אם אתה מעלה את הסקריפט לשירות של Google או מחשב אחר, ואז ניגש אליו דרך דפדפן במחשב שלך, זה כבר הופך אותו למרוחק.
כי הסקריפט לא רץ על המחשב שלך, אלא רץ על השרת ורק התוצאה חוזרת אליך.
&nbsp
סקריפט pyhotn מעולם לא ירוץ מקומית אצל משתמשים כי דפדפנים לא מריצים python, רק JS.
&nbsp
ומה שזה אומר הוא, שמבחינת הסקריפט, כל כונן C שלך בכלל לא קיים!
הוא לא יכול לראות אותו או לגעת בקבצים שלו, וטוב שכך, אחרת כל אתר שאתה גולש אליו, מתפוז ועד Google עצמם, יכלו לגנוב כל דבר ששמרת על המחשב שלך בקלות.
&nbsp
הקוד שכתבת מנסה לפתוח קובץ מקומי שחייב להיות פיזית על המחשב שעליו רץ הסקריפט, וגם במקום נגיש מבחינת הרשאות.
(בתור משתמש Windows מפונק אתה גם כנראה לא מכיר נושא של הרשאות על קבצים, וזה לא כ"כ טוב, אבל נדבר על זה אחר כך אם צריך)
 
למעלה