Django-自定义增删改查组件的一些体会

1.路由系统

namespace,用于区分相同name的url,通过namespace为url添加一个前缀

反向生成URL的时候

reverse('namespace:name')
{% url "namespace:name"%}
    @property
    def urls(self):
        return (self.get_urls(), None, 'stark')
 # 总的url
    def get_urls(self):
        model_class_app = (self.model_class._meta.app_label, self.model_class._meta.model_name)
        urlpatterns = [
            url(r'^$', self.wrap(self.changlist_view), name='%s_%s_changelist' % model_class_app),
            url(r'^add/$', self.wrap(self.add_view), name='%s_%s_add' % model_class_app),
            url(r'^(d+)/change/$', self.wrap(self.chang_view), name='%s_%s_change' % model_class_app),
            url(r'^(d+)/delete/$', self.wrap(self.delete_view), name='%s_%s_delete' % model_class_app)
        ]
        urlpatterns.extend(self.extra_url())
        return urlpatterns

    # 额外的url 在自己的config中定义该函数添加
    def extra_url(self):
        return []

    @property
    def urls(self):
        return self.get_urls()

    # 列表页面的url
    def get_list_url(self):
        name = 'stark:%s_%s_changelist' % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        list_url = reverse(name)
        return list_url

    # 添加按钮的url
    def get_add_url(self):
        name = 'stark:%s_%s_add' % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        add_url = reverse(name)
        return add_url

    # 编辑的url
    def get_change_url(self, nid):
        name = 'stark:%s_%s_change' % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        edit_url = reverse(name, args=(nid,))
        return edit_url

    # 删除的url
    def get_delete_url(self, nid):
        name = 'stark:%s_%s_delete' % (self.model_class._meta.app_label, self.model_class._meta.model_name)
        del_url = reverse(name, args=(nid,))
        return del_url

2. 制作项目启动时,自动加载文件

在当前app下的apps中写入下面代码即可,并去已注册的所有app中,找stark.py文件,并加载

def ready(self):
            from django.utils.module_loading import autodiscover_modules
            autodiscover_modules('stark')

3.model操作

model.UserInfo
        model.UserInfo._meta.app_label#获取当前app的名称
        model.UserInfo._meta.model_name#获取当前类名小写
        model.UserInfo._meta.get_field('username')#获取字段
        
        model.UserInfo._meta.get_field('username').verbose_name#获取verbose_name
        model.UserInfo._meta.get_field('外键或多对多字段').rel.to #得到关联的model类

        - models.UserInfo._meta.get_field('name') # 根据字段名称,获取字段对象
        - models.UserInfo._meta.fields # 获取类中所有的字段
        - models.UserInfo._meta._get_fields() # 获取类中所有的字段(包含反向关联的字段)
        - models.UserInfo._meta.many_to_many # 获取m2m字段

 

4.函数和方法

函数还是方法

对于类中的函数,直接用类名调用的话需要传入self参数,既函数

                             用对象调用的话就不需要传入self参数,既方法

class Foo(object):
                def __init__(self):
                    self.name = 'alex'
                def func(self):
                    print(self.name)

            from types import FunctionType,MethodType

            obj = Foo()
            print(isinstance(obj.func,FunctionType)) # False
            print(isinstance(obj.func,MethodType))   # True

            print(isinstance(Foo.func,FunctionType)) # True
            print(isinstance(Foo.func,MethodType))   # False
            """
            注意:
                方法,无需传入self参数
                函数,必须手动传入self参数
            """
函数是一个对象,
            - func.__name__  #获取函数的名字
            - func.text = "sdfsfd"  #设置属性值
# obj = Foo()
# print(obj.func) # <bound method Foo.func of <__main__.Foo object at 0x00000000021E8400>>

# print(Foo.func)  # <function Foo.func at 0x0000000001E89B70>
#
# obj = Foo()
# Foo.func(obj)
#
# obj = Foo()
# obj.func()
class Foo(object):
    def __init__(self):
        self.name = 'alex'
    def func(self):
        print(self.name)

from types import FunctionType,MethodType

obj = Foo()
print(isinstance(obj.func,FunctionType)) # False
print(isinstance(obj.func,MethodType))   # True

print(isinstance(Foo.func,FunctionType)) # True
print(isinstance(Foo.func,MethodType))   # False
"""
注意:
    方法,无需传入self参数
    函数,必须手动传入self参数
"""

5.保留搜索条件的两种方法

方式一 直接通过 request.GET.urlencode()

    列表页面:
                获取当前所有条件,添加到 
                    - 编辑按钮的URL后面
                    - 添加按钮的URL后面
            编辑或添加页面:
                - POST提交时,获取原来列表页面传过来的条件
                - 拼接URL  /hosts/?原来的条件
                
            list页面:
            
            list_condition = request.GET.urlencode()
            
                {% for item in host_list %}
                    <li>{{ item }} <a href="/edit/54/?{{ list_condition }}">编辑</a></li>
                {% endfor %}
                
            add/edit页面:http://127.0.0.1:8000/edit/10/?page=5&id__gt=4
                def edit_host(request,pk):
                    if request.method == "GET":
                        return render(request,'edit_host.html')
                    else:
                        # 修改成功 /hosts/?page=5&id__gt=4
                        url = "/hosts/?%s" %(request.GET.urlencode())
                        return redirect(url)

