این مقاله یکی از قسمت‌های سلسله مقالاتی برای آشنایی و آموزش زبان پایتون است. این مجموع پیش از این در ماهنامه شبکه منتشر شده اما به سایت جدید منتقل نشده بود. با توجه به اهمیت موضوع و درخواست‌های مکرر خوانندگان، این مجموعه را به سایت مجله اضافه می‌کنیم و امیدواریم که مورد توجه علاقمندان قرار بگیرد.

برای مطالعه قسمت‌های قبلی سلسله مقالات آموزش زبان برنامه‌نویسی پایتون اینجا کلیک کنید

import apsw

import string

 

class CookBook:

def __init__(self):

pass

def All(self):

pass

def Search(self):

pass

def Show(self,which):

pass

def Add(self):

pass

def Delete(self,which):

pass

 

def Menu():

ckb= CookBook()

loop=True

while loop:

print “********************”

print “* Recipe Database  *”

print “********************”

print “  ۱-Show all”

print “  ۲-Search for a recipe”

print “  ۳-Show a recipe”

print “  ۴-Add a recipe”

print “  ۵-Delete a recipe”

print “  ۰-Exit”

print “********************”

response= raw_input(“  Enter your selection: “)

if response == ‘۱’:

pass

elif response == ‘۲’:

pass

elif response == ‘۳’:

pass

elif response == ‘۴’:

pass

elif response == ‘۵’:

pass

elif response == ‘۰’:

print “ntGoodbye”

loop=False

else:

print “nUnrecognized command. Try again.nn”

 

Menu()

فهرست ۱-  چهارچوب كلی برنامه ‌Cook Book

def __init__(self):
        global connection
        global cursor
        self.totalCount=0
        connection = apsw.Connection(“cookbook1.db3”)
        cursor=connection.cursor()

فهرست ۲-  كدهای تكميل تابع راه‌اندازی كلاس Cook Book

def All(self):
        print “nnNumber tName ttServes ttSource”
        print “-”*۵۵
        sql = “SELECT * FROM Recipes”
        cntr=0
        for x in cursor.execute(sql):
                cntr += 1
                print “%s t%s t%s tt%s” %(x[0],x[1],x[2],x[3])
        print “-”*۵۵
        self.totalCount = cntr
        print “Total number of items: %s” %cntr

فهرست ۳-   كدهای تابع نمايش تمام موارد موجود در پايگاه داده

همچنین برای نگه‌داری روال‌های مربوط به پایگاه داده یک کلاس تعریف خواهیم کرد. چون این کد بسیار طولانی خواهد بود ما در ابتدا چهارچوب کلی آن را نوشته و سپس قسمت‌های مختلف را به تدریج به آن می‌افزاییم. برای شروع كار این چهارچوب را که در فهرست ۱ آورده شده، وارد کرده و آن را با نام CookBook.py ذخیره کنید.
همان‌طور که در این کد مشاهده می‌کنید، کلیت یک کلاس و تابعی برای ترسیم یک منو روی صفحه نمایش تعریف شده است. ما به تدریج این چهارچوب را برای رسیدن به برنامه نهایی تکمیل خواهیم کرد. اگر در وضعیت فعلی برنامه را اجرا کنید، شکلی همانند شكل ۱ را مشاهده خواهید کرد. در این حالت، تنها کلید ۰ برای خروج از برنامه کار خواهد کرد. اکنون به نوشتن روتین راه‌اندازی کلاس و سایر روتین‌های مربوط به اعمال نمایش‌کل اطلاعات، جست‌وجو، نمایش یک مورد، افزودن و حذف موارد پایگاه داده خواهیم پرداخت. از میان این روتین‌ها، روتین‌های نمایش کل اطلاعات، جست‌وجو و افزودن آیتم به هیچ آرگومان ورودی نیاز ندارند (البته همان‌طور که از بحث‌های کلاس‌ها و اشیاء به یاد دارید، به جزء آرگومان اجباری self). اما روتین‌های نمایش و حذف به پارامتری نياز دارند که در این کدها آن را which نامیده‌ایم و این پارامتر تعیین می‌کند کدام آیتم باید نمایش داده‌شده یا حذف شود.

راه‌اندازی

