19 Jul 18 Admin

19 Jul 18

一、计划

1 CRM

   stark组件(一周)

   权限,CRM (3天)

 

2 路飞

  restframework (2-3天)

  vue-cli

  luffy之支付系统,redis (一周)

 

3 爬虫

 

4 flask

 

5 linux

 

二、Django回顾

1 url控制器+MTV

 

2 Ajax

  a. ContentType(详见item 7)

 

3 forms组件

 

4 cookie,session

  def foo(request):

    request.session["name"]="egon"

    return balabala

 

5 用户认证组件

 

6 中间件

  a. cookie/session 和url的中间件很重要,要看源码

 

7 ContentType (请求体的编码类型)(*******)

  https://www.cnblogs.com/yuanchenqi/articles/9070966.html

  a. application/x-www-form-urlencoded

     1)在form和ajax提交POST请求时,如果不特意指定enctype(form)或contentType(ajax),默认使用的编码类型

     2)请求体:user=yuan&age=22;浏览器在解析请求头时,查看到编码类型,然后在用该编码类型对应的请求体数据样式,将数据进行相应提取展示

     3) 请求格式

        "

        POST /index  HTTP/1.1

       contentType:application/x-www-form-urlencoded

 

        name=yuan&pwd=123

        "

 

  b. multipart/form-data

     1) 使用表单上传文件时,必须让<form> 表单的enctype 等于multipart/form-data

 

  c. text/plan

     1) form表单只支持以上三种contentType(application/x-www-form-urlencoded,multipart/form-data,ext/plan),不支持application/json等

     2) text/pam基本上不被使用

 

  d. application/json

     1) request.POST只解析application/x-www-form-urlencoded;即如果用application/json编码格式提交数据,print(request.POST)为空。

     2)处理该情况,可以从request.body(为经处理的原始数据,bytes类型)中提取数据

 

  e. 用ajax发送json数据时,两种处理数据的方式

     1) 在html中用application/json这种contentType发送json格式数据,在views中从request.body中提取数据(解码,loads)

        d=json.loads(request.body.decode("utf8"))

     2)在html中依据用默认的contentType(application/x-www-form-urlencoded)发送数据,但做如下处理

        data:{xxx:JSON.stringify({a:1,b:2})},

 

8 如果有传来多个数据(checkbox,select multiple),用getlist取出相应数据

  a. checkbox

  <input type="text" name="user" value="yuan">

  <input type="checkbox" name="hobby" value="1"> 篮球

  <input type="checkbox" name="hobby" value="2"> 足球

  <input type="checkbox" name="hobby" value="3"> 彩色球

 

  b. select multiple

  <select multiple name="xxx">

     <option value="1">111</option>

     <option value="2">222</option>

     <option value="3">333</option>

  </select>

 

  c. 请求体格式

     user=yuan&hobby=[1,2,3]&xxx=[1,2,3]

 

  d. 在Django的views中取出相应数据

    request.POST.get("user")

     request.POST.getlist("hobby")

 

9 Others

  a. Django中response的一定是HttpResponse中的一类(HttpResponse,JsonResponse,render,redirect)

  b. Django一般比较适合大项目,而flask一般比较适合小精型项目

  c. request.meta :封装了请求头信息的字典

  d. wsgiref, 收发消息;将字符串封装成request对象,将response对象转换成字符串

  e. 浏览器只能识别HTML, CSS, JS

 

三、admin的使用

https://www.cnblogs.com/yuanchenqi/articles/8323452.html

1 Admin:Django下的后台数据管理的web页面

  # 每个注册过的表对应四个url

   http://127.0.0.1:8000/admin/app01/publish/

   http://127.0.0.1:8000/admin/app01/publish/add/

   http://127.0.0.1:8000/admin/app01/publish/1/change/

   http://127.0.0.1:8000/admin/app01/publish/1/delete/

 