方式二

    list页面: http://127.0.0.1:8000/hosts/?page=5&id__gt=4
            
                params = QueryDict(mutable=True)
                params['_list_filter'] = request.GET.urlencode()
                list_condition = params.urlencode()
                
                
                {% for item in host_list %}
                    <li>{{ item }} <a href="/edit/54/?{{ list_condition }}">编辑</a></li>
                {% endfor %}
    
            add/edit页面:http://127.0.0.1:8000/edit/54/?_list_filter=page%3D5%26id__gt%3D4
                
                def edit_host(request,pk):
                if request.method == "GET":
                    return render(request,'edit_host.html')
                else:
                    # 修改成功 /hosts/?page=5&id__gt=4
                    url = "/hosts/?%s" %(request.GET.get('_list_filter'))
                    return redirect(url)
request.GET本质是QuerySet,不能改变但是给他设置

request.GET._mutable=True就可以改变了,但是不建议改变request.GET

我们可以自定义
params = QueryDict(mutable=True)或者
import copy
params=copy.deepcopy(request.GET)
- request.GET
        - ?name=alex&age=18&age=19
        - params = { name:['alex', ], age:[18,19] }
        
        - params['hobby'] = "鲁宁"#实际上是一个列表
        - params = { name:['alex', ], age:[18,19], hobby:[ 鲁宁,] }
        
        - params.setlist('hobby',["鲁宁"])
        - params = { name:['alex', ], age:[18,19], hobby:[鲁宁,] }
类似的还有
pop()
remove()方法
用法和字典一样

6.Q函数的补充

- Q 
            - Q(id__gt=1)|Q(id=2)
            - con = Q()
        - 模板语言中的字典,不能以_开头   obj._
        - GET请求
        
        con = Q()

        q1 = Q()
        q1.connector = 'or'
        q1.children.append( ('name','alex1') )
        q1.children.append( ('name','alex2') )

        q2 = Q()
        q2.children.append( ('age__gt',18))
        q2.children.append( ('id__gt',18))

        con.add(q1,'OR')
        con.add(q2,'OR')
        # (name='alex' or name=='alex2') or (age>18 and id > 18)

        queryset = self.model_class.objects.filter(con)

7.一个对象是否可以被for循环?

    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('熊平',['搜索','所属'])]


            for obj in obj_list:
                for item in obj:
                    print(item)

# 需求:循环对象时,先打印对象name属性,然后再答应123。

class A(object):
    def __init__(self,name,data_list):
        self.name=name
        self.data_list=data_list

    def __iter__(self):
        yield self.name
        for i in self.data_list:
            yield i



obj_list=[A('ctz',[1,2,3]),A('aa',[1,2,3]),A('bb',[1,2,3]),A('cc',[1,2,3])]

for obj in obj_list:
    for item in obj:
        print(item)

8.里面用了很多yield 记住

9.isinstance

class Foo(object):
    pass

class Bar(Foo):
    pass

obj = Bar()

# isinstance用于判断,对象是否是指定类的实例 (错误的)
# isinstance用于判断,对象是否是指定类或其派生类的实例
print(isinstance(obj,Foo))
print(isinstance(obj,Bar))


print(type(obj) == Bar)
print(type(obj) == Foo)


#type  精确判断
# 对象,判断是否是某个类型? type,isinstance

from django.forms.models import ModelChoiceField
from django.forms.models import ModelMultipleChoiceField

isinstance(obj,ModelChoiceField)

10.反射补充

1.常用 普通

class Foo(object):
    def func(self):
        pass

obj = Foo()

name = "func"

fc = getattr(obj,name)

fc()

2.补充的 django setting.py中中间件注册(参考django源码得知)

class SqlServerHelper(object):
    def fetchone(self):
        """
        链接SQLServer,获取一条数据
        :return: 
        """
        print('SQLServer.fetchone')
sqlserver.py
class MySQLHelper(object):

    def fetchone(self):
        """
        链接MySQL,获取一条数据
        :return: 
        """
        print('MySQL.fetchone')
mysql.py
# DB_PATH = "db.mysql.MySQLHelper"
DB_PATH = "db.sqlserver.SqlServerHelper"
settings.py
from 反射.settings import DB_PATH

def func():
    # 导入文件
    # 反射
    # DB_PATH = "db.mysql.MySQLHelper"
    module_path,cls_name = DB_PATH.rsplit('.',maxsplit=1)

    # 以字符串的形式导入模块
    # from db import mysql
    import importlib
    module_obj = importlib.import_module(module_path)

    # 去模块中导入类
    cls = getattr(module_obj,cls_name)

    # 类实例化
    obj = cls()
    obj.fetchone()


if __name__ == '__main__':
    func()
app.py

 11、对象加减乘除

加法

class Foo(object):
                
                def __init__(self,age):
                    self.age = age
                    
                def __add__(self, other):
                    # return self.age + other.age
                    return Foo(self.age + other.age)
                    
            obj1 = Foo(19)
            obj2 = Foo(18)

            obj3 = obj1 + obj2

其他方法也有对应的方法 直接调用仿照上面即可

原文地址:https://www.cnblogs.com/ctztake/p/8076003.html