תכנות


11
אוג' 11

פייראפ ישראל עלה לאויר – פרוייקט קהילתי

כשהייתי בjunction התפתח לו נוהג לפני כל פגישה לשאול אנשים אם הם מחפשים שותפים לסטארטפ, או מחפשים להצטרף כשותפים. המשפטים היו די ברורים: אני כך וכך, המיזם שלי עושה כך וכך, ואני חפש כך וכך. לא עבר זמן רב ונפתח אקסל משותף בגוגל שערך את כל הנתונים.

הבעיה באקסל היתה שלא היתה דרך לנהל את התוכן, לראות ולהסיר פוסטים ישניםף לחפש בקלות וכו. בטיסה חזרה שלי מארה"ב לפני שבועיים החלטתי לשנות את זה – ולפני שבוע העלתי לאויר את pairup israel - שמטרתו לעזור ליזמים ישראלים למצא שותפים – או סטארטפים להצטרף אליהם. כמובן שהאתר די מוגבל, כיאה לאתר שנכתב ב12 שעות טיסה (פחות שתי ארוחות וסרט) – אבל הפטנקציונליות הבסיסית נמצאת שם ואפשר לשפר בהמשך.

בנוסף העלתי את הפרוייקט כקוד פתוח בגיטהב - אם אתם מתכנתי פייטון ורוצים לתרום או לשפר את מוזמנים. את רובו כתבתי בצורה הכי דג'נגואית שיכולתי תוך שימוש בקלאסים בסיסים ככל האפשר – אני מקווה שיהיה אפשר ללמוד הרבה מהפרוייקט אם אתם מתכנתים מתחילים.

כולם מוזמנים..


18
יוני 11

מתכנת מעל גיל 45? הסתבכת

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

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

הבעיה עם אנשי תוכנה מבוגרים לא פשוטה. היא קשורה, בין השאר, לעובדה שהתחום שלנו כולו הוא צעיר, משתנה מאוד, וחוקים כללים עדיין לא ברורים בו. האם נסיון של עשרות שנים רלוונטי תמיד בעולם של פרדיגמות משתנות? מהי החשיבות של עדכנות מיידית בטכנולוגיות חדשות, ומהי החשיבות (במיוחד בעולם הווב) של שימוש אישי בשירותים חדשים (האם תוכל להיות מתכנת טוב אם אתה לא משתמש בפייסבוק? אם לא ראית את טרנטייבל?) – ואולי החשוב ביותר: בעולם הסטארטאפים המשתנה הדגש על חברתיות, כיף בעבודה ושיטות ניהול חדשות הוא גדול מאוד – האם באמת התירוץ הקבוע של "חוסר התאמה לאופי החברה" הוא כל כך לא רלוונטי?

יש הרבה תשובות טובות לשאלות האלה, יש מספר דיונים שיכולים לצאת מהן. יש אנשים שתמיד נשארים מעודכנים, פשוט כי הם אוהבים את מה שהם עושים. יש אנשים שבודקים כל דבר חדש שיוצא, ויכולים לספר לך לא רק מה חדש שם, אלא מי עשה את זה בעבר, טוב יותר או רע יותר, מה ההבדלים ולמה זה עבד וההוא לא. כאן הנסיון של השנים מתחיל לעבוד חזק, ומצאתי שאנשים כאלה נתקלים פחות בבעיה של "חוסר התאמה", אולי משום שהם יותר מתאימים גם ברוחם לאנשים צעירים? – מה שמגדיל את החשד שלי שחוסר ההתאמה הזו מוצדקת לעיתים ואינה קשורה ישירות לגיל – אלא לתרגיל.

הבעיה בפוסט של משה שהוא לא מסביר את האתגר בצורה נכונה אלא רק נותן את הפתרון, ומי שיעשה את מה שהוא אומר בצורה עיוורת לא יקבל תוצאות טובות מספיק. רן מזכיר את זה בפודקאסט בצורה יותר כללית: אם אתה אוהב מה שאתה עושה, קורא כל הזמן, נשאר מעודכן, תהיה בסדר. אני מסכים עם הגישה הזו. מישהו שואל שם (לא זיהיתי את הקול, אני חושב שזה גילי) אם זה לא מתיש עם הזמן – ועונים לו שלא. לזה אני לא מסכים: לפעמים זה מתיש. לפעמים אתה רוצה קצת לנוח ולתת חתיכת קוד טובה ולא לחשוב מעבר, אבל זה לא המקצוע שלנו. המקצוע שלנו דורש עדכון מתמיד. לפעמים זה מרגיש כמו רדיפה, אבל זה מה שאנחנו עושים. קוד פתוח משתנה מהר, תאהבו את זה או תשנאו את זה.

