Привет, Фейсал! Во-первых, я все еще новичок в мире данных, в мире программирования или как там вы это называете. Итак, пожалуйста, дайте мне знать, если у вас, ребята, есть какие-либо предложения или критические замечания для меня, чтобы улучшить свои навыки, или если вы просто хотите подружиться со мной, я очень рад этому, спасибо вам в любом случае.

В этой статье я напишу кое-что о своем недавно законченном проекте (на самом деле еще не законченном, я имею в виду, что его можно развивать дальше), как вы можете видеть в заголовке, я расскажу о хранении нескольких контактов компании с программированием на питоне. язык. Вы знаете, когда у вас есть крупный клиент или вы просто хотите найти контакт определенной компании, может быть, потому что вы хотите прорекламировать им свой новый продукт, на самом деле вы связались с ними раньше, но как-то забыли, или вы просто хотите сохранить несколько контакты компании на случай, если они когда-нибудь понадобятся, эта программа для вас!

Без лишних слов, давайте углубимся в программу!!!

База данных CSV

CSV означает значения, разделенные запятыми, я использую CSV-файл в качестве своей базы данных, поэтому все, что вы делаете в программе, например, добавляете данные в базу данных, обновляете некоторые данные, удаляете некоторые данные, будет храниться в CSV-файле. Следовательно, всякий раз, когда вы возвращаетесь к программе, она предоставляет самую последнюю базу данных.

Сводка по применению

Вы когда-нибудь слышали о желтых страницах (Buku Kuning)? Если вы из поколения Z, я не уверен, что вы знаете это, поэтому, если нет, спросите своих родителей (✌️). Раньше Интернет не был таким большим, как сейчас, когда потребители или, может быть, директора компании ищут своего клиента, обычно у них рядом с ним есть желтые страницы. Но в сентябре 2017 года Yell, издатель Желтых страниц в Соединенном Королевстве, объявил, что бизнес будет полностью оцифрован с января 2019 года, что положит конец 51-летнему выпуску издания. Последние копии в Великобритании были размещены 18 января 2019 года.

Итак, в этом проекте я имитирую желтые страницы, но в цифровой версии, используя язык программирования Python. В этом проекте есть четыре основных меню: создание, чтение, обновление и удаление данных из/в базу данных или сокращенно CRUD. Я также добавляю некоторые функции, чтобы сделать программу более мощной, любопытно, какие функции? Давайте сначала поговорим об основных функциях!

Структуры данных

Прежде чем мы перейдем к тому, как выглядит программа, позвольте мне рассказать вам, какой тип данных я использую. Как я уже говорил, я использую файл CSV в качестве моей базы данных, из базы данных я возвращаю свои данные как тип данных словаря, потому что я не обращал внимания на последовательность. Вот как я вызываю свои данные из базы данных, хранящейся в CSV:

    import csv
    # path
    path = r'\dbYellowPages.csv'

    # Read csv file
    file = open(path, 'r')
    reader = csv.reader(file, delimiter=';')

    # columns
    columns = next(reader)

    # make dictionary data type. db as a variable of dictionary data
    db = {'columns':columns}
    for row in reader: # updating dictionary data
        db.update({
            str(row[0]) : [int(row[0]), 
                    str(row[1]),
                    str(row[2]), 
                    str(row[3]),
                    int(row[4]),
                    str(row[5])
                    ]})
    # close program
    file.close()

обратите внимание: это не настоящий путь, вам нужно настроить свой путь в соответствии с тем, где находится CSV, а затем скопировать и вставить его в переменную «путь». А еще это не настоящие данные, я использую фиктивные данные со всего интернета.

Я определил «db» как переменную данных, затем я обновляю одну за другой каждую строку своих данных, используя метод обновления и цикл for. Помните это, как вы можете видеть, я определяю свой ключ так же, как значение [0], которое ссылается на строки в столбце идентификатора, единственная разница заключается в типе данных, строке для моего ключа и целое число для моего значения [0]. ]. Это так полезно. Вы поймете позже.

Перед выходом из программы я поставил метод записи, встроенную в CSV-библиотеку функцию. Поэтому всякий раз, когда вы возвращаетесь к программе, она будет предоставлять самые последние данные.

# Open database in write condition
file = open(path, 'w')

