CRM前情

1. django源码settings

1.1 settings源码

 

ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
from django.conf import settings


settings = LazySettings()


class LazySettings(LazyObject):
     def _setup(self, name=None):
        """
        Load the settings module pointed to by the environment variable. This
        is used the first time we need any settings at all, if the user has not
        previously configured the settings manually.
        """
        # 从全局大字典os.environ中获取一个键为ENVIRONMENT_VARIABLE对应的值
        settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  
        self._wrapped = Settings(settings_module)


class Settings(object):
    def __init__(self, settings_module):  # BBS.settings
        # update this dict from global settings (but only for ALL_CAPS settings)
        for setting in dir(global_settings):  # 拿到global_settings文件里面所有的变量名
            if setting.isupper():  # 配置文件中只能写大写的变量名
                setattr(self, setting, getattr(global_settings, setting))
        self.SETTINGS_MODULE = settings_module

        mod = importlib.import_module(self.SETTINGS_MODULE)
        # from BBS import settings
        
         for setting in dir(mod):  # 获取暴露给用户settings配置中的变量名
            if setting.isupper():
                setting_value = getattr(mod, setting)
                setattr(self, setting, setting_value)  # 利用字典的键存在与否 完成用户配置了用用户的,用户没配置用全局
settings源码

1.2 动态导入模块

import importlib

res = 'conf.settings'  
module = importlib.import_module(res)  # 以字符串的形式导入模块
print(module)
print(module.NAME) # 可以得到conf.settings下的NAME的值
动态导入模块

1.3 自定义settings(用户配置的使用用户的,用户没有配置的,使用系统默认的)

# __init__.py:

import importlib
from lib.conf import global_settings
import os

class Settings(object):
    def __init__(self):
        for name in dir(global_settings):
            if name.isupper():
                k = name
                v = getattr(global_settings, name)
                setattr(self, k, v) # 将项目默认的配置文件中所有的配置文件中所有的配置以键值对的形式存入到了settings对象中

        # 从全局的大字典中回去暴露给用户的settings文件路径
        module_path = os.environ.get('xxx')
        module = importlib.import_module(module_path)
        for name in dir(module):
            if name.isupper():
                k = name
                v = getattr(module, name)
                setattr(self, k, v) # 将暴露给用户的配置文件中所有的配置文件中所有的配置以键值对的形式存入到了settings对象中

settings = Settings()
自定义settings

2. ORM复习

'''
    只有queryset对象才能查看sql语句
    print(models.Publish.objects.all().query)
'''
"""
    add,remove,set:三个可以传一个或多个参数  并且即可以是数字也可以是对象
    clear:不传参数 直接清空   
"""
    # 外键字段的增删改查
    '''
    创建create
    '''
    # 传数字
    models.Book.objects.create(title='三国演义', price='199', publish_id=1)
    # 传对象
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(title='水浒传',price='99', publish=publish_obj)

    '''
    修改update
    '''
    # 传数字
    models.Book.objects.filter(pk=1).update(publish_id=2)
    # 传对象
    publish_obj = models.Publish.objects.filter(pk=1).first()
    models.Book.objects.filter(pk=1).update(publish=publish_obj)

    """
    增加add
    """
    # add即可以传数字 也可以传对象  还支持传多个  单个单个的参数 不要传容器类型
    # 传数字
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.add(2)
    # 传对象
    book_obj = models.Book.objects.filter(pk=2).first()
    author_obj = models.Author.objects.filter(pk=1).first()
    book_obj.authors.add(author_obj)

    # 传所有对象
    book_obj = models.Book.objects.filter(pk=1).first()
    author_list = models.Author.objects.all()
    book_obj.authors.add(*author_list)

    """
    删除remove, clear
    """
    # 传数字  在多对多表中删除书的id为1, 作者id为1, 2,3的数据
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.remove(1)
    book_obj.authors.remove(2, 3)
    # 传对象
    book_obj = models.Book.objects.filter(pk=2).first()
    author_obj = models.Author.objects.all()
    book_obj.authors.remove(*author_obj)

    # clear
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.clear()   # 清空当前对象所对应的多对多关系


    """
    修改set
    """
    # 传数字
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.set([3,]) # 设置Book 的id=1的字段的author的值为3
    # 传对象
    book_obj = models.Book.objects.filter(pk=1).first()
    author_list = models.Author.objects.all()
    book_obj.authors.set(author_list)  # 设置author的所有对应Book的id=1