2 admin的定制

  a 方法

    1) 方法一

    class UserAdmin(admin.ModelAdmin):

        list_display = ('user', 'pwd',)

 

    admin.site.register(models.UserInfo, UserAdmin)  # 第一个参数可以是列表

 

    2)方法二

   @admin.register(models.UserInfo) # 第一个参数可以是列表

    class UserAdmin(admin.ModelAdmin):

        list_display = ('user', 'pwd',)

 

  b 可定制的功能

    1)list_display: 列表时,定制显示的列。

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        list_display = ('user', 'pwd', 'xxxxx')

 

        def xxxxx(self, obj):

            return "xxxxx"

 

    2)list_display_links:列表时,定制列可以点击跳转。

    @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        list_display = ('user', 'pwd', 'xxxxx')

        list_display_links = ('pwd',)

 

    3)list_filter:列表时,定制右侧快速筛选。

       # 一般用于一对多或多对多关系中

 

    4)list_select_related:列表时,连表查询是否自动select_related

 

    5)list_editable:列表时,可以编辑的列

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        list_display = ('user', 'pwd','ug',)

        list_editable = ('ug',)

 

    6)search_fields:列表时,模糊搜索的功能

       #列表中可以排多个值,是一种或的关系

    @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

 

        search_fields = ('user', 'pwd')

 

    7)date_hierarchy:列表时,对Date和DateTime类型进行搜索

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

 

        date_hierarchy = 'ctime'

 

    8)inlines:详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除

    class UserInfoInline(admin.StackedInline): # TabularInline

        extra = 0

        model = models.UserInfo

 

    class GroupAdminMode(admin.ModelAdmin):

        list_display = ('id', 'title',)

        inlines = [UserInfoInline, ]

 

    9)action:列表时,定制action中的操作;通过定制批量处理函数

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

 

        # 定制Action行为具体方法

        def func(self, request, queryset):

            print(self, request, queryset)

           print(request.POST.getlist('_selected_action'))

 

        func.short_description = "中文显示自定义Actions"

        actions = [func, ]

 

        # Action选项都是在页面上方显示

        actions_on_top = True

        # Action选项都是在页面下方显示

        actions_on_bottom = False

 

        # 是否显示选择个数

       actions_selection_counter = True

 

    10)定制HTML模板

    add_form_template = None

    change_form_template = None

    change_list_template = None

   delete_confirmation_template = None

    delete_selected_confirmation_template = None

    object_history_template = None

 

    11)raw_id_fields:详细页面,针对FK和M2M字段变成以Input框形式

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

 

        raw_id_fields = ('FK字段', 'M2M字段',)

 

    12)fields:详细页面时,显示字段的字段

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        fields = ('user',)

 

    13)exclude:详细页面时,排除的字段

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        exclude = ('user',)

 

    14)readonly_fields:详细页面时,只读字段

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        readonly_fields = ('user',)

 

    15)fieldsets:详细页面时,使用fieldsets标签对数据进行分割显示

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        fieldsets = (

            ('基本数据', {

                'fields': ('user', 'pwd', 'ctime',)

            }),

            ('其他', {

                'classes': ('collapse', 'wide', 'extrapretty'),  # 'collapse','wide', 'extrapretty'

                'fields': ('user', 'pwd'),

            }),

        )

 

    16)详细页面时,M2M显示时,数据移动选择(方向:上下和左右)

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)

 

    17)ordering:列表时,数据排序规则

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        ordering = ('-id',)

        或

        def get_ordering(self, request):

            return ['-id', ]

 

    18)radio_fields:详细页面时,使用radio显示选项(FK默认使用select)

 

    radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL

 

    19)form = ModelForm:用于定制用户请求时候表单验证

    from app01 import models

    from django.forms import ModelForm

    from django.forms import fields

 

    class MyForm(ModelForm):

        others = fields.CharField()

 

        class Meta:

            model = models = models.UserInfo

            fields = "__all__"

 

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

 

        form = MyForm

 

    20)empty_value_display = "列数据为空时,显示默认值"

   @admin.register(models.UserInfo)

    class UserAdmin(admin.ModelAdmin):

        empty_value_display = "列数据为空时,默认显示"

 

        list_display = ('user','pwd','up')

 

        def up(self,obj):

            return obj.user

        up.empty_value_display = "指定列数据为空时,默认显示"

 

四、admin的源码

https://www.cnblogs.com/yuanchenqi/articles/8323452.html

