关于模拟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=&id= 的字符串
# 我们携带这个数据进入要编辑页面,当我们编辑完我们还会携带这个数据,返回之前我们页面,所以说这个数据就是当前页面的状态
有个问题?
如果请求携带的数据有重复怎么办?
我们引入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=) # 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(""); 交互 取消 关闭
window.prompt(""); 输入内容 取消 关闭
############################# 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, width: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__"
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="" /> 因为内部的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
关于模拟admin实现stark组件的知识点的更多相关文章
- 模拟Django的admin自定义stark组件
1.新建Django项目--新建app:app01和stark--在settings中配置app和数据库--在models.py中新建模型表--完成数据库迁移 2.在stark下的apps.py中: ...
- 10.15仿admin开发stark组件(一)
2018-10-15 12:28:50 越努力,越幸运!永远不要高估自己! 低调做人,高调做事! 明天开stark项目!! admin 参考连接: http://www.cnblogs.com/yua ...
- admin源码解析以及仿照admin设计stark组件
---恢复内容开始--- admin源码解析 一 启动:每个APP下的apps.py文件中. 首先执行每个APP下的admin.py 文件. def autodiscover(): autodisco ...
- stark组件之pop操作【模仿Django的admin】
一.先看下什么django的admin的pop到底是个什么东西 其实就是这么一个东西, a.在添加页面,在一对多和多对多的项后加了一个+号 b.点击这个加号,会弹出对应的添加 页面,在新的添加 c.添 ...
- 仿照admin的stark自定义组件的功能实现
仿照admin的stark自定义组件的功能实现:其中最主要的就是增删改查的实现 1.查:首先页面中显示表头和数据,都是动态的,而不是写死的. (1) 先看表头和表单数据:这个是查看的视图函数,但是为了 ...
- stark组件之批量操作【模仿Django的admin】
一.先看下django的admin是如何实现批量操作 首先在配置类中定义一个函数 然后我们为这个函数对象设置一个属性,这个属性主要用来显示在select标签中显示的文本内容 最后把函数对象放到一个ac ...
- stark组件之搜索【模仿Django的admin】
一.先看下django的admin是如何做搜索功能的 配置一个search_fields的列表就可以实现搜索的功能 class testbook(admin.ModelAdmin): # 第一步,定义 ...
- stark组件之路由分发【模仿Django的admin】
一.先看下django的admin是如何进行路由分发的 1.先看下django的admin的url路径有哪些 其实很简单,假如有一个书籍表,那么每张表对应四个url,增.删.改.查 查看的url ht ...
- stark组件之注册【模仿Django的admin】
一.先看下django的admin是如何实现注册功能 首先导入admin这个对象和我们的model模块 from django.contrib import admin # Register your ...
随机推荐
- java中+=详解 a+=b和a=a+b的区别
short a=10; a+=4; System.out.println(a); 1.第一段代码的输出结果为14.执行流程是首先声明变量,判断赋给变量的初始值是否在short类型范围内,如果在则进行强 ...
- php-resque 简单的php消息队列
摘要: 消息队列是个好东西,各种×××MQ很多.然而看一下它们的文档,你得吓尿,什么鬼,我只是想用它触发个短信接口而已. 幸好也有简单的.这次是php-resque 安装 首先这货需要在linux下跑 ...
- 常见Git操作及关键知识点
一.Git三区概念 工作区 (work dict) 暂存区(stage)(add 是添加到当前的暂存区) 提交区(就是当前工作的分支master分支或者branches分支) git 所有操作都是基于 ...
- [译]HIPAA要求的SSL/TLS等级
原文链接:https://luxsci.com/blog/level-ssl-tls-required-hipaa.html 原文发表时间:2015.1.13 本博文仅仅是上述原文的翻译,仅供研究参考 ...
- HDU - 5628:Clarke and math (组合数&线性筛||迪利克雷卷积)
题意:略. 思路:网上是用卷积或者做的,不太会. 因为上一题莫比乌斯有个类似的部分,所以想到了每个素因子单独考虑. 我们用C(x^p)表示p次减少分布在K次减少里的方案数,由隔板法可知,C(x^p)= ...
- BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*
BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...
- CODEVS3013 单词背诵 【Hash】【MAP】
CODEVS3013 单词背诵 题目描述 Description 灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词. 文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要 ...
- Hive SQL的编译过程[转载自https://tech.meituan.com/hive-sql-to-mapreduce.html]
https://tech.meituan.com/hive-sql-to-mapreduce.html Hive是基于Hadoop的一个数据仓库系统,在各大公司都有广泛的应用.美团数据仓库也是基于Hi ...
- 给select增加placeholder技巧
转自:http://stackoverflow.com/questions/5805059/how-do-i-make-a-placeholder-for-a-select-box/8442831 使 ...
- JavaScript:基本包装类型
为了方便操作,JavaScript提供了3个特殊的引用类型:Boolean.Number和String.实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而可以调用这些 ...