zoukankan      html  css  js  c++  java
  • 关于模拟admin实现stark组件的知识点

    一. url知识

    还记得include分发么?里面的参数都可以有些什么?

    urlconf_module本质是返回的是模块路径对象
    def include(arg, namespace=None, app_name=None):
        .......
        return (urlconf_module, app_name, namespace)

    1. 字符串格式?

    url(r'^joker/', include('app01.urls')),

    源码解释。

    patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)

    通过反射找到urlconf_moduls模块下的urlpatterns,如果没有urlpatterns会报错

    2. 列表格式?

    url(r'^joker/', include([
        url('login1', login),
    ])),

    源码解释。

    if isinstance(arg, tuple):
          .......
    else:
          # No namespace hint - use manually provided namespace
          urlconf_module = arg

    走else,也就是urlconf_moduls返回的就是这个列表

    3 元祖?

    url(r'^joker/', ([
                            url('app01/',([(url('login',login))],None,None)),
                            url('login2',login),
    ],None,None)),           

    源码解释。

    return (urlconf_module, app_name, namespace)

    include分发本质返回的就是,url模块,app名字,命名空间,那我们直接把这个元祖写这里,相当于分发

    最后,上面都是前面与后面的拼接成url

    2. 装饰器

    我们给视图函数(增删改查)加上了装饰器,其目的是让每个url都是个request对象,为了携带当前访问时候的数据

    当时的代码如下

    self.request = None 类属性当时为None
    # 携带数据装饰器
        def warp(self, view_func):
            def inner(request, *args, **kwargs):
                self.request = request           ######   每个增删改查在点击的时候都携带REQUEST这个数据
                return view_func(request, *args, **kwargs)
            return inner
    
        # LIST_VIEW = WARP(LIST_VIEW) == INNER (LIST_VIEW)  ==
        # URL
        def get_urls(self):  # 默认的增删改查
    
            # 我这里获取的URL是不是应该加入别名?反向解析呢?
            # url( 正则,视图(元祖,列表),命名空间)
            app_model_name = (self.model._meta.app_label, self.model._meta.model_name)  # 应用名称,表名称
            temp = [
                url("^$", self.warp(self.list_view), name="%s_%s_list" % app_model_name),
                url("^add/$", self.warp(self.add_view), name="%s_%s_add" % app_model_name),
                url("^(d+)/edit/$", self.warp(self.edit_view), name="%s_%s_edit" % app_model_name),  ###  注意小括号
                url("^(d+)/delete/$", self.warp(self.delete_view), name="%s_%s_delete" % app_model_name),
            ]
    
            return temp
    stark用装饰器源码

    装饰器学习

    http://www.cnblogs.com/jokerbj/p/7247901.html

    3. model取值操作

    常规取值操作

    http://www.cnblogs.com/jokerbj/p/8145387.html

    针对表对象可以取一些特定的值,比如咱们的代码

    # 注册,这是在启动的时候就会加载的
    joker.site.register(models.Book)
    # 针对model取值
    model_name = model._meta.model_name             # 数据库表名
    app_label = model._meta.app_label               # 应用表名
    # 取表字段
    verbox_name=self.model._meta.get_field('title').verbose_name  # 如果 model里面没有指定verbose_name就是字段名,指定就是verbose_name对应的值
    _field.rel.to.objects.all() # _field 是字段,拿到的是该字段的所有值

    针对Q查询,看下咱们代码

    condition = Q()    # 利用Q 查询
    condition.connector = 'or'   # 指定Q查询之间是什么关系
    if key_word and self.show_search_form:  # 有默认搜索值,并且前端开启页面
        for field_name in search_fields:   #  'title__contains','price',
            condition.children.append((field_name,‘joker’))   # title=joker的值或者price=joker的值
        print(condition)
    
    数据查询这块就是
    queryset = self.model.objects.filter(self.get_search_condition())  # 过滤条件

    4. request.GET.urlencode()  携带数据跳转

    我们之前为了保持每次搜索携带数据,引入了request.get.urleode方法,这个方法可以使请求的数据直接变成字符串

    # 例如访问的url
    http://127.0.0.1:8000/?page=1&id=2
    # 如果我们用将这次请求利用request.GET.urlencode()打印
    得到 page=1&id=2  的字符串
    # 我们携带这个数据进入要编辑页面,当我们编辑完我们还会携带这个数据,返回之前我们页面,所以说这个数据就是当前页面的状态

    有个问题?

    如果请求携带的数据有重复怎么办?

    我们引入QueryDict这个字典,因为普通的字典无法被urlencode,打开request.GET修改?

    # queryset dict
    from django.http import QueryDict
    
    # 获取当前请求头
    query_str = self.request.GET.urlencode()   # 请求数据
    
    # QueryDict 字典加入值
    parames = QueryDict(mutable=True)  # 允许更改request.GET mutable 可变的意思
    parames[self._query_param_key] = query_str   # 加入当前URL数据
    
    # 好了之后,反问哪个就加入下面经过urlencode处理的数据
    return mark_safe("<a href='%s?%s'>edit</a>" % (a,b,parames.urlencode()))  # 调用反向解析出来的url,就是这样携带数据访问
    
    # 后端处理数据后,返回的页面就是携带之前的数据
    list_query_str = request.GET.get(self._query_param_key)
    list_url = "%s?%s" % (self.get_list_url(), list_query_str,)
    return redirect(list_url)

    强插一个知识点》》

    config.request.GET.get(config.search_key,'')

    如果没有获取不到该值,可以给个默认值空。当然也可以为别的,默认是None

    强插一个知识点》》

    _params.setlist(self.option.field_name,id_list) # 重新设置请求
    url = '{0}?{1}'.format(self.request.path_info, _params.urlencode())

    可以传入列表,元祖,重新赋值

    5. button可以提交数据?

    有时html页面button点击会出现自动提交表单的情况。

    <form action="" method="post">
        {% csrf_token %}
        <input type="text" placeholder="xxx">
        <button></button>
    </form>

    form表单下的按钮在没有指定type类型的时候,button会有一个默认的type=”submit”

    给button设置一个类型type="button",这样button的类型就不是默认的submit了,就不会自动提交表单了

    <form action="" method="post">
        {% csrf_token %}
        <input type="text" placeholder="xxx">
        <button type="button"></button>
    </form>

    6. 模版语言里面不能用_  or __ 去调用

    {{ cls._pk }}
    {{ cls.__pk }}

    7. 判断字段是不是外键,或者多对多关系

    from django.db.models import ForeignKey,ManyToManyField
    if isinstance(_field,ForeignKey):
        pass

    8. 取choices字段中文

    
    
    device_status_choices = (
    (1, '上架'),
    (2, '在线'),
    (3, '离线'),
    (4, '下架'),
    )
    device_status_id = models.IntegerField(choices=device_status_choices, default=1)
    return obj.get_gender_display() 
    # 这里用法就是 get_fieldname_display() fieldname device_status_di中间加入字段就会自动拿到CHOICE对应的中文拿到前提就是这个对象有这个字段
    # 前端 <td>{{ data.asset.get_device_status_id_display }}</td> 这样获取

    9 . 单例模式

    class Foo(object):
        _instance = None
    
        def __init__(self, name):
            self.name = name
    
        @classmethod
        def instance(cls, *args, **kwargs):
            if not Foo._instance:
                obj = Foo(*args, **kwargs)
                Foo._instance = obj
            return Foo._instance
    
    obj1 = Foo.instance('alex')
    obj2 = Foo.instance('alex')
    print(id(obj1), id(obj2))

    10. 反射

    ###  settings
    # DB_PATH = "db.mysql.MySQLHelper" DB_PATH = "db.sqlserver.SqlServerHelper"

    ### db 下的mysql/sqlserverPY文件
    class MySQLHelper(object):
    def fetchone(self):
    """
    链接MySQL,获取一条数据
    :return:
    """
    print('MySQL.fetchone')
    ### app.py
    from settings import DB_PATH   # 我导入一段字符串
    def func():
        # 导入文件
        # 反射
        # DB_PATH = "db.mysql.MySQLHelper"
        module_path, cls_name = DB_PATH.rsplit('.', maxsplit=1)   # db.mysql / db.sqlserver
    
        # 以字符串的形式导入模块
        # from db import mysql  类似于 这种
        import importlib   导入模块
        module_obj = importlib.import_module(module_path) # 
    
        # 去模块中导入类
        cls = getattr(module_obj, cls_name)  cls_name 是模块下的类
    
        # 类实例化
        obj = cls()
        obj.fetchone()
    
    if __name__ == '__main__':
        func()
    

    11. 对象封装数据

    class Foo(object):
        def __init__(self, name, data_list):
            self.name = name
            self.data_list = data_list
    
        def __iter__(self):
            yield "<div>"
            yield "全部"
            for item in self.data_list:
                yield item
            yield "</div>"
    
    obj_list = [Foo('富贵', ['', '']), Foo('强哥', ['已报名', '未报名']), Foo('熊平', ['内部转介绍', '百度推广'])]
    
    # 需求:循环对象时,先打印对象name属性,然后再答应123。
    for obj in obj_list:
        for item in obj:
            print(item)

    12. 弹出popup

    三种window对象,弹出关闭
    window.alert(123);   关闭
    window.confirm("123"); 交互    取消 关闭
    window.prompt("123"); 输入内容  取消 关闭
    #############################   url代码
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^pop/', views.pop),
    ]
    
    ############################    views代码
    def index(request):
        return render(request, 'index.html')
    
    def pop(request):
        if request.method == "GET":
            return render(request, 'pop.html')
        else:
            user = request.POST.get('user')
            return render(request, 'pop_response.html', {'user': user})
    
    ############################     index.html代码
    <h1 id="i1">我会被更改的</h1>
    <a href="#" onclick="popUp('http://www.oldboyedu.com')">点我点我</a>
    
    <script>
        function xxxpopupCallback(text) {
            document.getElementById('i1').innerHTML = text;
        }
    
        function popUp(url) {
            window.open('/pop/', "n1", "status=1, height:500, 600, toolbar=0, resizeable=0");
        }
    
    </script>
    
    ###########################      pop.html代码
     <form method="post">
            {% csrf_token %}
            <input type="text" name="user">
            <input type="submit" value="保存">
        </form>
    
    ###########################     pop_response代码
    <h1>正在关闭</h1>
    <script>
        (function () {
            // 可以调用popup原页面的一个函数
            opener.xxxpopupCallback("{{ user }}");
            window.close();
        })()
    </script>

    流程解释:

      我们访问到index页面,利用事件让浏览器弹出一个我们自定义的窗口(window.open),在这个窗口中我们给予他需要弹出的页面pop.html页面,并设置xxxpopupCallback接收到时候儿html的返回值。提交表单post发回视图,视图转给pop_response页面,匿名函数返回给源html值,opener.xxxpopupCallback("{{ user }}");随后关闭。

    13. form表单补充

    数据实时更新

    方式一
    class RegForm(forms.Form):
        user = forms.CharField(max_length=32)
        #gender_tuple=(0,'上海'),(1,'北京'),(2,'保定')
        gender = forms.ChoiceField(choices =City.objects.all().values_list("id","name"))  # 第一次启动时候数据拿了一遍,无法实时更新,如果数据更新了,页面显示不出来
    
        def __init__(self,*args,**kwargs):
            super(RegForm,self).__init__(*args,**kwargs)  # 通过构造方法实时更新
            #print("Ok")
            print(self.fields["gender"].choices)
            self.fields["gender"].choices=City.objects.all().values_list("id","name")
    
    
    方式二  依赖 MODEL
    from django.forms import ModelChoiceField,MultipleChoiceField
    
    class RegForm(forms):
        gender = fields.ModelChoiceField(queyset=City.objects.all())  # 字段 页面单选
    
    class RegForm(forms):
        gender = fidles.MultipleChoiceField(queyset=City.objects.all())  # 字段  页面多选
    
    # 方式三
    class RegForm(ModelForm):    # 依赖MODEL,同方式二,
        class Meta:
            model = UserInfor    # 如果UserInfor是F,就生成ModelChoiceField,是M2,就生成MultipleChoiceField
            fields = "__all__"
    View Code

    modelform转变form

    class RegForm(ModelForm):    # 依赖MODEL,同方式二,
        class Meta:
            model = UserInfor    # 如果UserInfor是F,就生成ModelChoiceField,是M2,就生成MultipleChoiceField
            fields = "__all__"

    读取model = userinfo中的字段,转变成form字段

    class UserInfor(models.Model):
        user=models.CharField(max_length=32)
        gender=models.IntegerField(choices=((1,""),(2,"")))
        city=models.ForeignKey("City",default=1)
        roles=models.ManyToManyField("Roles",default=1)
    |||||
    
    class UserInfor(forms.Form):
        user=forms.CharField()
        gender=forms.TypedChoiceField(choices=((1,""),(2,"")))
        city=forms.ModelChoiceField(choices=City.objects.all())
        roles=forms.ModelMultipleChoiceField(choices=Roles.objects.all())

    循环form

    def reg(reqeust):
        form = RegForm()  # form包含了表内的所有字段
        for i in form:
            print(i)   <input type="text" name="user" required id="id_user" maxlength="32" />  因为内部的str方法才显示的标签,不过还是个对象,这个是前端渲染框的
         print(i.field) # <django.forms.fields.CharField object at 0x1068d1c88> boundield 里面的field字段打印就是每个字段的类型
        print(type(i)) <class 'django.forms.boundfield.BoundField'>,每个字段都是对象,被boundfield封装

    前端页面 {{ field.label }},打印的是字段名称,如果有verbose_name打印这个,没有打印字段名字

     源form学习

    http://www.cnblogs.com/jokerbj/p/8157669.html

  • 相关阅读:
    【NOI2008】志愿者招募
    【NOI2015】小园丁和老司机
    【TJOI2007】小朋友
    【HNOI2008】神奇的国度
    【CTSC2014】企鹅QQ
    【CQOI2014】通配符匹配
    【JSOI2008】火星人
    【SCOI2007】压缩
    【ZJOI2009】对称的正方形
    【LOJ#6066】同构子树
  • 原文地址:https://www.cnblogs.com/jokerbj/p/8402742.html
Copyright © 2011-2022 走看看