מה שחשוב זה להבין את העולם הזה, לקבל אותו ולרוץ איתו. זמן ונסיון בלבד לא הופכים אותך למתכנת טוב. אולי זו פרדיגמה שעבדה במקומות אחרים, אולי גם זה מעולם לא היה נכון, אבל אם אתם מתכנתים ורואים עצמכם עובדים במקצוע בעתיד – עשו לעצמכם טובה והפנימו את הדבר ה"קטן" הזה. אתם חייבים להתקרב לעולם התכנות כל יום מחדש כאילו הוא היום הראשון. לבדוק, להתעדכן, ללמוד. להשתתף.


11
יוני 11

Django Unit Test על דאטהבייס חלופי

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

רציתי לתאר שלוש שיטות שונות שמתגברות על בעיות מאוד ספציפיות בדיקות unit test בdjango הקשורות לסביבות שאתם עובדים בהן. אלה לא בהכרח בעיות שכולם נתקלים בהן, ומתי שכן הפתרון הוא חד פעמי, ועדיין, חשוב לכתוב אותו ואולי לשמוע דעות של אחרים על הפתרון ועל אלטרנטיבות אחרות.

בדיקות על POSTGRES

Django מגיע עם דאטהבייס sqlite המיועד לפיתוח בלבד, עובד חזק בזכרון ולא תומך כל כך טוב בכמה משתמשים בו זמנית – אבל הוא קל ומהיר. הבעיה מתחילה שבעולם האמיתי אתם משתמשים במוצר אחר (אני משתמש כרגע בpostgres) ויש חוסר תאימות בחלק מהמוצרים או בביצועים. אני לא אכנס להחלטה האם כדאי לפתח על אותה סביבה של המוצר, עד כמה רחוק ללכת וכו. רק אציין שאצלי אכן עברתי מsqlite לpostgres בפיתוח, ואז מתקלתי בבעיה: בכל תחילת ריצה מנוע הבדיקות של django מבקש למחוק את בסיס הנתונים כדי להתחיל נקי.. אופס! לא רציתי את זה כי בסיס הנתונים מכיל מידע שאני אוהב לבדוק איתו בבדיקות הידניות.. אבל אני רוצה גם וגם!

הפתרון: קובץ קונפיגורציה שונה (או נוסף) לבדיקות. ממילא היו לי שני קבצים (local, production) החלטתי להוסיף קובץ שלישי שכל מטרתו לקנפג בסיס נתונים חדש:

במקרה שלי מכל מיני סיבות החלטתי שהקובץ ירש מהקובץ המקומי (קובץ הproduction) מקבל כל מיני נתונים שלא תלויים בי ולא רציתי לשמור את התלות הזו), ואז פשוט להוסיף את השורות הבאות שמשנות את הנתונים שחשובים לי:

try:
from settings import *
except ImportError:
pass

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

DATABASES = {
'default': {
# Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'ENGINE': 'django.db.backends.sqlite3',
'NAME': project/dev.db',                      # Or path to database file if using sqlite3.
'USER': '',                      # Not used with sqlite3.
'PASSWORD': '',                  # Not used with sqlite3.
'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
'PORT': '',
},
}

<p style="text-align: right;"><code dir="ltr">
בשילוב עם הרצה של הבדיקות רק על החלקים שלי, פקודת הבדיקה תהיה:

./manage.py test_watook --settings test-settings

בעיה שנייה


29
מרץ 11

קצרצר: לאתחל את סיסמת המנהל (admin) בדג'נגו

משהו שקורה לי כל כמה זמן – אני שוכח את הסיסמה לאדמין שלי. יש שיטה קלה יחסית להחליף אותה, וזה ע"י כניסה לdatabase:

