zoukankan      html  css  js  c++  java
  • 仿优酷1

    一、需求分析

    1.管理员:

    注册、登录、上传视频、删除视频、发布公告

    2.用户:

    注册、登录、充会员、查看视频、下载免费视频、下载收费视频、查看下载记录、查看公告

    二、程序的架构设计(三层架构)

    1.用户视图层

    与用户交互

    2.接口层

    处理核心业务逻辑

    3.数据层

    对数据进行存取

    三、ORM(对象关系映射)

    将对象映射成数据表中的一条条记录

    类 ----> 表名

    对象 ----> 记录

    对象.属性 ----> 字段

    # 问题1: 每一张表类,都必须定义一个__init__方法,
    # 假设有100张表,就得写100次,无法确定每张表的字段个数,以及字段的名字;
    # 解决1: 通过继承字典类,解决该问题;
    
    # 问题2: 继承的字典无法通过 对象.属性的 取值方式, 对象.属性 = 属性值 增加或修改属性的操作?
    # 解决2: __getattr__解决了取值方式, __setattr__解决了增加或修改属性的方式
    
    class Models(dict, metaclass=OrmMetaClass):
    
        # 对象.属性, 属性没有时触发
        def __getattr__(self, item):
            # print(self)
            return self.get(item)  # {'name': 'tank', 'pwd': '123'}.get('name') ----> tank
    
        # 对象.属性 = 属性值 时触发
        def __setattr__(self, key, value):
            # print(key, value)
            # print(self)  # {'name': 'tank', 'pwd': '123'}
            # 给字典添加键值对的方式
            self[key] = value
    # 问题3: 一张表中只能有一个唯一的主键,在当前表类中,无法控制用户定义类的型?
    # 自定义元类:
    # 解决三件事情 ---》
    # 1、保证一张表必须要有表名  2、保证一张表中只能有一个主键
    # 3、将所有 “字段名” 与 “字段对象” 添加到一个独立的字典中(mappings),
    # 以key(字段名):value(字段对象) , 添加到类的名称空间中,方便后期使用
    
    
    class OrmMetaClass(type):
    
        # __call__ ---> __new__ ----> type.__new__() ---> obj ---> Models
        # 只要定义类就会触发__new__, 因为类也是对象,OrmMetaClass() ---> Models类对象 、User类对象
        def __new__(cls, class_name, class_bases, class_attr):
            # class_name, class_bases, class_attr = args
            # print(f'类名: {class_name}')
            # print(f'基类: {class_bases}')
            # print(f'类的名称空间: {class_attr}')
    
            # 1、过滤Models类
            if class_name == 'Models':
                # 将models类的类名、基类、名称空间原路返回
                return type.__new__(cls, class_name, class_bases, class_attr)
    
            # 2、获取 table 表名,若自定义则获取,没有则默认使用类名
            # dict.get(key) ---> key若有则返回对应的值,若没有则返回默认值 class_name就是默认值
            # 将类名当做表名
            table_name = class_attr.get('table_name', class_name)
    
            # print(table_name)
    
            # 打印修改类名称空间前的  名称空间
            # print(class_attr)
    
            # 主键值: 主键名为 字段名, 比如 主键是 id字段 ---》 id就是主键的名字
            primary_key = None
    
            # 存放字段名与字段对象的字典
            mappings = {}
    
            # 3、保证一张表只能有一个唯一的主键
            # 循环遍历类的名称空间
            for k, v in class_attr.items():
                # print(k, v)
                # 将字段以外的属性过滤掉
                # 判断当前的v是否是字段对象
                if isinstance(v, Field):
                    # print(k, v)
                    # print(v.__dict__)
                    # 4、将所有 “字段名” 与 “字段对象” 添加到一个独立的字典中(mappings)
                    mappings[k] = v
    
                    # 判断字段对象如果有 主键primary_key, 则为primary_key 变量赋值
                    if v.primary_key:
                        # 若第二次进来,primary有值,证明有主键,抛出异常
                        if primary_key:
                            raise TypeError('一张表只能有一个主键')
    
                        # primary_key = k
                        # print(k == v.name, 111111)
                        # 给primary_key变量做一个赋值操作
                        primary_key = v.name
    
            # 5、过滤掉类名称空间中重复的字段属性
            for key in mappings.keys():
                class_attr.pop(key)
    
    
            if not primary_key:
                raise TypeError('必须要有一个主键!!!')
    
            # 6、给类的名称空间,添加table_name, primary_key,mappings属性;
            class_attr['table_name'] = table_name
            class_attr['primary_key'] = primary_key
            class_attr['mappings'] = mappings
    
            # print('*' * 100)
            # print(class_attr)
    
            return type.__new__(cls, class_name, class_bases, class_attr)
    # 定义字段类型: 每个字段都应该有---> 字段名、字段类型、是否为主键、默认值
    class Field:
        def __init__(self, name,
                     column_type,
                     primary_key,
                     default):
            self.name = name
            self.column_type = column_type
            self.primary_key = primary_key
            self.default = default
    
    
    # varchar
    class StringField(Field):
        def __init__(self, name,
                     column_type='varchar(64)',
                     primary_key=False, default=None):
            super().__init__(name, column_type, primary_key, default)
    
    
    # int
    class IntegerField(Field):
        def __init__(self, name,
                     column_type='int',
                     primary_key=False, default=0):
            super().__init__(name, column_type, primary_key, default)

    ORM需要处理的事情:

    1.控制表类的创建  ---> 控制表创建的过程

    2.给表类封装 增、查、改 方法

    四、封装mysql方法类

    import pymysql
    
    
    # MySQL连接类
    class MySQL:
    
        __instance = None
    
        # 单例模式
        @classmethod
        def singleton(cls):
            if not cls.__instance:
                cls.__instance = cls()
    
            return cls.__instance
    
        # 实例化MySQL类时,获取数据库链接对象,获取游标对象
        def __init__(self):
            self.mysql_client = pymysql.connect(
                host='127.0.0.1',
                port=3306,
                user='root',
                password='123456',
                charset='utf8',
                database='orm_demo',
                autocommit=True
            )
    
            self.cursor = self.mysql_client.cursor(
                pymysql.cursors.DictCursor
            )
    
        # 自定义查询方法
        def select(self, sql, args=None):
            # 1、先提交查询sql语句
            # select * from table;
            # select * from table where id=%s;
            self.cursor.execute(sql, args)
    
            # 2、获取返回的查询结果
            # res ---> [{}, {}]
            res = self.cursor.fetchall()
            return res
    
        # 自定义提交sql语句方法,比如: insert、update
        def execute(self, sql, args):
            # 1、提交sql语句
            # insert into table(字段) values(%s);
            try:
                self.cursor.execute(sql, args)
    
            except Exception as e:
                print(e)
    
        def close(self):
            # 先关闭游标
            self.cursor.close()
            # 再关闭数据库连接
            self.mysql_client.close()
  • 相关阅读:
    安装与配置 Elasticsearch
    推荐几个 WebSocket 服务端实现
    GitLab 修改主机名,更换 IP 配置,配置 SMTP
    Choose GitLab for your next open source project
    大数据全栈式开发语言 – Python
    IPC's epoch 6 is less than the last promised epoch 7
    将/home空间从新挂载到/var/lib/docker
    Initialization failed for Block pool <registering> (Datanode Uuid unassigned) service to IP1:8020 Invalid volume failure config value: 1
    查看端口被那个进程占用
    查看java进程启动的详细参数和过程
  • 原文地址:https://www.cnblogs.com/hexianshen/p/12061695.html
Copyright © 2011-2022 走看看