普通增删改查
# 基于对象的跨表查询 (都是子查询)
    # 1.查询书籍是三国演义的出版社的名称
    book_obj = models.Book.objects.filter(title='三国演义').first()
    print(book_obj.publish.name)
    # 2.查询北方出版社出版的所有的书
    publish_obj = models.Publish.objects.filter(name='北方出版社').first()
    print(publish_obj.book_set)  # app01.Book.None 当出现这个结果时,代表少了一个 all()
    print(publish_obj.book_set.all())
    # 3.查询作者是jason的写过的所有的书
    author_obj = models.Author.objects.filter(name='jason').first()
    print(author_obj.book_set.all())
    # 4.查询作者jason的住址
    author_obj = models.Author.objects.filter(name='jason').first()
    print(author_obj.author_detail.addr)
    # 5.查询手机号是111的作者姓名
    author_detail = models.AuthorDetail.objects.filter(phone='111').first()
    print(author_detail.author.name)
基于对象的跨表查询
 # 基于双下划线的跨表查询
    # 1.查询书籍是三国演义的出版社名称
    res = models.Book.objects.filter(title='三国演义').values('publish__name')
    print(res)
    # 2.查询书籍是三国演义的作者姓名
    res = models.Book.objects.filter(title='三国演义').values('authors__name')
    print(res)
    # 3.查询作者jason的手机号
    res = models.Author.objects.filter(name='jason').values('author_detail__phone')
    print(res)
    # 4.查询书籍是三国演义的作者的手机号
    res = models.Book.objects.filter(title='三国演义').values('authors__author_detail__phone')
    print(res)

    # 反向查询
    # 1.查询出版社为北方出版社的所有图书的名字和价格
    res = models.Publish.objects.filter(name='北方出版社').values('book__title', 'book__price')
    print(res)
    # 2.查询作者姓名是jason的手机号
    res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
    print(res)
基于双下划线的跨表查询

 

3. django  admin后台管理使用详细

 3.1 表的注册

admin.site.register(models.Book,BookConfig)
admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)
admin.py中(表的注册)

3.2 增删改查的url

http://127.0.0.1:8000/admin/app01/book/             book表的查看http://127.0.0.1:8000/admin/app01/book/add/         book表的添加http://127.0.0.1:8000/admin/app01/book/3/change/     book表的编辑http://127.0.0.1:8000/admin/app01/book/3/delete/     book表的删除页面        http://127.0.0.1:8000/admin/app01/publish/              publish表的查看http://127.0.0.1:8000/admin/app01/publish/add/          publish表的添加http://127.0.0.1:8000/admin/app01/publish/3/change/     publish表的编辑http://127.0.0.1:8000/admin/app01/publish/3/delete/     publish表的删除页面
增删改查的url

 

 

3.3 五大常用方法

list_display
list_play_links
search_fields
list_filter
actions

3.3.1 list_display控制展示字段

list_display = ['title', 'price', 'publish_date', 'publish']

3.3.2 list_display_links控制跳转字段

list_display_links = ['title','price']

3.2.3 search_fields:或查询

search_fields = ['title', 'price']

3.3.4 list_filter 用于过滤,上下为与关系

 

3.3.5 actions 批量处理函数

def patch_init(self, request, queryset):
    queryset.update(price=666)
patch_init.short_description = '价格批量修改'
actions = [patch_init]

 

4. django admin 启动源码

 4.1 启动源码

django在启动的时候会依次执行每一个应用下的admin.py文件

from django.contrib import admin
INSTALLED_APPS = [
    'django.contrib.admin',]



from django.utils.module_loading import autodiscover_modules
def autodiscover():
    autodiscover_modules('admin', register_to=site)
启动源码

 

4.2 注册源码

admin.site.register(models.Publish) # 仅仅是将注册了的模型表和以模型表为
# 参数实例化产生的对象当做键值对存入了site对象中的_registry字段

class AdminSite(object):
    def __init__(self, name='admin'):
            self._registry = {}  # model_class class -> admin_class instance
    def register(self, model_or_iterable, admin_class=None, **options):
        if not admin_class:
            admin_class = ModelAdmin
        # Instantiate the admin class to save in the registry
        self._registry[model] = admin_class(model)