הכנסו לshell החביב עליכם. לרוב אני משתמש בshell_plus של הdjango extensions שהוא shell רגיל (כמו django shell רק שהוא מעלה אוטומטית את כל המודולים שלכם):

from django.contrib.auth.models import User

us = User.objects.get(username="{{ your username }}")

us.set_password('{{ your password}}')

us.save()

פשוט, לא?


19
מרץ 11

חשיבות הכיסוי (coverage) בבדיקות התוכנה – ואיך עושים את זה בד'נגו

בפוסט הקודם (על בדיקות תוכנה חלקיות בdjango) כתבתי על היכולת לבדוק רק מה שאתה כותב בתוך הפרוייקט. השלב הבא ההגיוני הוא להבין עד כמה הבדיקות האלה טובות.

מכיוון שעדיין לא נתקלתי במישהו שחושב שבדיקות coverage חשובות כמו שאני חושב, אני רוצה לעצור כאן רגע ולדבר על הקונספט עצמו לרגע.

מהן בדיקות כיסוי (coverage)

פירוט והסבר מלא אפשר למצא בוויקיפדיה (או כרגיל, בגרסה הטובה בהרבה באנגלית). הרעיון הוא פשוט: מריצים בדיקות אוטומטית או ידיניות, ובמקביל לגמרי, בלי קשר לבדיקות, בודקים מה בדיוק מורץ. אפשר לבדוק מדדים שונים (קוד, שורות, מסלולים ועוד) – אבל הרעיון דומה: בסופו של התהליך זוהי הדרך היחידה לדעת עד כמה הבדיקות שלכם מקיפות – ולכן להסיק עד כמה הן טובות. בצורה מפתיעה, אנשים רבים מבינים את חשיבות הבדיקות האוטומטיות (וגם זה שיפור לטובה) – אבל לא מבינים שללא הבנה של הכיסוי, ייתכן שהבדיקות שלכם לא שוות כלום.

חשוב לציין כמה נקודות קטנות בקשר לבדיקות האלה:

  • קשה מאוד להגיע ל100% בדיקות, ומעט מאוד אנשים חושבים שזה היעד. יש תלות מסויימת בקוד הספציפי שלכם, אבל קטנה מאוד – אני ממליץ לנסות להגיע לפחות ל70% כיסוי, ולא לנסות להלחם יותר מדי על ה10% האחרונים.
  • בדיקות קוד צד לקוח בעתיות יותר ואני לא הולך להתיחס אליהן בפוסט הזה (במיוחד כי הדגש כרגע הוא על django)
  • התירוץ החוזר הוא ש"הקוד שלנו שונה כי xyz, ולכן קשה בהרבה להגיע לכיסוי טוב". החליפו את xyz בדברים כמו "הוא מערב הרבה מודולים שונים", "אי אפשר להגיע לבדיקה של כל פינה", "יש לנו הרבה יותר נקודות קצה", והחביב עלי: "הקוד שלנו מאוד שונה כי הוא פועל על שילוב מחלקות שונות וקריאות מסובכות, תלויות חצוניות ודברים דומים". יש עוד הרבה כאלה. אל תקשיבו – עוד לא פגשתי קוד שבלתי אפשרי להגיע לאחוזים גבוהים של כיסוי – אם כי פגשתי קוד שהיה צריך לכתוב כמה mockups, נקודות קצה וירוטאליות ועוד משחקים שונים ומשונים.

בדיקות כיסוי בdjango

בדיקות הכיסוי בdjango במוססות על בדיקות כיסוי של נד בצ'לדר (Ned Batchelder) שנמצאות גם כאן או כאן. בחרו את הדרך הנוחה לכם להתקנה:

pip install hg+https://bitbucket.org/ned/coveragepy

או

easy_install coverage

וכדומה. בצורה דומה אפשר לחבר את החבילה לbuildout.

לאחר מכן התקינו את התוסף לdjango:

https://bitbucket.org/kmike/django-coverage/src

יש מספר תוספים אבל אני מחבב אותו. הופיעו שם כמה בעיות בחלק מהטמפלטים, אני מקווה שמתישהו אמצא זמן לשבת ולתקן – בנתיים, אפשר להשתמש בטמפלטים הרגילים.