# Keep the database up to date
writer = csv.writer(file, lineterminator='\n', delimiter=';')
columns = list(db.values())[0]
data = list(db.values())[1:]
writer.writerow(columns)
data = list(db.values())[1:]
for i in data:
    writer.writerow(i)
# close Program
file.close()

Функции

Читать меню. В этом меню мы можем увидеть все данные в базе данных. Указываю шесть столбцов, ID, название компании, в какой сфере занимается, в каком городе находится компания, номер телефона и электронную почту. Я также даю вариант, вы можете увидеть данные в деталях. Что означает подробный способ, если вы знаете только идентификатор, но не знаете, что это за компания, в какой сфере бизнеса они занимаются или какой у них адрес электронной почты, вы можете просто ввести идентификатор, и программа предоставит вам точная строка, которую вы ищете, но если идентификатор не существует, программа сообщит вам, что идентификатор не существует.

Двигаясь дальше, я также добавляю дополнительные функции, такие как фильтрация данных на основе сферы деятельности и города и сортировка данных на основе идентификатора и названия компании, на тот случай, если вы знаете только название компании. Фильтрация данных по сфере деятельности и городу очень эффективна. Поэтому всякий раз, когда вам нужно искать компании, которые занимаются определенной сферой бизнеса, или компании, расположенные в определенном городе, вы используете эти мощные функции. Вот как это работает:

# data detailing based on businessField
elif inputChoicesDetail == 'businessField':
  # Available businessField stored in set data type, hence there's no duplication, then convert into list data type
  businessFieldSet = {data[index][2] for index in range(len(data))}
  businessFieldList = list(businessFieldSet)
  # user choose city
  userInput = pyip.inputMenu(prompt="Input the businessField you're looking for\n", choices=businessFieldList, numbered=True)
  # find the keys of dictionary data
  keysTarget = [str(i[0]) for i in data if i[2] == userInput]

  # data target in 2D list based on keysTarget
  dataTarget = [database[i] for i in keysTarget]

  # show dataTarget in tabular format
  print(tabulate.tabulate(dataTarget, headers=columns, tablefmt='github'))

# data detailing based on city
elif inputChoicesDetail == 'City':
  # Available city stored in set data type, hence there's no duplication, the convert into list data type
  citySet = {data[index][3] for index in range(len(data))}
  cityList = list(citySet)
  # user choose city
  userInput = pyip.inputMenu(prompt="Input the city you're looking for\n", choices=cityList, numbered=True)
  # find the keys of dictionary
  keysTarget = [str(i[0]) for i in data if i[3] == userInput]

  # data target in 2D list based on keysTarget
  dataTarget = [database[i] for i in keysTarget]

  # show dataTarget in tabular format
  print(tabulate.tabulate(dataTarget, headers=columns, tablefmt='github'))

Он также работает для фильтрации данных на основе определенного города, для этого нужно всего один шаг: изменить индекс в соответствии с индексом столбца города. Это то, о чем я говорил вам в самом начале: я определяю свой ключ так же, как и значение[0], которое ссылается на строки в столбце ID, единственное отличие — тип данных, строка для моего ключа и целое число для моего value[0] — когда я знаю, что такое идентификатор, это означает, что я могу получить доступ ко всем данным на основе этого идентификатора, поскольку идентификатор также относится к моим ключам, если я могу получить доступ к своим ключам, это означает, что я могу получить доступ ко всем своим данные на основе этих ключей (ID). Надеюсь, вы понимаете, что я пытаюсь сказать… — извините за мой английский —

# sorting based on companyName (A-Z)
elif inputChoicesDetail == 'sorted companyName':
    # sorted company Name
    companyNameList = [data[index][1] for index in range(len(data))]
    companyNameSort = sorted(companyNameList) # order by companyName A-Z #

    # find the keys of dictionary
    keysTarget = []
    for valuesI in companyNameSort: # compare sorted companyName with 2D list[1] which is companyName of database, 
        for valuesJ in data:         # when match, return index[0] which is similar with keys
             if valuesI == valuesJ[1]:
                 keysTarget.append(valuesJ[0])

    # data target in 2D list based on keysTarget
    dataTarget = [database[str(i)] for i in keysTarget]

    # show dataTarget in tabular format
    print(tabulate.tabulate(dataTarget, headers=columns, tablefmt='github'))
                
