Python如何使用Rich type和TinyDB构建联系人通讯录

发布时间:2022-08-09 09:30:45 作者:iii
来源:亿速云 阅读:163

Python如何使用Rich type和TinyDB构建联系人通讯录

目录

  1. 引言
  2. 项目概述
  3. 环境准备
  4. Rich库简介
  5. TinyDB简介
  6. 项目结构
  7. 创建联系人模型
  8. 使用TinyDB存储数据
  9. 使用Rich库美化界面
  10. 实现增删改查功能
  11. 添加搜索功能
  12. 添加分页功能
  13. 添加导出功能
  14. 添加导入功能
  15. 添加备份功能
  16. 添加恢复功能
  17. 添加日志功能
  18. 添加错误处理
  19. 添加单元测试
  20. 总结

引言

在现代软件开发中,构建一个功能完善且用户友好的应用程序是非常重要的。Python作为一种广泛使用的编程语言,提供了丰富的库和工具来简化开发过程。本文将介绍如何使用Python中的Rich库和TinyDB来构建一个联系人通讯录应用程序。通过本文,你将学习如何利用Rich库来美化命令行界面,以及如何使用TinyDB来存储和管理联系人数据。

项目概述

本项目旨在构建一个命令行界面的联系人通讯录应用程序。该应用程序将允许用户执行以下操作:

为了实现这些功能,我们将使用Rich库来美化命令行界面,并使用TinyDB来存储联系人数据。

环境准备

在开始项目之前,我们需要确保我们的开发环境中安装了所需的库。我们将使用pip来安装这些库。

pip install rich tinydb

Rich库简介

Rich是一个Python库,用于在终端中创建美观的文本输出。它支持多种功能,包括彩色文本、表格、进度条、语法高亮等。Rich库的主要特点包括:

在本项目中,我们将使用Rich库来美化命令行界面,使联系人通讯录应用程序更加用户友好。

TinyDB简介

TinyDB是一个轻量级的NoSQL数据库,适用于小型应用程序。它使用JSON文件来存储数据,并且具有简单的API,易于使用。TinyDB的主要特点包括:

在本项目中,我们将使用TinyDB来存储和管理联系人数据。

项目结构

在开始编写代码之前,我们需要规划项目的结构。以下是我们将使用的项目结构:

contact_book/
│
├── contact_book/
│   ├── __init__.py
│   ├── models.py
│   ├── database.py
│   ├── ui.py
│   ├── commands.py
│   ├── utils.py
│   └── tests/
│       ├── __init__.py
│       ├── test_models.py
│       ├── test_database.py
│       ├── test_ui.py
│       └── test_commands.py
│
├── main.py
├── requirements.txt
└── README.md

创建联系人模型

首先,我们需要定义一个联系人模型。联系人模型将包含以下字段:

我们将使用Python的dataclasses模块来定义联系人模型。

# contact_book/models.py

from dataclasses import dataclass
from typing import Optional

@dataclass
class Contact:
    id: int
    name: str
    phone: str
    email: Optional[str] = None
    address: Optional[str] = None

使用TinyDB存储数据

接下来,我们需要实现与TinyDB的交互。我们将创建一个Database类来封装与TinyDB的交互。

# contact_book/database.py

from tinydb import TinyDB, Query

class Database:
    def __init__(self, db_path: str = 'contacts.json'):
        self.db = TinyDB(db_path)
        self.contacts_table = self.db.table('contacts')

    def add_contact(self, contact: 'Contact') -> int:
        return self.contacts_table.insert(contact.__dict__)

    def get_contact(self, contact_id: int) -> dict:
        return self.contacts_table.get(doc_id=contact_id)

    def get_all_contacts(self) -> list:
        return self.contacts_table.all()

    def update_contact(self, contact_id: int, contact: 'Contact') -> None:
        self.contacts_table.update(contact.__dict__, doc_ids=[contact_id])

    def delete_contact(self, contact_id: int) -> None:
        self.contacts_table.remove(doc_ids=[contact_id])

    def search_contacts(self, query: str) -> list:
        ContactQuery = Query()
        return self.contacts_table.search(
            (ContactQuery.name.search(query)) |
            (ContactQuery.phone.search(query)) |
            (ContactQuery.email.search(query)) |
            (ContactQuery.address.search(query))
        )

使用Rich库美化界面

现在,我们将使用Rich库来美化命令行界面。我们将创建一个UI类来处理界面的显示。

# contact_book/ui.py

from rich.console import Console
from rich.table import Table

