zoukankan      html  css  js  c++  java
  • pyramid基本用法

    模板

    alchemy:基础功能加数据库--常用

    starter:只包含pyramid最基本功能,简单模板,无数据库

    zodb:

    创建项目

    pcreate -s alchemy 项目名称

     项目创建完成后进入到项目路径

    python setup.py develop  # 不会把代码复制过去,会在site-packages里创建一个路径,还是回去项目目录里找代码
    
    python setup.py install  # 把项目需要的依赖全部复制到site-packages里,就算是把项目目录删掉都可以用,会导致项目里改代码的话不生效

    查看MyProject.egg-link

    /home/python/.virtualenv/虚拟环境/lib/python2.7/site-packages

    这里有MyProject.egg-link和其它的一些依赖

    依赖包

     打开debug调试

    在development.ini中打开

    debugtoolbar.hosts = 192.168.2.3  # 输入想在哪个ip调试

     development.ini详细介绍

    ###
    # app configuration
    # http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
    ###
    
    [app:main]  # 一个中括号是一个节
    use = egg:MyProject  # egg后面跟项目名称
    
    pyramid.reload_templates = true  # 对模板进行修改后是否自动重载,开发阶段可以用来调试,正式环境会降低渲染速度 
    pyramid.debug_authorization = false  # 认证和权限相关的调试信息
    pyramid.debug_notfound = false  # 找不到页面的时候提示相关信息
    pyramid.debug_routematch = false  # url映射机制调试
    pyramid.default_locale_name = en  # 程序默认语言
    pyramid.includes =        # 可以多条 加载pyramid相关插件
        pyramid_debugtoolbar
        pyramid_tm
    
    sqlalchemy.url = sqlite:///%(here)s/devdata.db
    # sqlalchemy.url = mysql://root:mysql@localhost:3306/pyramid_myproject?charset=utf8
    # By default, the toolbar only appears for clients from IP addresses
    # '127.0.0.1' and '::1'.
    # debugtoolbar.hosts = 127.0.0.1 ::1  # 调试工具条 只能在本地使用
    
    ###
    # wsgi server configuration
    ###
    
    [server:main]
    use = egg:waitress#main
    host = 192.168.230.128  # 监听ip
    port = 5678  # 端口
    
    ###
    # logging configuration
    # http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
    ###
    
    [loggers]
    keys = root, myproject, sqlalchemy
    
    [handlers]
    keys = console
    
    [formatters]
    keys = generic
    
    [logger_root]
    level = INFO
    handlers = console
    
    [logger_myproject]
    level = DEBUG
    handlers =
    qualname = myproject
    
    [logger_sqlalchemy]
    level = INFO
    handlers =
    qualname = sqlalchemy.engine
    # "level = INFO" logs SQL queries.
    # "level = DEBUG" logs SQL queries and results.
    # "level = WARN" logs neither.  (Recommended for production systems.)
    
    [handler_console]
    class = StreamHandler
    args = (sys.stderr,)
    level = NOTSET
    formatter = generic
    
    [formatter_generic]
    format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s

     初始化数据

    initialize_[项目名称]_db development.ini

    存储模型设计

    model.py

    class Users(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)  # Column固定用法
        name = Column(Unicode(255), unique=True)
        password = Column(Unicode(255))
        email = Column(Unicode(255), unique=True)
        group_id = Column(Integer)
    
        def __init__(self, name, password, email, group_id):
            self.name = name
            self.password = password
            self.email = email
            self.group_id = group_id

     注册到initializedb.py中

    import os
    import sys
    import transaction
    
    from sqlalchemy import engine_from_config
    
    from pyramid.paster import (
        get_appsettings,
        setup_logging,
        )
    
    from ..models import (
        DBSession,
        MyModel,
        Users,
        Base,
        )
    
    
    def usage(argv):
        cmd = os.path.basename(argv[0])
        print('usage: %s <config_uri>
    '
              '(example: "%s development.ini")' % (cmd, cmd))
        sys.exit(1)
    
    
    def main(argv=sys.argv):
        if len(argv) != 2:
            usage(argv)
        config_uri = argv[1]
        setup_logging(config_uri)
        settings = get_appsettings(config_uri)
        engine = engine_from_config(settings, 'sqlalchemy.')
        DBSession.configure(bind=engine)
        Base.metadata.create_all(engine)
        with transaction.manager:
            # model = MyModel(name='one', value=1)
            # DBSession.add(model)
            admin = Users()
            admin.name = 'admin'
            admin.password = 'admin'
            admin.email = '88983860@qq.com'
            DBSession.add(admin)

    删除原来的devdata.db,重新初始化数据库

     数据存储类型设计

    多对多,多表关联

    自关联

    # -*- coding:UTF-8 -*-
    from datetime import datetime
    from sqlalchemy import (
        Table,          # 创建关联表的时候要导入
        Column,
        ForeignKey,     # 引用外键
        Integer,        # 整型
        Text,           # 文本类型
        Unicode,        # Unicode类型
        DateTime,       # 时间类型
        Float,          # 浮点型
        )
    
    from sqlalchemy.ext.declarative import declarative_base
    
    from sqlalchemy.orm import (
        scoped_session,
        sessionmaker,
        relationship,  # 引用关联数据
        )
    
    from zope.sqlalchemy import ZopeTransactionExtension
    
    DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
    Base = declarative_base()
    
    
    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)  # primary_key 主键
        name = Column(Unicode(255), nullable=False, unique=True)  # nullable=False
                                                                  # 不允许为空 unique 唯一
        password = Column(Unicode(255), nullable=False)
        email = Column(Unicode(255), unique=True)
        group_id = Column(Integer, ForeignKey('groups.id'), nullable=False)  # 关联外键groups的id
        group = relationship('Group', backref='users')
        # 可以使用User的实例对象+".group"查询Group的数据,
        #  backref可以使用Group的实例对象查询User的数据,
        # 以列表形式返回 相当于在Group里写users = relationship('User')
    
    # 创建关联中间表
    # 中间表 = Table(表名, Base.metadata,字段1,字段2....)
    # Base.metadata 固定用法
    group_permisson = Table('group_permission', Base.metadata,
        Column('group_id', Integer, ForeignKey('groups.id'), primary_key=True),  # 字段前要加字段名称
        Column('permission_id', Integer, ForeignKey('permissions.id'),
               primary_key=True)
                            )
    
    class Group(Base):
        __tablename__ = 'groups'
        id = Column(Integer, primary_key=True)
        name = Column(Unicode(255), nullable=False)
    
        permission = relationship('Permission', secondary='group_permission',  # 从表关联
                                  backref='groups')
    
    class Permission(Base):
        __tablename__ = 'permissions'
        id = Column(Integer, primary_key=True)
        name = Column(Unicode(255), nullable=False)
    
    class Item(Base):
        __tablename__ = 'items'
        id = Column(Integer, primary_key=True)
        name = Column(Unicode(255), nullable=False, unique=True)
        description = Column(Text)
        price = Column(Float, nullable=False, default=0.00)
    
        category_id = Column(Integer, ForeignKey('categories.id'), nullable=False)
        category = relationship('Category', backref='items')
    
    class Category(Base):
        __tablename__ = 'categories'
        id = Column(Integer, primary_key=True)
        name = Column(Unicode(255), nullable=False, unique=True)
        parent_id = Column(Integer, ForeignKey('categories.id'), nullable=True)
        parent = relationship('Category', remote_side=[id],   # 外键是自己的时候需要加入remote_side
                              backref='children')
    
    class ItemImage(Base):
        __tablename__ = 'images'
        id = Column(Integer, primary_key=True)
        path = Column(Unicode(255), nullable=False)
        item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
        item = relationship('Item', backref='images')
    
    class Comment(Base):
        __tablename__ = 'comments'
        id = Column(Integer, primary_key=True)
        user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
        user = relationship('User', backref='comments')
        item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
        item = relationship('Item', backref='comments')
    
        rank = Column(Integer, nullable=False, default=3)
        content = Column(Text)
    
    cart_item = Table('cart_item', Base.metadata,
        Column('cart_id', Integer, ForeignKey('carts.id'), primary_key=True),
        Column('item_id', Integer, ForeignKey('items.id'), primary_key=True)
                      )
    
    class Cart(Base):
        __tablename__ = 'carts'
        id = Column(Integer, primary_key=True)
    
        items = relationship('Item', secondary='cart_item')
        user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
        user = relationship('User', backref='cart')
    
    order_item = Table('order_item', Base.metadata,
        Column('order_id', Integer, ForeignKey('orders.id'), primary_key=True),
        Column('item_id', Integer, ForeignKey('items.id'), primary_key=True)
                   )
    
    class Order(Base):
        __tablename__ = 'orders'
        id = Column(Integer, primary_key=True)
        user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
        user = relationship('User')
    
        items = relationship('Item', secondary='order_item')
        add_time = Column(DateTime, nullable=False, default=datetime.now())
        address = Column(Unicode(255), nullable=False)
        telephone = Column(Unicode(25), nullable=False)

     配置路由

     __init__.py

    # -*- coding:UTF-8 -*-
    from pyramid.config import Configurator
    from sqlalchemy import engine_from_config
    
    from .models import (
        DBSession,
        Base,
        )
    
    
    def main(global_config, **settings):
        """ This function returns a Pyramid WSGI application.
        """
        engine = engine_from_config(settings, 'sqlalchemy.')
        DBSession.configure(bind=engine)
        Base.metadata.bind = engine
        config = Configurator(settings=settings)
        config.add_static_view('static', 'static', cache_max_age=3600)  # 静态资源
        config.add_route('home', '/')  # url映射 对应home主页
        config.add_route('category', '/category')  # url映射 对应category页面
        config.scan()
        return config.make_wsgi_app()

    视图函数views.py函数中

    # -*- coding:UTF-8 -*-
    from pyramid.response import Response
    from pyramid.view import view_config
    
    
    from .models import (
        DBSession,
        )
    
    
    @view_config(route_name='home', renderer='templates/mytemplate.pt')
    def my_view(request):
        # try:
        #     one = DBSession.query(MyModel).filter(MyModel.name == 'one').first()
        # except DBAPIError:
        #     return Response(conn_err_msg, content_type='text/plain', status_int=500)
        return {'one': 'one', 'project': '我是天才'}
    
    
    @view_config(route_name='category', renderer='string')  # route_name对应__init__.py中的config.add_route('category', '/category')
    def category_view(request):
        return 'This is category!'

    使用视图类view_defaults

    创建views文件夹

     创建base.py文件

    import logging
    from pyramid.httpexceptions import HTTPFound, HTTPBadRequest, HTTPServerError, 
        HTTPForbidden, HTTPUnauthorized
    import json
    
    log = logging.getLogger(__name__)
    
    
    class Base(object):
        def __init__(self, request):
            self.request = request
    
    
    class CBase(Base):
        def __init__(self, request):
            Base.__init__(self, request)

    创建视图控制器categories.py

    # -*- coding:UTF-8 -*-
    from pyramid.response import Response
    from pyramid.view import view_config, view_defaults
    from myshop.lib import category  # 引用category数据文件
    from base import CBase
    
    ctrl = 'categories'
    
    # @view_config(route_name='home', renderer='templates/mytemplate.pt')
    @view_defaults(route_name='/')  # url映射对应__init__.py中的config.add_route('/', '/{ctrl}/{action}')
    class categories(CBase):
        def __init__(self, request):
            CBase.__init__(self, request)
            self.request.title = '分类'
    
        @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),  # 对应控制器文件和方法
                     renderer="mytemplate.html")
        def view(request):
            category_list = category.get_category_list()
            return {'one': 'one', 'project': category_list}

    __init__.py文件中修改路由

    # -*- coding:UTF-8 -*-
    from pyramid.config import Configurator
    from sqlalchemy import engine_from_config
    
    from myshop.models import (
        DBSession,
        Base,
        )
    
    
    def main(global_config, **settings):
        """ This function returns a Pyramid WSGI application.
        """
        engine = engine_from_config(settings, 'sqlalchemy.')
        DBSession.configure(bind=engine)
        Base.metadata.bind = engine
        config = Configurator(settings=settings)
        config.add_renderer(".html", 'pyramid.mako_templating.renderer_factory')
        config.add_static_view('static', 'static', cache_max_age=3600)  # 静态资源
        # config.add_route('home', '/')  # url映射 对应home主页
        # config.add_route('category', '/category')  # url映射 对应category页面
        config.add_route('/', '/{ctrl}/{action}')  # url映射 对应category页面
        config.scan()
        return config.make_wsgi_app()
    带参数路由

    配置url映射

    config.add_route('/', '/{ctrl}/{action}/{id}')  # url映射 携带id参数

    视图函数views/item.py中接收参数

    # -*- coding:UTF-8 -*-
    from pyramid.response import Response
    from pyramid.view import view_config, view_defaults
    from myshop.lib import category
    from base import CBase
    
    ctrl = 'item'
    
    # @view_config(route_name='home', renderer='templates/mytemplate.pt')
    @view_defaults(route_name='/')
    class item(CBase):
        def __init__(self, request):
            CBase.__init__(self, request)
            self.request.title = '商品'
    
        @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                     renderer="item.html")
                     # renderer="string")
        def view(self):
            id = self.request.matchdict.get('id')  # 接收id
            result = {}
            result['id'] = id
            return result

    渲染到模板item.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>${id}</h1>
    </body>
    </html>

    模板引擎换成mako以及后缀换成'.html'

    1. 在配置文件development.ini中,添加上:

    mako.directories = [project name]:[root path]

    mako.directories = myshop:templates  # 更改为mako模板 mako.directories = [project name]:[root path] 项目名:html文件目录
    mako.strict_undefined = true

    project name是你项目的名称

    root path 是你模板文件存放的根目录

    跟多关于mako的设置: https://pyramid.readthedocs.io/en/1.3-branch/narr/environment.html#mako-template-render-settings

    2. 修改项目的__init__.py文件,在main函数中添加上:

    config.add_renderer('.html', 'pyramid.mako_templating.renderer_factory')

    凡是使用.html结尾的模板,都会使用mako引擎

    3. 当在View.py中,使用.html的模板,就会使用mako模板引擎了。

    @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                     renderer="mytemplate.html")
        def view(request):
            # try:
            #     one = DBSession.query(MyModel).filter(MyModel.name == 'one').first()
            # except DBAPIError:
            #     return Response(conn_err_msg, content_type='text/plain', status_int=500)
            return {'one': 'one', 'project': 'TTTTT'}

     出错

    File "/home/python/.virtualenvs/pyramid_py2/local/lib/python2.7/site-packages/mako/lookup.py", line 263, in get_template
        "Cant locate template for uri %r" % uri
    TopLevelLookupException: Cant locate template for uri 'mytemplate.html'

    development.int文件里mako配置的时候不能在后面加注释

    mako.directories = myshop:templates  # 更改为mako模板 mako.directories = [project name]:[root path] 项目名:html文件目录

    导致找不到模板

    # 更改为mako模板 mako.directories = [project name]:[root path] 项目名:html文件目录
    mako.directories = myshop:templates

    解决

    认证和权限

    配置__init__.py

    # -*- coding:UTF-8 -*-
    from pyramid.config import Configurator
    from pyramid.authentication import AuthTktAuthenticationPolicy  # 认证
    from pyramid.authorization import ACLAuthorizationPolicy        # 权限
    from pyramid.security import Allow
    from sqlalchemy import engine_from_config
    from myshop.lib import user
    from myshop.models import (
        DBSession,
        Base,
        )
    
    def groupfinder(userid, request):
        """每当用户登录的时候,每当认证机制检查用户是否存在时都会调用下这个函数"""
        print("*" * 100)
        user_info = user.get_user_by_id(userid)  # 查询登录账户信息
        if user_info:
            return [user.group.id]
        return None
    
    class RootFactory(object):   # 创建RootFactory类
        def __init__(self, request):
            """读取所有权限"""
            group_list = user.get_group_list()  # 查询所有的组
            self.__acl__ = []  # 准备acl列表
            for group in group_list:
                for permission in group.permissions:
                    # 给acl列表添加元祖,  1.Allow 允许或拒绝 需要导入Allow库 2.为了不和其它id冲突 添加g:的标识符 3.权限名称
                    self.__acl__.append(
                        (Allow, 'g:' + str(group.id), permission.name)
                    )
    
    
    def main(global_config, **settings):
        """ This function returns a Pyramid WSGI application.
        """
        engine = engine_from_config(settings, 'sqlalchemy.')
        DBSession.configure(bind=engine)
        Base.metadata.bind = engine
        # 权限和授权
        # 认证机制
         authn_policy = AuthTktAuthenticationPolicy(
                     'secret',  # 加密密钥
                     callback = groupfinder,  # 用于查询用户属于哪个用户组,以及这个用户是否存在
                     hashalg = 'sha512'  # hashalg算法,用什么方式进行加密
                        )
    
        # 授权机制
        authz_policy = ACLAuthorizationPolicy()
    
        # config = Configurator(settings=settings)
        # config配置里添加权限
        config = Configurator(settings=settings, root_factory='myshop.RootFactory')
        # 添加认证机制到config
        config.set_authentication_policy(authn_policy)
        # 添加授权机制
        config.set_authorization_policy(authz_policy)
    
        config.add_renderer(".html", 'pyramid.mako_templating.renderer_factory')
        config.add_static_view('static', 'static', cache_max_age=3600)  # 静态资源
        # config.add_route('home', '/')  # url映射 对应home主页
        # config.add_route('category', '/category')  # url映射 对应category页面
        config.add_route('/', '/{ctrl}/{action}*pa')  # url映射 对应控制器-方法 页面
        config.add_route('index', '/{action:.*}')  # url映射 对应控制器-方法 页面
        config.scan()
        return config.make_wsgi_app()

    RootFactory要做的事

    查出user.id ---> 通过user查出组 user.group.id -> 保存起来 save it

    查出组的权限 group.permission ---->  对比视图函数权限  view(permission=???)   检查成功则说明有这个权限,继续访问这个视图

    RootFacory里就是要查出哪个组有哪个权限的信息,然后告诉pyramid这个框架

    给item视图加权限

    # -*- coding:UTF-8 -*-
    from pyramid.response import Response
    from pyramid.view import view_config, view_defaults
    from myshop.lib import category
    from base import CBase
    
    ctrl = 'item'
    
    # @view_config(route_name='home', renderer='templates/mytemplate.pt')
    @view_defaults(route_name='/')
    class item(CBase):
        def __init__(self, request):
            CBase.__init__(self, request)
            self.request.title = u'商品'
    
        @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                     renderer="item.html", permission='item')
                     # renderer="string")
        def view(self):
            id = self.request.params.get('id')  # 接收id
            item_info = category.get_item_by_id(id)
            return {'item':item_info}

    登录有权限的账号发现

     如图:如果没有添加商品得权限则不让添加商品按钮显示

    model.py中给user添加校验方法

    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)  # primary_key 主键
        name = Column(Unicode(255), nullable=False, unique=True)  # nullable=False
                                                                  # 不允许为空 unique 唯一
        password = Column(Unicode(255), nullable=False)
        email = Column(Unicode(255), unique=True)
        group_id = Column(Integer, ForeignKey('groups.id'), nullable=False)  # 关联外键groups的id
        group = relationship('Group', backref='users')
        # 可以使用User的实例对象+".group"查询Group的数据,
        #  backref可以使用Group的实例对象查询User的数据,
        # 以列表形式返回 相当于在Group里写users = relationship('User')
    
        def has_permission(self, permission):
            # import pdb;pdb.set_trace()
            for perm in self.group.permissions:
                if perm.name == permission:
                    return True
            return False

    然后再视图模板中调用该方法

    <ul class="menu_r">
                <li><a href="${request.route_path('index', ctrl='', action='',pa=())}">首页</a></li>
                % if request.title==u'分类':
                    % if request.user.has_permission('item'):
                        <li><a href="#"  onclick="itemAdd()">添加商品</a></li>
                    % endif
                % endif
            </ul>

    单步调试

    在需要调试的地方引用pdb;pdb_set_trace()

    此处__init.py中的groupfinder方法需要调试

    def groupfinder(userid, request):
        """每当用户登录的时候,每当认证机制检查用户是否存在时都会调用下这个函数"""
        import pdb;pdb.set_trace()
        user_info = user.get_user_by_id(userid)  # 查询登录账户信息
        if user_info:
            return [user_info.group.id]
        return None

    登录账号然后查看终端

     此处可以打印下id等查看

    也可以输入n进行下一步,一步一步调试

    调试后发现返回的只是一个用户组的id,且id是整型 与RootFactory中__acl__定义的不一致

    def groupfinder(userid, request):
        """每当用户登录的时候,每当认证机制检查用户是否存在时都会调用下这个函数"""
        print("*" * 100)
        user_info = user.get_user_by_id(userid)  # 查询登录账户信息
        if user_info:
            return [user.group.id]  # 与__acl__定义的标识符不一致
        return None
    
    class RootFactory(object):   # 创建RootFactory类
        def __init__(self, request):
            """读取所有权限"""
            group_list = user.get_group_list()  # 查询所有的组
            self.__acl__ = []  # 准备acl列表
            for group in group_list:
                for permission in group.permissions:
                    # 给acl列表添加元祖,  1.Allow 允许或拒绝 需要导入Allow库 2.为了不和其它id冲突 添加g:的标识符 3.权限名称
                    self.__acl__.append(
                        (Allow, 'g:' + str(group.id), permission.name)  
                    )

    修改为

    def groupfinder(userid, request):
        """每当用户登录的时候,每当认证机制检查用户是否存在时都会调用下这个函数"""
        # import pdb; pdb.set_trace()  # 断点调试
        user_info = user.get_user_by_id(userid)  # 查询登录账户信息
        if user_info:
            return ['g:' + str(user_info.group.id)]  # 与__acl__定义的标识符保持一致
        return None

    可以进入页面了

     登录时把user信息存入request

    __init__.py配置config

    def get_user(request):
        user_id = unauthenticated_userid(request)
        user_info = user.get_user_by_id(user_id)
        return user_info
    
    def main(global_config, **settings):
        """ This function returns a Pyramid WSGI application.
        """
        .
        .
        .
         # 添加授权机制
        config.set_authorization_policy(authz_policy)
        # 添加用户信息到request
        config.set_request_property(get_user,  # 回调函数
                                    'user',   # 此处写user就是request.user 写u就是request.u
                                    reify=True)  # 为True的时候会把登录用户保存下来 不需要每次区查询

     html模板里用request.user渲染数据

    <span  class="fl">
             ${request.user.name},欢迎您的到来
    </span>

     DBSession存入request

    # 添加DBSession到request
        config.set_request_property(lambda request: DBSession,
                                    'db',
                                    reify=True)

    用的时候需要传入request

    def get_category_list(request):
        result = request.db.query(Category).filter_by(parent=None).all()
        return result

     ValueError: renderer was passed non-dictionary as value:渲染器以非字典形式作为值传递

    做添加商品页面时出现错误

    视图函数中item.py

     @view_config(match_param=('ctrl=%s' % ctrl, 'action=item_add'),
                     renderer="itemadd.html")
        def item_add(self):
    
            category_id = self.request.params.get('category_id','')
            print(category_id)
            return category_id

     解决方法-使用字典传值

     @view_config(match_param=('ctrl=%s' % ctrl, 'action=item_add'),
                     renderer="itemadd.html")
        def item_add(self):
            result = {}
            result['category_id'] = self.request.params.get('category_id', '')
            print(result)
            return result
  • 相关阅读:
    day 66 crm(3) 自创组件stark界面展示数据
    day 65 crm(2) admin源码解析,以及简单的仿造admin组件
    用 Python+nginx+django 打造在线家庭影院
    django -admin 源码解析
    day 64 crm项目(1) admin组件的初识别以及应用
    云链接 接口不允许 情况 解决方法 mysql Host is not allowed to connect to this MySQL server解决方法
    day 56 linux的安装python3 ,虚拟环境,mysql ,redis
    day55 linux 基础以及系统优化
    Codeforces 989 P循环节01构造 ABCD连通块构造 思维对云遮月参考系坐标轴转换
    Codeforces 990 调和级数路灯贪心暴力 DFS生成树两子树差调水 GCD树连通块暴力
  • 原文地址:https://www.cnblogs.com/yifengs/p/12243553.html
Copyright © 2011-2022 走看看