1 复习单例

  单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。

  比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建AppConfig 对象的实例,这就导致系统中存在多个AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

  在Python 中,我们可以用多种方法来实现单例模式:

 

  a 使用__new__

    class Singleton(object):

        _instance = None

        def __new__(cls, *args, **kw):

            if not cls._instance:

                cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)

            return cls._instance

 

    class MyClass(Singleton):

        a = 1

 

  b 使用装饰器(decorator)

  import settings

  def singleton(cls): #cls=Mysql

     _instance=cls(settings.HOST,settings.PORT)

 

      def wrapper(*args,**kwargs):

          if args or kwargs:

             obj=cls(*args,**kwargs)

              return obj

          return _instance

 

      return wrapper

 

  @singleton # Mysql=singleton(Mysql)

  class Mysql:

      def __init__(self,host,port):

          self.host=host

          self.port=port

 

  obj1=Mysql()

  obj2=Mysql()

  obj3=Mysql()

  print(obj1 is obj2 is obj3) #True

 

  obj4=Mysql('1.1.1.3',3307)

  obj5=Mysql('1.1.1.4',3308)

  print(obj3 is obj4) #False

 

  c 使用元类(metaclass)

  import settings

  class Mymeta(type):

      def __init__(self,name,bases,dic): #定义类Mysql时就触发

          # 事先先从配置文件中取配置来造一个Mysql的实例出来

          self.__instance = object.__new__(self)  # 产生对象

         self.__init__(self.__instance, settings.HOST, settings.PORT)  # 初始化对象

          # 上述两步可以合成下面一步

          # self.__instance=super().__call__(*args,**kwargs)

 

         super().__init__(name,bases,dic)

 

      def __call__(self, *args, **kwargs): #Mysql(...)时触发

          if args or kwargs: # args或kwargs内有值

             obj=object.__new__(self)

             self.__init__(obj,*args,**kwargs)

              return obj

 

          return self.__instance

 

  class Mysql(metaclass=Mymeta):

      def __init__(self,host,port):

          self.host=host

          self.port=port

 

  obj1=Mysql() # 没有传值则默认从配置文件中读配置来实例化,所有的实例应该指向一个内存地址

  obj2=Mysql()

  obj3=Mysql()

 

  print(obj1 is obj2 is obj3)

  obj4=Mysql('1.1.1.4',3307)

 

  d 定义一个类方法实现单例模式

  import settings

  class Mysql:

      __instance=None

      def __init__(self,host,port):

          self.host=host

          self.port=port

 

      @classmethod

      def singleton(cls):

          if not cls.__instance:

             cls.__instance=cls(settings.HOST,settings.PORT)

          return cls.__instance

 

  obj1=Mysql('1.1.1.2',3306)

  obj2=Mysql('1.1.1.3',3307)

  print(obj1 is obj2) #False

 

  obj3=Mysql.singleton()

  obj4=Mysql.singleton()

  print(obj3 is obj4) #True

 

  e 使用模块

    Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成.pyc 文件,当第二次导入时,就会直接加载.pyc 文件,而不会再次执行模块代码。

    因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:

 

    # mysingleton.py

    class My_Singleton(object):

        def foo(self):

            pass

    my_singleton = My_Singleton()

 

    # 使用

    from mysingleton import my_singleton

    my_singleton.foo()

 

    注意:

    1)在同一django中的不同py文件中导入变量my_singleton为同一单例

    2)在同一django中的不同py文件中导入类My_singleton为同一个类,但调用其产生的对象为不同的对象

 

2 复习类/对象中属性的查找

 

 

3 启动

  循环加载执行所有已经注册的app中的admin.py文件

  def autodiscover():

     autodiscover_modules('admin', register_to=site)

 

4 注册(*******)

  class AdminSite(object):

      def __init__(self, name='admin'):

          self._registry = {}

      def register(self, model_or_iterable, admin_class=None, **options):

          if not admin_class:

              admin_class = ModelAdmin   # 配置类

 

         self._registry[model] = admin_class(model, self)

 

          # {Book:BookConfig(Book),Publish:ModelAdmin(Publish)}

 

  site=AdminSite()   # 对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象

 

 -----------------------------------------

  class BookConfig(ModelAdmin):

     list_display=["",]

 

 admin.site.register(Book,BookConfig) # Book在app01中

 admin.site.register(Publish)  # Publish在app02中;按照注册顺序,先执行app01中的admin,再执行app02中的admin

 

 -----------------------------------------

  print(admin.site._registry)

  {

  <class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x00000256B97EF9E8>,

  <class 'django.contrib.auth.models.User'>: <django.contrib.auth.admin.UserAdmin object at 0x00000256B9825438>,

  <class 'app01.models.Book'>: <app01.admin.BookConfig object at 0x00000256B983C080>,

  <class 'app01.models.Publish'>: <app01.admin.PublishConfig object at 0x00000256B983C128>

  }

  # 两个django自带的键值对,外加两个app中各自注册的键值对(model:对应配置类的对象)

猜你喜欢

转载自www.cnblogs.com/zhangyaqian/p/py20180719.html
今日推荐