در ابتدا باید روتین راه‌اندازی کلاس یا __init__ را کامل کنیم. کدهای مورد نیاز برای این روتین در فهرست ۲ آورده شده است. اين كد را جايگزين خطوط ۵ و۶ فهرست ۱ كنيد.
در اینجا ابتدا دو متغیر جهانی تعریف‌کرده‌ایم. این متغیرها به رغم این‌که در تعریف یک تابع آورده شده‌اند، به‌واسطه کلمه global، در تمام برنامه قابل استفاده‌خواهند بود. این کار را به این دلیل انجام می‌دهیم که پایگاه داده و مکان‌نمای مربوط به آن در تمام روتین‌های برنامه قابل دسترس باشند. برای کار با پایگاه داده‌ای که در قسمت قبل ایجاد کردید، باید این برنامه و فایل پایگاه‌داده را در یک پوشه و در کنار هم قرار دهید و در خط ۵،  نام فایل پایگاه داده خود را جایگزین cookbook1.db3 کنید.

نمایش همه موارد

برای نمایش همه موارد از کد فهرست‌۳ استفاده خواهیم کرد. این کد را در کلاس CookBook فهرست‌۱ جایگزین خطوط ۷ و ۸ کنید. همین‌طور باید از خط ۳۴ فهرست ۳ کلمه pass را حذف و عبارت زير را  جایگزین آن کنید:

ckb.All()
temp = raw_input(“Press any key to continue…”)