class UI:
    def __init__(self):
        self.console = Console()

    def display_contacts(self, contacts: list) -> None:
        table = Table(title="Contacts")

        table.add_column("ID", justify="right", style="cyan", no_wrap=True)
        table.add_column("Name", style="magenta")
        table.add_column("Phone", style="green")
        table.add_column("Email", style="blue")
        table.add_column("Address", style="yellow")

        for contact in contacts:
            table.add_row(
                str(contact['id']),
                contact['name'],
                contact['phone'],
                contact.get('email', ''),
                contact.get('address', '')
            )

        self.console.print(table)

    def display_message(self, message: str, style: str = "bold green") -> None:
        self.console.print(message, style=style)

    def display_error(self, message: str) -> None:
        self.console.print(f"[bold red]Error: {message}[/bold red]")

实现增删改查功能

接下来,我们将实现添加、删除、更新和查看联系人的功能。我们将创建一个Commands类来封装这些功能。

# contact_book/commands.py

from typing import Optional
from .models import Contact
from .database import Database
from .ui import UI

class Commands:
    def __init__(self):
        self.db = Database()
        self.ui = UI()

    def add_contact(self, name: str, phone: str, email: Optional[str] = None, address: Optional[str] = None) -> None:
        contact = Contact(id=self._generate_id(), name=name, phone=phone, email=email, address=address)
        self.db.add_contact(contact)
        self.ui.display_message("Contact added successfully!")

    def delete_contact(self, contact_id: int) -> None:
        if self.db.get_contact(contact_id):
            self.db.delete_contact(contact_id)
            self.ui.display_message("Contact deleted successfully!")
        else:
            self.ui.display_error("Contact not found!")

    def update_contact(self, contact_id: int, name: Optional[str] = None, phone: Optional[str] = None, email: Optional[str] = None, address: Optional[str] = None) -> None:
        contact = self.db.get_contact(contact_id)
        if contact:
            updated_contact = Contact(
                id=contact_id,
                name=name if name else contact['name'],
                phone=phone if phone else contact['phone'],
                email=email if email else contact.get('email'),
                address=address if address else contact.get('address')
            )
            self.db.update_contact(contact_id, updated_contact)
            self.ui.display_message("Contact updated successfully!")
        else:
            self.ui.display_error("Contact not found!")

    def list_contacts(self) -> None:
        contacts = self.db.get_all_contacts()
        self.ui.display_contacts(contacts)

    def _generate_id(self) -> int:
        contacts = self.db.get_all_contacts()
        return max([contact['id'] for contact in contacts], default=0) + 1

添加搜索功能

为了增强应用程序的功能,我们将添加一个搜索功能,允许用户根据姓名、电话、电子邮件或地址搜索联系人。

# contact_book/commands.py

class Commands:
    # ... (之前的代码)

    def search_contacts(self, query: str) -> None:
        contacts = self.db.search_contacts(query)
        if contacts:
            self.ui.display_contacts(contacts)
        else:
            self.ui.display_message("No contacts found.")

添加分页功能

当联系人数量较多时,我们需要添加分页功能,以便用户可以分页查看联系人列表。

# contact_book/commands.py

class Commands:
    # ... (之前的代码)

    def list_contacts(self, page: int = 1, page_size: int = 10) -> None:
        contacts = self.db.get_all_contacts()
        start = (page - 1) * page_size
        end = start + page_size
        paginated_contacts = contacts[start:end]
        self.ui.display_contacts(paginated_contacts)

添加导出功能

为了方便用户备份联系人数据,我们将添加一个导出功能,允许用户将联系人数据导出为CSV文件。

# contact_book/commands.py

import csv

class Commands:
    # ... (之前的代码)

    def export_contacts(self, file_path: str) -> None:
        contacts = self.db.get_all_contacts()
        with open(file_path, mode='w', newline='') as file:
            writer = csv.DictWriter(file, fieldnames=['id', 'name', 'phone', 'email', 'address'])
            writer.writeheader()
            writer.writerows(contacts)
        self.ui.display_message(f"Contacts exported to {file_path} successfully!")

添加导入功能

为了允许用户从CSV文件导入联系人数据,我们将添加一个导入功能。

# contact_book/commands.py

class Commands:
    # ... (之前的代码)

    def import_contacts(self, file_path: str) -> None:
        try:
            with open(file_path, mode='r') as file:
                reader = csv.DictReader(file)
                for row in reader:
                    contact = Contact(
                        id=int(row['id']),
                        name=row['name'],
                        phone=row['phone'],
                        email=row.get('email'),
                        address=row.get('address')
                    )
                    self.db.add_contact(contact)
            self.ui.display_message(f"Contacts imported from {file_path} successfully!")
        except Exception as e:
            self.ui.display_error(f"Failed to import contacts: {e}")

添加备份功能

为了确保数据安全,我们将添加一个备份功能,允许用户备份联系人数据。

# contact_book/commands.py

import shutil