# sorting based on ID (0-9)
else:
    # sorted ID
    idList = [data[index][0] for index in range(len(data))]
    idSort = sorted(idList) # order by ID 0-9 #

    # find the keys of dictionary
    keysTarget = []
    for valuesI in idSort: # compare sorted ID with 2D list[0] which is ID of each data in database, 
        for valuesJ in data:         # when match, return index[0] which is similar with keys
            if valuesI == valuesJ[0]:
                 keysTarget.append(valuesJ[0])

    # data target in 2D list based on keysTarget
    dataTarget = [database[str(i)] for i in keysTarget]

    # show dataTarget in tabular format
    print(tabulate.tabulate(dataTarget, headers=columns, tablefmt='github'))

Это немного отличается от сортировки по названию компании и идентификатору, но все они имеют одинаковую концепцию, найдите ключи. Сначала я использую «отсортированный» метод для сортировки названий компаний и идентификаторов, а затем играю в игру «найди совпадение» (?) с помощью вложенного for. В принципе, сравните отсортированный список (отсортированное название компании и идентификатор) с самими данными, когда они совпадают, я взял ключи. Поскольку название компании и идентификатор уже были отсортированы ранее, ключи также были отсортированы автоматически, поэтому я показываю данные на основе отсортированных ключей.

Создать меню. В этом меню вы можете добавить данные в базу данных на основе введенного вами идентификатора, если идентификатор уже существует, программа откажет. У нас не может быть дубликатов ID, потому что это испортит базу данных, верно? Затем, если идентификатор не существует, программа поможет вам написать название компании, сферу деятельности, город и т. д. Специально для столбца с номером телефона я ограничиваю максимальное количество цифр до 11 цифр, используя «пока правда».

while True:
   phoneNumber = pyip.inputInt(prompt='input phone number: ')
   if len(str(phoneNumber)) <= 11:
       break
   else:
       print("number of digits of the phone number must be less than or equal to 11 digits")

После того, как вы закончите заполнять название компании, сферу деятельности, город и т. д., программа подскажет, хотите ли вы добавить данные или нет. И отобразит данные, которые вы только что заполнили, на всякий случай, чтобы предупредить пользователей, если они введут неправильные данные. После этого программа покажет все данные в базе данных, последней строкой будут данные, которые вы только что ввели.

Меню обновления. В этом меню вы можете обновлять данные на основе определенных идентификаторов и определенных столбцов. Во-первых, вы должны выбрать, какой идентификатор вы хотите обновить. Допустим, мы хотим обновить ID 12 (ID, который мы только что ввели). Опять же, программа будет гарантировать вам, хотите ли вы продолжать обновление данных или нет. Если «да, я хочу продолжить обновление», то программа спросит вас, какой столбец вы хотите обновить (кроме столбца ID, очевидно, потому что это «первичный ключ», верно?)

Поскольку в этих столбцах есть несколько типов данных, мне нужно разделить новые значения пользовательского ввода на основе типа данных.

# available ID
choices = [data[index][0] for index in range(len(data))]
userInputIndex = pyip.inputInt(prompt='Which ID do you want to update ?\n')
# if userInputIdex does exist in database
if userInputIndex in choices:
      # show row that user want to update
      print(tabulate.tabulate(list([database[str(userInputIndex)]]), headers=columns, tablefmt="github"))
      updateMenuInput = pyip.inputYesNo(prompt='\nDo you want to continue to update the data ? (Yes/No):') 
      if updateMenuInput == 'yes':
            # print columns options
            userInputColumn = pyip.inputMenu(prompt='Which column do you want to update ?\n', choices=columns[1:], numbered=True) # output string
            # if the user selects a column that contains integer data type (phoneNumber)
            if type(database[str(userInputIndex)][columns.index(userInputColumn)]) == int:
                # number of digits of phone number must be less than or equal to 11 digits
                while True:
                    database[str(userInputIndex)][columns.index(userInputColumn)] = pyip.inputInt(prompt='Enter new value:')
                    if len(str(database[str(userInputIndex)][columns.index(userInputColumn)])) <= 11:
                         break
                    else:
                         print("number of digits of the phone number must be less than or equal to 11 digits")      
            # if user choose 'Email' column
            elif userInputColumn == 'Email':
                 database[str(userInputIndex)][columns.index(userInputColumn)] = pyip.inputEmail(prompt='Enter new valu: ')
            # if the user selects a column that contains string data type
            else:
                 database[str(userInputIndex)][columns.index(userInputColumn)] = pyip.inputStr(prompt='Enter new value:', applyFunc=lambda x: x.title(), blockRegexes='1234567890@')