site = AdminSite()


@python_2_unicode_compatible
class ModelAdmin(BaseModelAdmin):
      # 配置类
    list_display = ('__str__',)
    list_display_links = ()
    list_filter = ()
    ...
注册源码

 

 

5. 实现单例模式

 

1.基于classmethod
2.基于装饰器
3.基于元类__call__
4.基于__new__
5.基于模块

5.1 基于classmethod

class Mysql(object):
    _instance = None
    def __init__(self, host, port):
        self.host = host
        self.port = port
    @classmethod
    def singleton(cls):
        if not cls._instance:
            cls._instance = cls('127.0.0.1', 8080)
        return cls._instance

obj1 = Mysql.singleton()
obj2 = Mysql.singleton()
obj3 = Mysql('192.168.11.11', 8080)
print(id(obj1), id(obj2), id(obj3))     # 1610636363200 1610636363200 1610636363256
基于classmethod

5.2 基于装饰器

def singleton(cls):
    _instance = cls('127.0.0.1', 8080)
    def inner(*args, **kwargs):
        if args or kwargs:
            obj = cls(*args, **kwargs)
            return obj
        return _instance
    return inner

@singleton
class Mysql(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
obj1 = Mysql()
obj2 = Mysql()
obj3 = Mysql('127.0..0', 8080)
print(id(obj1), id(obj2),  id(obj3))   # 2382258537976 2382258537976 2382258540104
基于装饰器

5.3 基于元类__call__

class MymetClass(type):
    def __call__(self, *args, **kwargs):
        if not getattr(self, '_instance'):
            self._instance = super().__call__(*args, **kwargs)
        return self._instance

class Mysql(object, metaclass=MymetClass):
    _instance = None
    def __init__(self, host, port):
        self.host = host
        self.port = port
obj1 = Mysql('127.0.0.1', 8080)
obj2 = Mysql('127.0.0.1', 8000)
print(id(obj1), id(obj2))    # 2501473371584 2501473371584
基于元类`__call__`

5.4 基于__new__

class Mysql(object):
    _instance = None
    def __init__(self, name):
        self.name = name
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
        return cls._instance
obj1 = Mysql('jason')
obj2 = Mysql('egon')
print(id(obj1), id(obj2))    # 1883165918712 1883165918712
print(obj1.name)             # egon
print(obj2.name)             # egon
基于`__new__

5.5 基于模块

# singleton1.py
class Settings(object):
    pass
settings = Settings()


from singleton1 import settings
print(id(settings))         # 2385839183744
from singleton1 import settings
print(id(settings))         # 2385839183744


# singleton2.py
from singleton1 import settings
def func():
    print(id(settings))

    
from singleton1 import settings
from singleton2 import func

print(id(settings))   # 2479206335600
func()                # 2479206335600
基于模块

 

6. 路由分发的本质

 6.1 路由分发的本质

url(r'^test/', ([], None, None))
# 中括号中可以继续Wie路由,这样可以无穷尽的路由

6.2 django admin中的路由源码

url(r'^admin/', admin.site.urls),
# urls看似为一个属性,实则为一个方法, 点击urls结果如下

@property
def urls(self):
    return self.get_urls(), 'admin', self.name
# 点击get_urls(), 结果如下

def get_urls(self):
     urlpatterns = [
            url(r'^$', wrap(self.index), name='index'),
            url(r'^login/$', self.login, name='login'),
            url(r'^logout/$', wrap(self.logout), name='logout'),
            url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
            url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
                name='password_change_done'),
            url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
            url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
                name='view_on_site'),
        ]
    return urlpatterns


# 由上可以推论出路由分发的本质 第一位元组内的第一个值一定为一个列表
django admin的路由源码

6.3 一级路由与二级路由

url(r'^index/', ([
            url(r'^test1/',([
                    url(r'^test1_1', test1_1),
                    url(r'^test1_2', test1_2),
                    url(r'^test1_3', test1_3),
                            ],None, None)),
            url(r'^test2/', test2),
                     ], None, None))
一级路由与二级路由

 

posted on 2019-07-31 09:54  软饭攻城狮  阅读(112)  评论(0编辑  收藏  举报

导航