לאחר שהתקנתם, הוספתם את django_coverage לsettingsINSTALLED_APPS, אתם כמעט מוכנים, ויכולים לבדוק את ההתקנה ע"י הרצה של

python manage.py test_coverage

אני ממליץ ללכת שלב נוסף, כמו שהזכרתי בפוסט הקודם, וליצור בדיקות רק לקוד שלכם:

בתוך management->commands (הפוסט הקודם מסביר את זה):

from django.core.management.base import AppCommand, BaseCommand

[python]
from django.core.management.base import AppCommand, BaseCommand
from django.core.management import call_command

from django.conf import settings

class Command(BaseCommand):

    def handle(self, *args, **options):
        test_app_path = ()
        for app in settings.MY_INSTALLED_APPS:
            test_app = app.split('.')
            if len(test_app) > 1:
                test_app = (test_app[-1],)
            else:
                test_app = (app,)
            test_app_path += test_app
        call_command("test_coverage",*test_app_path, **options)

[/python]

הוסיפו בsettings שלכם את מיקום יצירת הhtml:

COVERAGE_REPORT_HTML_OUTPUT_DIR כדי לבחור את הספריה ליצירת תוצאות הHTML


16
מרץ 11

דג'נגו – להריץ בדיקות רק על החלקים שלך

כחלק מפיתוח תוכנה רגילה בdjango אנשים מעודדים להשתמש (בתקווה גם לתרום) לקוד פתוח דרך ספריות מתוך pypi, github' bitbucket וכדומה. כל זה טוב ויפה, אבל מה קורה שאתה אוסף לך רשימה די ארוכה של אפליקציות, שרק חלק קטן מהן שלך, ואתה רוצה להריץ את הבדיקות שכתבת לעצמך (כי כולנו כותבים unit tests, נכון?)?

הבעיה

דג'נגו תומך בפקודה manage.py test, שמריצה את כל הבדיקות מהאפליקציות המותקנות. אבל זה כולל בדיקות רבות שלא קשורות אליך, במקרה הטוב זה לוקח הרבה זמן, במקרה הרע חלק מהבדיקות לא עוברות משום שהן דורשות סביבה מיוחדת (במיוחד הבדיקות של django עצמה), ובמקרה הרע מאוד – הן פשוט לא עוברות.

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

הפתרון

הפתרון קשור לדרך ולפרמטרים שהפקודה הנ"ל כן תומכת בהם: אפשר להריץ בדיקות על מספר אפליקציות ע"י קריאה לרשימת אפליקציות מופרדות ברווח:

python manage.py test app1 app2 app3

וכן מהיכולת להפריד את האפליקציות המותקנות לשתי רשימות, בלי לפגוע בעבודה היום יומית. לקחתי את הINSTALLED_APPS הרגיל שנמצא בsettings.py והפכתי אותו לשתי רשימות:

MY_INSTALLED_APPS = ( app1, app2 )

INSTALLED_APPS = MY_INSTALLED_APPS+( app3 )

בצורה הזו עדיין כל האפליקציות נמצאות בקובץ הsettings אחת ליד השניה, אין כפילות ואין בעיה לשמור על הסדר.

עכשיו רק צריך ליצור פקודה שרצה על MY_INSTALLED_APPS ומריצה על כל אחת מהן פקודת test. בשביל זה יצרתי פקודת שליטה: בתוך הספרייה management->commands יצרתי קובץ test_apps, שבו הקוד:

[python]
from django.core.management.base import AppCommand, BaseCommand
from django.core.management import call_command

from django.conf import settings

class Command(BaseCommand):

    def handle(self, *args, **options):
        test_app_path = ()
        for app in settings.MY_INSTALLED_APPS:
            test_app = app.split('.')
            if len(test_app) > 1:
                test_app = (test_app[-1],)
            else:
                test_app = (app,)
            test_app_path += test_app
        call_command("test",*test_app_path, **options)

[/python]

ועכשיו כשאני רוצה להריץ רק את הבדיקות שלי, אני פשוט מריץ python manage.py test_apps

 

 

 


20
פבר' 11