class Commands:
    # ... (之前的代码)

    def backup_contacts(self, backup_path: str) -> None:
        try:
            shutil.copy2('contacts.json', backup_path)
            self.ui.display_message(f"Contacts backed up to {backup_path} successfully!")
        except Exception as e:
            self.ui.display_error(f"Failed to backup contacts: {e}")

添加恢复功能

为了允许用户从备份中恢复联系人数据,我们将添加一个恢复功能。

# contact_book/commands.py

class Commands:
    # ... (之前的代码)

    def restore_contacts(self, backup_path: str) -> None:
        try:
            shutil.copy2(backup_path, 'contacts.json')
            self.ui.display_message(f"Contacts restored from {backup_path} successfully!")
        except Exception as e:
            self.ui.display_error(f"Failed to restore contacts: {e}")

添加日志功能

为了帮助调试和监控应用程序的运行状态,我们将添加一个日志功能。

# contact_book/utils.py

import logging

def setup_logger(log_file: str = 'contact_book.log') -> logging.Logger:
    logger = logging.getLogger('contact_book')
    logger.setLevel(logging.DEBUG)

    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.DEBUG)

    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    file_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    return logger

commands.py中使用日志功能:

# contact_book/commands.py

from .utils import setup_logger

class Commands:
    def __init__(self):
        self.db = Database()
        self.ui = UI()
        self.logger = setup_logger()

    def add_contact(self, name: str, phone: str, email: Optional[str] = None, address: Optional[str] = None) -> None:
        try:
            contact = Contact(id=self._generate_id(), name=name, phone=phone, email=email, address=address)
            self.db.add_contact(contact)
            self.ui.display_message("Contact added successfully!")
            self.logger.info(f"Added contact: {contact}")
        except Exception as e:
            self.ui.display_error(f"Failed to add contact: {e}")
            self.logger.error(f"Failed to add contact: {e}")

添加错误处理

为了增强应用程序的健壮性,我们将添加错误处理机制。

# contact_book/commands.py

class Commands:
    # ... (之前的代码)

    def delete_contact(self, contact_id: int) -> None:
        try:
            if self.db.get_contact(contact_id):
                self.db.delete_contact(contact_id)
                self.ui.display_message("Contact deleted successfully!")
                self.logger.info(f"Deleted contact with ID: {contact_id}")
            else:
                self.ui.display_error("Contact not found!")
                self.logger.warning(f"Contact not found with ID: {contact_id}")
        except Exception as e:
            self.ui.display_error(f"Failed to delete contact: {e}")
            self.logger.error(f"Failed to delete contact: {e}")

添加单元测试

为了确保代码的正确性,我们将添加单元测试。我们将使用unittest框架来编写测试。

# contact_book/tests/test_models.py

import unittest
from contact_book.models import Contact

class TestContactModel(unittest.TestCase):
    def test_contact_creation(self):
        contact = Contact(id=1, name="John Doe", phone="1234567890", email="john@example.com", address="123 Main St")
        self.assertEqual(contact.id, 1)
        self.assertEqual(contact.name, "John Doe")
        self.assertEqual(contact.phone, "1234567890")
        self.assertEqual(contact.email, "john@example.com")
        self.assertEqual(contact.address, "123 Main St")

if __name__ == '__main__':
    unittest.main()
# contact_book/tests/test_database.py

import unittest
from contact_book.database import Database
from contact_book.models import Contact

class TestDatabase(unittest.TestCase):
    def setUp(self):
        self.db = Database('test_contacts.json')
        self.contact = Contact(id=1, name="John Doe", phone="1234567890", email="john@example.com", address="123 Main St")

    def test_add_contact(self):
        contact_id = self.db.add_contact(self.contact)
        self.assertIsNotNone(contact_id)

    def test_get_contact(self):
        contact_id = self.db.add_contact(self.contact)
        contact = self.db.get_contact(contact_id)
        self.assertEqual(contact['name'], "John Doe")

    def tearDown(self):
        import os
        if os.path.exists('test_contacts.json'):
            os.remove('test_contacts.json')

if __name__ == '__main__':
    unittest.main()

总结

通过本文,我们学习了如何使用Python中的Rich库和TinyDB来构建一个功能完善且用户友好的联系人通讯录应用程序。我们实现了添加、删除、更新、查看、搜索、分页、导出、导入、备份、恢复等功能,并添加了日志和错误处理机制。此外,我们还编写了单元测试来确保代码的正确性。

希望本文对你有所帮助,并激发你进一步探索Python编程的兴趣。Happy coding!

推荐阅读:
  1. python中type的含义和使用方法
  2. 苹果手机如何恢复通讯录联系人呢?怎样恢复

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python tinydb

上一篇:React如何实现监听粘贴事件并获取粘贴板中的截图

下一篇:vue项目搭建及打包运行的方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》