# if ID doesnt exist            
else:
     print("The data you're looking for doesn't exist\n")

Удалить меню. В этом меню вы можете удалить данные на основе ID. Есть два подменю, либо вы удаляете одни данные, либо несколько данных одновременно. Это также полезная функция, вместо того, чтобы удалять данные по одному, вы можете удалить данные более чем по одному за раз, просто написав, какой ID вы хотите удалить. Одна из причин, почему я люблю программирование, это его интегрированность. Я покажу вам, как это выглядит:

Сначала вы должны указать, сколько идентификаторов вы хотите удалить, один или несколько, потому что для этого требуются разные блоки кода. Прежде чем я покажу блок кода, дайте мне закончить демонстрацию. Если вы решите удалить более одного идентификатора, программа отобразит доступный идентификатор, поэтому вам не нужно беспокоиться, если вы не знали идентификатор. А также, если вы уже выбрали один идентификатор, он больше не появится. Например, если я хочу удалить сразу 3 идентификатора, то первый из них имеет идентификатор 0.

Как видите, после того, как я выберу ID 0 в качестве первого, он больше не появится. Так что вам не нужно беспокоиться, если ввод дублируется. Прежде чем вы удалите данные, программа отобразит идентификаторы, которые вы хотите удалить, в табличном формате, чтобы вы могли легко прочитать и перепроверить свой ввод.

Теперь давайте перейдем к блоку кода. Я разделил их, либо удалив только одни данные, либо сразу несколько данных.

# delete data
def deleteMenu(database):
    """Fungsi untuk menghapus item dari database

    Args:
        database (dict): databases yang akan diolah

    Returns:
        database: latest database
    """
    # list of data
    data = list(database.values())[1:]

    # available ID
    choices = [data[index][0] for index in range(len(data))]

    # select delete menu
    while True:
        choices1 = ['Delete data in Yellow Pages database', 'Back to Main Menu']
        userInput = pyip.inputMenu(prompt='Select Delete Menu:\n', choices=choices1, numbered=True)
        if userInput == 'Delete data in Yellow Pages database':
            # ensure user how many ID that user want to delete
            userInput1 = pyip.inputChoice(prompt='How many ID that you want to delete ?\nPlease select one of: one or more than one ? ', 
                             choices=['one', 'more than one'])
            
            # if user want to delete only one ID
            if userInput1 == 'one':
                userInput2 = pyip.inputInt(prompt='Enter ID that you want to delete in database:')
                if userInput2 in choices:
                    # display data that you want to delete in tabular format
                    print(tabulate.tabulate(list([database[str(userInput2)]]), headers=columns, tablefmt="github"))
                    # Ensure user whether to delete or not ?
                    deletingMenuInput = pyip.inputYesNo(prompt='Are you sure want to delete the data ? (Yes/No):')
                    # if 'Yes' delete data from database
                    if deletingMenuInput == 'yes':
                        del database[str(userInput2)]
                        # show database after data is deleted
                        print(tabulate.tabulate(list(database.values())[1:], headers=columns, tablefmt="github"))

                        # notification that data 'Data successfully deleted!'
                        print('\nData successfully deleted!')

                        # datetime object containing current date and time
                        now = datetime.now()
                        # dd/mm/YY H:M:S
                        dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

                        # write record.txt
                        file = open(pathRecord, 'a')
                        file.write(f'(DELETE) User has deleted data with ID number {userInput2} at {dt_string}\n')
                        file.close()
                        
                    else:
                        print('Okey double check your input!\n')
                else:
                    print("ID doesn't exist!")

            # if user want to delete more than one ID
            else:
                # ensure the user what is the exact amount of ID that user want to delete
                userInput3 = pyip.inputInt(prompt='Specify the exact amount of ID that you want to delete ?\n', greaterThan=1, lessThan=len(data))
                userInput4 = []
                # available ID
                choices2 = [data[index][0] for index in range(len(data))]
                for i in range(userInput3):
                    userInput5 = pyip.inputMenu(prompt=f'Enter ID ke-{i+1} that you want to delete: \nThese are the available ID:\n', 
                                                choices=valueInttoStr(choices2), lettered=True)
                    # in order to showing the data that user want to delete
                    userInput4.append(userInput5)
                    # Delete the ID from the list of available ID because of ID has been selected, so that the user does not duplicate input 
                    choices2.remove(int(userInput5))

                # display IDs that user want to delete
                displayDeleteData = [database[i] for i in userInput4]
                print(tabulate.tabulate(displayDeleteData, headers=columns, tablefmt="github"))

                # Ensure user whether to delete or not ?
                deletingMenuInput = pyip.inputYesNo(prompt='Are you sure want to delete the data ? (Yes/No):\n')
                # if 'Yes' delete data from database
                if deletingMenuInput == 'yes':
                    # delete multiple ID
                    for i in userInput4:
                        del database[str(i)]
                    # show database after data is deleted
                    print(tabulate.tabulate(list(database.values())[1:], headers=columns, tablefmt="github"))

                    # notification that data 'Data successfully deleted!'
                    print('\nData successfully deleted!')

                    # datetime object containing current date and time
                    now = datetime.now()
                    # dd/mm/YY H:M:S
                    dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

                    # write record.txt
                    file = open(pathRecord, 'a')
                    file.write(f"(DELETE) User has deleted data with ID number {','.join(userInput4)} at {dt_string}\n")
                    file.close()
                    
                else:
                    print('Okey double check your input!\n')
        # Back to main menu
        else:
            break
    # keep database up to date
    return database