זיהוי משתמש לפי מייל בdjango

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

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

שני דברים הנחו אותי בכתיבה:

1. אפשר לזהות מייל בכל מיני שיטות שונות ומתוחכמות. לא הכרחי ולא תמיד יעיל – החלטתי לחפש @ בשם המשתמש – דבר שאסור לפי החוקים במערכת שלי.

2. ליתר בטחון כמעט בכל מעבר (לא מצאתי @, לא מצאתי מייל וכו) – אני מעביר את הקריאה להמשך טיפול רגיל. במקרה הגרוע פגעתי בביצועים בעיקר בחיפוש אחד נוסף.

הנה הקוד:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User

class EmailUserBackend(ModelBackend):

    def authenticate(self, username=None, password=None):

        if '@' in username:

            try:

                user = User.objects.get(email=username)

                if user.check_password(password):

                    return user

            except User.DoesNotExist:

                pass

        return super(EmailUserBackend,self).authenticate(username, password)

בנוסף, צריך להחליף את הקוד הנוכחי בsettings.py:

AUTHENTICATION_BACKENDS = (

'gifts.giftuser.backend.EmailUserBackend',

#'django.contrib.auth.backends.ModelBackend',

)

בהערה: הקוד הקודם.


16
פבר' 11

תיקון אבטחה בdjango משנה קריאות ajax (אין תאימות אחורה)

אם אתם משתמשים בdjango עדכני ולפתע מקבלים שגיאת 403 לקריאות הajax שלכם ולא מבינים למה, כדאי שתקראו את זה.

ב8 בפברואר שוחרר תיקון אבטחה בdjango שכלל גרסאות 1.1, 1.2 וגרסת הקוד האחרונה. הסיפור הוא די פשוט, אבל כדי להבין אותו כדאי לדעת כמה פרטים כללים על CSRF, למה משתמשים בזה ואיך. אם אתם יודעים אתם יכולים לקפוץ על הפסקאות הבאות הישר לפתרון.

מה זה CSRF

csrf הם ראשי התיבות לCross-site request forgery, פירצת אבטחה המאפשרת שליחת פקודות לאתר בשמו של משתמש שהאתר מכיר ובוטח. בניגוד לxss המפורסמת קצת יותר, שבה מנצלים את האימון שהמשתמש נותן באתר. הרעיון בבסיסו פשוט מאוד: אם התוקף יודע שמשתמש מסויים מחובר לאתר, הוא שותל קוד באתר או באתר אחר, המפנה לפעולה מסויימת ושולח אותו במספר דרכים זדוניות למשתמש, אשר ביודעין או לא מפעיל את הקוד הזה. מכיוון שהמשתמש מחובר, האתר בוטח בו ובזהות שלו ומפעיל את הפקודה.

דוגמא פשוטה מתוך וויקיפידיה היא שתילת קוד בתוך כתובת של תמונה. הדפדפן של הקורבן ניגש להביא את התמונה, מזדהה כקורבן ומפעיל פעולה שאינה קשורה כלל לתמונה:

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">

השיטה הפופלרית ביותר להתמודדות (זו שdjango משתמשת בה, וכן wordpress וruby) היא הוספת קוד סודי לפני קריאות אפשריות לשרת. אם הקוד לא שם אז השרת מתיחס לקריאה כפריצת אבטחה ומחזיר קוד 403.

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

מהי ההתקפה האפשרית החדשה

צוות של גוגל מצא אפשרות ליצור, בעזרת קומבינציה של תוספים לדפדפן ומספר redirects קריאה שנראית כמו ajax אבל למעשה אינה כזו, ובכך לגרום לצד הדפדפן לא להגן על המשתמש ולצד השרת לחשוב שכן – ובכך ליצור את הפירצה. הפתרון: הגנה בצד השרת גם על קריאות ajax, ולכן הפגיעה אחורה בקוד שלכם.
למרבית ההפתעה (וחוסר הסדר), המסמכים הרשמיים נותנים שני פתרונות אפשריים אם אתם משתמשים בjquery. אחד נמצא בהודעה על השיחרור, והשני במסמכים של הגירסה החדשה. ישנם גם מספר דיונים על הדרך הטובה והיעילה ביותר לעשות את זה, אז שווה להמשיך לעקוב – אבל כרגע קודם כל לפתור את הבעיה.

