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')
class MySQLHelper(object): def fetchone(self): """ 链接MySQL,获取一条数据 :return: """ print('MySQL.fetchone')
# DB_PATH = "db.mysql.MySQLHelper" DB_PATH = "db.sqlserver.SqlServerHelper"
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()
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
其他方法也有对应的方法 直接调用仿照上面即可