zoukankan      html  css  js  c++  java
  • 公用插件开发-Day2

    如何实现注册model?

    在app_plug中创建service文件夹,创建v1.py用于接收,封装,和处理model,此处我们首先需要实现的是接收,封装,具体做法如下:

    class BasePlugModel:
        def __init__(self, model_class, site):
            self.model_class = model_class
            self.site = site
    
    
    class AppPlugSite(object):
        def __init__(self):
            self._registry = {}
            self.app_name = "app_plug"
            self.namespace = "app_plug"
    
        def register(self, model_class, app_plug_model_class=BasePlugModel):
            self._registry[model_class] = app_plug_model_class(model_class, self)
    

    在别的app中注册model时只需要:

    v1.site.register(models.UserInfo)
    

    自动生成URL

    对于此类问题肯定要首先解决路由分发的问题,以前运用include函数可以将URL分层管理,进入include源码可以发现,源码如下:

    def include(arg, namespace=None):
        app_name = None
        if isinstance(arg, tuple):
            # Callable returning a namespace hint.
            try:
                urlconf_module, app_name = arg
            except ValueError:
                if namespace:
                    raise ImproperlyConfigured(
                        'Cannot override the namespace for a dynamic module that '
                        'provides a namespace.'
                    )
                raise ImproperlyConfigured(
                    'Passing a %d-tuple to include() is not supported. Pass a '
                    '2-tuple containing the list of patterns and app_name, and '
                    'provide the namespace argument to include() instead.' % len(arg)
                )
        else:
            # No namespace hint - use manually provided namespace.
            urlconf_module = arg
    
        if isinstance(urlconf_module, str):
            urlconf_module = import_module(urlconf_module)
        patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
        app_name = getattr(urlconf_module, 'app_name', app_name)
        if namespace and not app_name:
            raise ImproperlyConfigured(
                'Specifying a namespace in include() without providing an app_name '
                'is not supported. Set the app_name attribute in the included '
                'module, or pass a 2-tuple containing the list of patterns and '
                'app_name instead.',
            )
        namespace = namespace or app_name
        # Make sure the patterns can be iterated through (without this, some
        # testcases will break).
        if isinstance(patterns, (list, tuple)):
            for url_pattern in patterns:
                pattern = getattr(url_pattern, 'pattern', None)
                if isinstance(pattern, LocalePrefixPattern):
                    raise ImproperlyConfigured(
                        'Using i18n_patterns in an included URLconf is not allowed.'
                    )
        return (urlconf_module, app_name, namespace)
    

    大部分地方可以不用管,我们需要了解的是他的返回值,返回值的属性分别为:url关系列表或模块(模块内部必须有urlpatterns属性);app_name;namespace

    了解了返回值之后我们可以自己写一个函数来模仿include函数所做的事,其实这个函数的返回值和include函数的返回值要求相同即可,在AppPlugSite类中创建

        def urls(self):
            """
            创建URL对应关系
            :return: 元组类型:url关系列表或模块(模块内部必须有urlpatterns属性);app_name;namespace
            """
            return self.get_urls(), self.app_name, self.namespace
    

    然后要处理的就是get_urls函数该怎么写,首先要明确的时这个函数的返回值一定是个列表类型,简单的写:

        def get_urls(self):
            """
            封装url至列表
            :return: 装有url的列表
            """
            from django.conf.urls import include
            from django.urls import re_path
            # urlpatterns变量名不能更改,因为include内部实现寻找url时就是查找urlpatterns变量获取
            urlpatterns = [
                # url(r'^$', self.index, name='index'),
                re_path(r'^login/$', self.login, name='login'),
                re_path(r'^logout/$', self.logout, name='logout'),
            ]
            return urlpatterns
    

    然后在urls.py中添加:

    re_path(r'^plug/', v1.site.urls),
    

    这样就添加了一些二级的URL,但是我们所要做的是要对任何数据列表进行增删改查的操作,URL格式应该为:http://127.0.0.1:8000/plug/app01/userinfo/1/delete/ 这样的,这个URL所含的信息有包名,models的类名,还有操作方式和操作对象id

    获取包名和类名的方法为: 类._meta.app_label,类._meta.model_name,这样在BasePlugModel类中再创建:

        def another_urls(self):
            """
            钩子函数,用于自定义额外的URL
            :return:
            """
            return []
    
        def get_urls(self):
            """
            配置最后一段URL用于增删改查等操作
            :return:
            """
            from django.urls import re_path
            # 获取包名和类名,方便日后反向生成URL
            info = self.model_class._meta.app_label, self.model_class._meta.model_name
            urlpatterns = [
                re_path(r'^$', self.list_view, name='%s_%s_list' % info),
                re_path(r'^add/$', self.add_view, name='%s_%s_add' % info),
                re_path(r'^(.+)/delete/$', self.delete_view, name='%s_%s_delete' % info),
                re_path(r'^(.+)/change/$', self.change_view, name='%s_%s_change' % info),
                # re_path(r'^(.+)/detail/$', self.detail_view, name='%s_%s_detail' % info),
            ]
            urlpatterns += self.another_urls()
            return urlpatterns
    
        @property
        def urls(self):
            return self.get_urls()
    

    这样,就可以对任何数据列表进行增删改查的操作。

    在AppPlugSite中的完整的get_urls函数为:

        def get_urls(self):
            """
            封装url至列表
            :return: 装有url的列表
            """
            from django.conf.urls import include
            from django.urls import re_path
            # urlpatterns变量名不能更改,因为include内部实现寻找url时就是查找urlpatterns变量获取
            urlpatterns = [
                # url(r'^$', self.index, name='index'),
                re_path(r'^login/$', self.login, name='login'),
                re_path(r'^logout/$', self.logout, name='logout'),
            ]
            # 根据model动态生成URL
            for model_class, plug_model_obj in self._registry.items():
                # 获取包名和类名
                app_label = model_class._meta.app_label
                model_name = model_class._meta.model_name
                # 拼接URL
                urlpatterns += [re_path(r'^%s/%s/' % (app_label, model_name), include(plug_model_obj.urls)), ]
            return urlpatterns
    

      

  • 相关阅读:
    cocos2d-x学习记录5——CCTransition场景过渡
    cocos2d-x学习记录4——图形绘制
    cocos2d-x学习记录3——CCTouch触摸响应
    cocos2d-x学习记录2——CCAction动作
    cocos2d-x学习记录1——图片显示
    cocos2d-x环境搭建
    自定义CCNode
    cocos2d-x调度器原理
    cocos2d-x动作原理
    cocos2d-x触摸分发器原理
  • 原文地址:https://www.cnblogs.com/yu-jie/p/9405059.html
Copyright © 2011-2022 走看看