אני אציג כאן רק את הפתרון הרשמי יותר, משום שהוא כללי ותומך בעוגיות, ואילו הפתרון השני מסתמך על נוכחות של form בקוד שלכם, מה שלא תמיד נכון.

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        function getCookie(name) {
            var cookieValue = null;
            if (document.cookie && document.cookie != '') {
                var cookies = document.cookie.split(';');
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = jQuery.trim(cookies[i]);
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) == (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
            // Only send the token to relative URLs i.e. locally.
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});

תיאור הפתרון:

בעזרת jquery אנחנו תופסים כל בקשת ajax, ובודקים אם יש לנו עוגיה המכילה את המילה csrftoken, ומוסיפים אותה לבקשה.


1
פבר' 11

Django's get_model וסדר טעינת מודולים

היום היה יום עמוס במיוחד. הוא התחיל עם באג קטן שמצאתי בDjango, המשיך בכמה תיקונים בשתי חבילות חדשות שהתחלתי להשתמש (django-registration ו-django-social-auth) והמשיך הלאה משם. את התיקון בdjango לקח לי קצת זמן למצא פשוט מהסיבה שלא האמנתי שיש ממש באג בבסיס, אבל התיקון בsocial-auth היה מענין יותר.

social-auth הוא תוסף המאפשר הרשמה של משתמשים מרשתות חברתיות לאפליקלציה שלך. אני משתמש בפייסבוק, טוויטר ואולי גוגל בהמשך, אבל התוסף עצמו תומך גם ביאהו, אורקוט וopen id של גוגל – לא רע בכלל.

ההסתבכות הגיעה כשהתחלתי להשתמש במודול משתמש משלי. אני שולף כמה נתונים מפייסבוק בנוסף לדברים הבסיסיים ביותר, ומכניס אותם לפרטי המשתמש – וכדי לעשות את זה אני משתמש בשני כלים שהתוסף מאפשר לי: סיגנלים ומודל משתמש מיוחד של דגנו.

סיגנלים הם כלי פשוט אבל חזק של הוקים וטריגרים במערכת. יש כמה שמגיעים עם המערכת (לפני ואחרי שמירת מודל לדוגמא) ויש אפשרות לבנות גם כמה סיגנלים משלך (כמו שהתוסף עשה). מהצד השני אתה בוחר לאיזה סוג של סיגנל אתה רוצה להקשיב, ופועל לפיו.

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

הבעיה היתה שמכיוון ששני השימושים הנ"ל (הסיגנל והמודל המקומי) התיחסו למודל שלי של המשתמש, אפשרתי את שניהם באותו הקובץ, לפני ההגדרה של מודל המשתמש שלי. כל אחד מהנ"ל יכל לעבוד, אבל ביחד – השימוש בסיגנל הכניס את המודל לזכרון, וברגע שהוא נכנס לזכרון הוא קרא לget_model כדי להעלות את המשתמש שלי – אבל זה עדיין לא היה נגיש בשלב הזה. התוצאה: התרסקות.

הפתרון – הוצאה של כל החבילה הזו למודול נפרד או הורדה לאותו מודול אבל מתחת להגדרה המקומית שלי. שניהם פתרונות לא אידיאליים מבחינת נכונות וסדר קוד, אבל זה מה יש.


2
ינו' 11

לקחי טכנולוגיה – 30.12.10 – buildout

  • כשבונים buildout לפייטון, במיוחד בסביבת eclipse, משתנה הextra-path יגרום לסקריפט להכניס נתונים לbin/django שלכם הכוללים את הpath לחבילות המותקנות. אם יש לכם מודל ספציפי שאתם רוצים להשתמש בו ישירות, אתם חייבים להכניס את השורה הזו.
  • השוואה מצויינת של ביצועי ווב סרברז לפייטון שלא רק נכנסת לפרטי הבדיקות, בודקת הרבה סרסבים אלא גם מסבירה את ההבדלים, ממה הם נובעים וכו. לכל האנשים שמדברים ביצועים אבל לא תמיד סגורים למה thread pool שונה מthread per process, הנה.