در این تابع ما از cursor ساخته شده در روتین __init__ استفاده کرده‌ایم و تمام محتویات جدول Recipes را فراخوانی کرده‌ایم، سپس در یک حلقه تمام مقادیر را با قالب‌بندی‌های استفاده شده در دستور print (که قبلاً با آن آشنا شده‌اید) به‌صورت منظم چاپ کرده‌ایم. به یاد دارید که apsw مقادیر برگشتی جدول را به صورت توپل به ما باز‌می‌گرداند، به همین دلیل، ما از [x[0  و [x[1 و… استفاده کرده‌ایم. در انتهای این روتین و در خط ‌۱۱ تعداد کل آیتم‌های موجود در جدول Recipes را نیز اعلام کرده‌ایم.

شکل ۱- منوی دسترسی به پايگاه داده

جست‌وجو

برای بخش جست‌وجو، به دلیل کمبود فضا، تنها بخش جست‌وجوی نام دستورالعمل را پیاده‌سازی کرده‌ایم و جست‌وجو بر اساس محتویات و تعداد نفراتی را که با یک دستورالعمل سير می‌شوند، به عهده شما گذاشته‌ایم. کدهای این روتین در فهرست ۴ آورده شده است. اين كدها را جايگزين خطوط ۹ و ۱۰ فهرست كنيد.
در این کد و در خط ۵ عبارت موردنظر از کاربر پرسیده شده و در خط ۶ با تعریف یک دستور sql عملیات جست‌وجو را روی پایگاه داده انجام‌داده‌ایم. شاید عبارت %%%s%% در این خط کد عجیب به نظربرسد. در زبان sql برای تعریف مشابهت از کلمه کلیدی like و فرم %term% استفاده می‌شود. در این حالت کلماتی که مشابه term باشند، برگردانده می‌شوند. اما چون در زبان پایتون از علامت % برای فرمت‌کردن رشته‌ها استفاده می‌شود، یک رشته نمی‌تواند به طور مستقیم شامل علامت % باشد. برای درج این علامت در یک رشته باید دوبار آن را پشت سر هم (%%) به‌کار ببریم. به این ترتیب، در خط ۷ جفت علامت‌های سمت راست و چپ به تک علامت‌های % و قسمت وسط (%s) نیز توسط عبارت term جایگزین‌می‌شود. در انتهای این روتین و در خط ۹ از تابع ()Show  که آن را در قسمت بعد تعریف می‌کنیم، برای نمایش آیتم‌های مورد نظر استفاده کرده‌ایم. براي فعال شدن اين بخش بايد كلمه pass درخط ۳۶ فهرست ۱ با عبارت  () ckb.Search  جايگزين شود.

def Search(self):
        print 
        print “=”*۵۵
        print “Searching in recipes by name”
        term = raw_input(“Enter name of the recipe: “)
        sql = “SELECT pkID , name FROM Recipes WHERE name like ‘%%%s%%’” %term
        for x in cursor.execute(sql):
                self.Show(x[0])

فهرست ۴-  كدهای تابع جست‌وجو در پايگاه داده براساس نام دستورالعمل

def Show(self,which):
        sql = “SELECT * FROM Recipes WHERE pkID = %s” %str(which)
        print “n”
        print “=”*۵۵
        for x in cursor.execute(sql):
                print “Title: %s t Serves: %s t Source: %s” %(x[1],x[2],x[3])
                
        sql = “SELECT * FROM Ingredients WHERE pkID = %s” %str(which)
        print “nIngredients:”
        for x in cursor.execute(sql):
                print x[1]
        
        sql = “SELECT * FROM Instructions WHERE pkID = %s” %str(which)
        print “nInstructions:”
        for x in cursor.execute(sql):
                print x[1]
        print “=”*۵۵
        print “n”

فهرست ۵-  كدهای تابع مورد نياز برای نمايش يك آيتم از پايگاه داده

نمایش یک مورد

برای عملیاتی کردن این بخش، ابتدا با فراخوانی تابع ()All تمام موارد را به کاربر نشان خواهیم داد و از او خواهیم خواست که آیتم مورد نظر را انتخاب کند.براي اين كار كلمه pass در خط ۳۸ فهرست ۱ را با كد‌های زير جايگزين كنيد:

ckb.All()
temp = raw_input(“What to show:”)
ckb.Show(temp)

 پس از آن با فرستادن آیتم انتخاب شده به عفاکتورین آرگومان which به روتین ()Show آن آیتم را به نمایش خواهیم گذاشت. کدهای مربوط به این روتین در فهرست ۵ آورده شده است. اين كدها را جايگزين  خطوط ۱۱ و ۱۲ فهرست ۱ كنيد. در این کد، در خط ۲ دستور sql مورد نیاز را برای انتخاب آیتمی که شماره ردیف (pkID) آن با آرگومان which به تابع اعلام شده است، تعریف کرده‌ایم. پس از آن با تعریف دو دستور sql دیگر مقادیر متناظر را از جدول‌های Ingredients و Instructions استخراج کرده و با دستور print چاپ کرده‌ایم.

def Add(self):
        ings = ““
        lastid = 0
        recipename=raw_input(‘Enter Recipe Title -> ‘)
        recipesource=raw_input(“Enter Recipe Source -> “)
        recipeserves=raw_input(“Enter number of servings -> “)
        while True:
                ing = raw_input(‘Enter Ingredient (“۰” to exit) -> ‘)
                if ing != ‘۰’:
                        ings = ings + ing + “, “
                else:
                        break
        instructions = raw_input(‘Enter Instructions -> ‘)
        print ‘=’*۵۵
        print “Here›s what we have so far”
        print “Title: %s” % recipename
        print “Source: %s” % recipesource
        print “Serves: %s” % recipeserves
        print “Ingredients: %s” % ings
        print “Instructions: %s” % instructions
        print ‘=’*۵۵
        resp = raw_input(“OK to save? (Y/n) -> “)
        if resp.upper() != ‘N’:
                #connection=apsw.Connection(“cookbook1.db3”)
                #cursor=connection.cursor()
                # Write the Recipe Record
                sql = ‘INSERT INTO Recipes (name,serves,source) VALUES (“%s”,”%s”,”%s”)’ %(recipename,recipeserves,recipesource)
                cursor.execute(sql)
                # Get the new Recipe pkID
                sql = “SELECT last_insert_rowid()”
                cursor.execute(sql)
                for x in cursor.execute(sql):
                        lastid = x[0]
                        print “last id = %s” % lastid
                # Write the Instruction Record
                sql = ‘INSERT INTO Ingredients (recipeID,ingredients) VALUES (%s,”%s”)’ % (lastid,x)
                cursor.execute(sql)
                # Write the Ingredients records
                sql = ‘INSERT INTO Instructions (recipeID,instructions) VALUES( %s,»%s»)’ %(lastid,instructions)
                cursor.execute(sql)
                # Prompt the user that we are done
                print ‘Donen’
        else:
                print ‘Save abortedn’

 

فهرست ۶-  كدهای تابع افزودن آيتم جديد به پايگاه داده

افزودن

روتین مربوط به افزودن موارد، طولانی‌ترین روتین این مجموعه است که آن را در فهرست ۶ مشاهده می‌کنید، آن را جايگزين خطوط ۱۳ و۱۴ فهرست ۱ كنيد. شروع این روتین و خط‌های ۲ تا ۶ متغیرهای ابتدایی مورد نیاز نظیر نام دستورالعمل، تعداد نفرات و… را تعریف و مقداردهی می‌کند. تنها موردی که شاید به توضیح نياز داشته باشد، دریافت مواد لازم است که در یک حلقه while انجام شده است و هر ورودی کاربر به‌صورت رشته‌ای با جداکننده کاما (،) به انتهای متغیر ings افزوده شده است. این روند تا زمانی که کاربر۰ را وارد کند، ادامه می‌یابد. پس از آن در خطوط ۱۴ تا ۲۱ کل اطلاعات یک بار دیگر برای کاربر نمایش داده می‌شود تا از صحت آن اطمینان حاصل شود.
پس از گرفتن تأیید کاربر، در خطوط ۲۷ تا ۲۹ با تعریف دستورالعمل مورد نیاز، موارد ابتدایی را در جدول Recipes ذخیره می‌کنیم. در خطوط ۳۱ و ۳۲ همان‌گونه که در قسمت قبل دیده‌اید، شماره آخرین رکورد افزوده شده به جدول را استخراج کرده‌ایم. از این رکورد برای مرتبط کردن داده‌های جدول‌هاي Ingredients و Instructions به مقادیر وارد شده در جدول Recipes استفاده کرده‌ایم. ذخیره داده در دو جدول Ingredients و Instructions به ترتیب در خطوط ۳۶ تا ۳۹ و۴۰ تا ۴۳ انجام شده است.  در نهایت، اتمام عملیات ذخیره‌سازی با یک پیغام به کاربر اطلاع داده شده است.فراموش نكنيدكه براي فعال شدن اين بخش بايد كلمه pass در خط ۴۰ فهرست ۱ را با ()ckb.Add   جايگزين كنيد.

حذف

در نهایت به روتین حذف موارد می‌رسیم. همان‌گونه که حدس می‌زنید، در این روتین نیز ابتدا با فراخوانی()ckb.All   همه موارد به کاربر نشان داده شده و در نهایت از او خواسته می‌شود تا آیتم مورد نظر را برای حذف‌کردن انتخاب کند. این روتین در فهرست ۶ آورده شده است.آن را جايگزين خطوط ۱۵ و ۱۶ فهرست ۱ كنيد و برای كار كردن اين كد بايد كلمه pass در خط۴۲ فهرست‌۱ با عبارت زير جايگزين شود:

ckb.All()
temp = raw_input(“What to delete:”)
ckb.Delete(temp)

در این کد هم با استفاده از آرگومان which که شماره انحصاری آیتم را نشان می‌دهد، دستورات sql مورد نیاز را برای حذف آیتم‌ها از جدول‌های Recipes، Ingredients و Instructions تعریف و اجرا کرده‌ایم.دقت کنید که برای ساده‌تر‌شدن کار، ما از بسیاری از روتین‌های کنترل ورودی کاربر، مرتب‌سازی خروجی و بسیاری قابلیت‌های دیگر که می‌توانست چنین برنامه‌ای را کامل‌تر‌کند، صرف‌نظر‌کرده‌ایم. اگرچه وجود این قابلیت‌ها در غالب نرم‌افزارهای تجاری و حرفه‌ای الزامی است، اما پیاده‌سازی آن‌ها بسیار ساده و بدون مشکل خواهد بود. برای نمونه، در هنگام نمایش یا حذف یک مورد بهتر بود که ما شماره آیتم وارد‌شده توسط کاربر را بررسی کنیم تا در محدوده صحیحی قرار داشته باشد یا مثلاً کاربر به جای شماره از حروف استفاده نکرده باشد. که چنين مواردی با روال‌های معمول if قابل پیاده‌سازی است.