Еще раз, поскольку значение [0] также является моим ключом, я могу легко получить доступ к данным. Таким образом, я могу показать пользователю, какой идентификатор он хочет удалить, просто чтобы убедиться, что пользователь еще раз дважды проверит, хочет ли он удалить данные или нет. После того, как мы удалим идентификаторы 0, 1 и 2, программа покажет последние данные в базе данных.

Журнал базы данных

Как следует из названия, функция журнала базы данных полезна для записи всех действий пользователя от входа в программу до выхода из программы. Журнал базы данных сохраняется в файле .txt. И что еще более мощно, журнал базы данных записывает все действия, например, когда пользователь добавляет, удаляет или изменяет данные о каком идентификаторе, даже в какую дату и в какое конкретно время, также будет записан в этот журнал, очень специфичный! Я покажу тебе.

Блочный код журнала базы данных более или менее совпадает с CSV-файлом, который имеет метод чтения и метод записи. Также есть разница в размещении кода, если в CSV я помещаю метод записи, когда пользователь выходит из программы, а в базе данных журнала я помещаю метод записи в каждое меню добавления, обновления и удаления. Это полезно для записи активности пользователя после того, как он закончил работу с этими меню. Для примера воспользуемся меню добавления.

from datetime import datetime

# second, read path record
pathRecord = r'\recordYellowPages.txt'

# datetime object containing current date and time
now = datetime.now()

# dd/mm/YY H:M:S
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")

# write record.txt
file = open(pathRecord, 'a')
file.write(f'(ADD) User has added data with ID number {userInputIndex} at {dt_string}\n')
file.close()

Вот как выглядит вывод:

Как видите, журнал базы данных точно знает, что вы делаете в программе, когда вы это делаете и какие идентификаторы были изменены. Это так полезно, не так ли?

В любом случае, ребята, вы все думали о том же, что и я? CRUD — это фундаментальная система в любой системе баз данных или, возможно, в любой системе, иногда вам нужно обновить данные, добавить данные, удалить данные или просто просмотреть данные. Я думаю, что мы можем сделать другие программы с системами CURD.

Чтобы получить полный блок кода, вы можете посетить мой профиль GitHub и щелкнуть репозиторий под названием YellowPages, или вы можете просто щелкнуть эту ссылку!

Очень приятно видеть, что вы читаете мою статью до конца, так что спасибо вам за это, и я надеюсь, что у вас все отлично! Увидимся на моем следующем!!!