昨日内容回顾

第一部分:权限相关
1. 权限基本流程
用户登录成功后获取权限信息,将【权限和菜单】信息写入到session。
以后用户在来访问,在中间件中进行权限校验。
为了提升用户体验友好度,在后台通过inclusion_tag动态生成一个二级菜单。
2. 使用权限
- 用户登陆:权限和菜单的初始化; init_permission
- 配置中间件
- 配置白名单
- 配置session中使用到的key
- load rbac
- menu ,inclusion_tag 生成菜单
- filter,可以在if后做条件,粒度控制到按钮。
第二部分:stark组件
1. 如何使用
- 在app中编写 stark.py
- 在stark.py中进行定制
- 默认配置:
site.register(models.UserInfo)
- 自定义配置:
class UserConfig(StarkConfig):
list_display = [] # 表格式列表上显示的字段
def get_list_display():
pass
order_by = [] # 排序
action_list=[] # 批量操作
search_list = [] # 模糊搜索
list_filter = [] # 组合搜索
add_btn # 是否显示添加按钮
model_form_class # 自定义ModelForm def extra_url(self): # 自定义扩展 URL
pass def get_urls(self): # 自定义URL
pass def changelist_view(self,request):
pass def add_view(self,request):
pass def change_view(self,request):
pass def del_view(self,request):
pass site.register(models.UserInfo,UserConfig)

一、popup

什么是popup

popup英文翻译叫 弹出窗口。

弹窗是一个非常流行的对话框,弹窗可以覆盖在页面上展示。

弹窗可用于显示一段文本,图片,地图或其他内容。

注意:popup弹窗,是由浏览器生成的!

在前端里面的,有一个模态框。那是由Html生成的!跟popup弹框不一样!

window.open

popup实际上,是调用了js中的window.open方法

open() 方法用于打开一个新的浏览器窗口或查找一个已命名的窗口。

语法

window.open(URL,name,features,replace)

注意:如果name重名,只会打开一个

窗口特征(Window Features)

这里只列举,下面例子中,会用到的参数

status=yes|no|1|0 是否添加状态栏。默认是 yes。
height=pixels 窗口文档显示区的高度。以像素计。
width=pixels 窗口的文档显示区的宽度。以像素计。
toolbar=yes|no|1|0 是否显示浏览器的工具栏。默认是 yes。
resizable=yes|no|1|0 窗口是否可调节尺寸。默认是 yes。

其他更多参数,请参考链接:

http://www.w3school.com.cn/jsref/met_win_open.asp

在django admin中,就用到了popup。比如之前写的博客系统

点击加号

它弹出了一个网页框。注意:它是单页面的!不能像浏览器一样,在当前页面,新开一个窗口。

不能收藏!URL地址也不能修改!

举例:

新建一个项目,注意:django版本为1.11

修改urls.py,增加路径

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
]

修改views.py,增加视图函数

from django.shortcuts import render

# Create your views here.
def index(request):
return render(request,"index.html")

在templates目录下,创建文件index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加页面</h1>
<form>
<p><input type="text"></p>
<p>
<select id="city">
<option>北京</option>
<option>上海</option>
<option value="">深圳</option>
</select>
<input type="button" value="+" onclick="popUp();">
</p>
</form>
<script>
function popUp() {
{#弹窗#}
window.open("http://www.py3study.com/",'x1',"status=1, height=500, width=500, toolbar=0, resizable=0")
}
</script>
</body>
</html>

启动django项目,访问首页

点击加号按钮,弹窗页面。它是一个单页面!

弹窗的内容,可以定制吗?当然可以!

修改urls.py,增肌路径

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^pop/', views.pop),
]

修改views.py,增肌视图函数

from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
return render(request,"index.html") def pop(request):
if request.method == "GET":
return render(request,"add_city.html") print(request.POST)
return HttpResponse('添加成功')

在templates目录下,创建文件add_city.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>创建城市</h1>
<form method="post">
{% csrf_token %}
<div style="width: 200px;height: 300px;border: 1px solid #dddddd">
<input type="text" name="city">
<input type="submit" value="提交">
</div>
</form>
</body>
</html>

刷新页面,重新点击加号按钮,效果如下:

点击提交之后,效果如下:

但是窗口并没有自动关闭!它应该自动关闭,并跳转到首页才对!

怎么让它自动关系呢?使用windows.close()

由于windows.close()是js代码,需要使用html文件来执行才行!

在templates目录下,创建文件pop_response.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>正在关闭</title>
</head>
<body>
<script>
{#自执行函数#}
(function () {
window.close();
})()
</script>
</body>
</html>

自执行函数,也就是能够自动立即执行的函数

看下面一段代码

(function () {
window.close();
})()

在js中声明函数,使用function关键字。函数执行,必须要加括号执行。

所以上面一段代码,就是声明之后,立刻被执行了!

还有一种用途,用于做隔离。比如多个js文件之间相互调用时!

修改views.py,渲染pop_response.html

from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
return render(request,"index.html") def pop(request):
if request.method == "GET":
return render(request,"add_city.html") print(request.POST)
return render(request, 'pop_response.html')

重启django,刷新页面,重新添加一次。效果如下:

那么问题来了,添加之后的数据,要在下拉框中展示。要实时更新,怎么搞?

注意:拉下框中的数据,是来源于数据库的。所以即使添加成功了,要刷新页面,才能加载出来!

popup,它能记住是由哪个页面触发弹窗的。它能调用原始页面的数据!使用opener调用

测试一下

修改index.html,增加tx方法

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加页面</h1>
<form>
<p><input type="text"></p>
<p>
<select id="city">
<option>北京</option>
<option>上海</option>
<option value="">深圳</option>
</select>
<input type="button" value="+" onclick="popUp();">
</p>
</form>
<script>
{#测试函数#}
function tx() {
alert('xxx');
}
function popUp() {
{#弹窗#}
window.open("/pop/",'x1',"status=1, height=500, width=500, toolbar=0, resizable=0")
}
</script>
</body>
</html>

修改pop_response.html,调用tx方法

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>正在关闭</title>
</head>
<body>
<script>
{#自执行函数#}
(function () {
//调用tx方法
opener.tx();
window.close();
})()
</script>
</body>
</html>
(function () {
window.close();
})()

刷新页面,重新添加一次,效果如下:

那么既然可以调用index.html的方法,就可以传值了

修改views.py,增加变量content,用来使用js传参给index.html

from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
return render(request,"index.html") def pop(request):
if request.method == "GET":
return render(request,"add_city.html") print(request.POST)
# 假设数据已经添加成功了,这里要获取添加的id和title
content = {'id':4,'title':'成都'}
# 渲染页面,用来将参数传给index.html
return render(request, 'pop_response.html',content)

修改pop_response.html,调用tx方法,并传参。

注意:参数是字符串,要用引号括起来

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>正在关闭</title>
</head>
<body>
<script>
{#自执行函数#}
(function () {
//调用tx方法,参数必须是字符串
opener.tx('{{ id }}','{{ title }}');
window.close();
})()
</script>
</body>
</html>
(function () {
window.close();
})()

修改index.html,接收参数后,操作DOM

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加页面</h1>
<form>
<p><input type="text"></p>
<p>
<select id="city">
<option value="">北京</option>
<option value="">上海</option>
<option value="">深圳</option>
</select>
<input type="button" value="+" onclick="popUp();">
</p>
</form>
<script>
{#测试函数#}
function tx(cityId,cityTitle) {
//创建option标签
var tag = document.createElement('option');
//设置value
tag.value = cityId;
// 设置text属性
tag.innerText = cityTitle;
// 获取ID标签
var city = document.getElementById('city');
//最后一个位置添加option标签
city.appendChild(tag);
}
function popUp() {
{#弹窗#}
window.open("/pop/",'x1',"status=1, height=500, width=500, toolbar=0, resizable=0")
}
</script>
</body>
</html>

重启django,刷新页面,重新添加一次!效果如下:

注意:这里只是添加到浏览器了,并没有到数据库。所以刷新页面,数据会丢失!

django render传输的变量。变量只会在指定的文件渲染!如果这个文件包含了js,那么即使js使用{{  }} 语法,也不会渲染!

举例:

修改views.py,给index.html传一个id参数

from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
return render(request,"index.html") def pop(request):
if request.method == "GET":
return render(request,"add_city.html",{'id':''}) print(request.POST)
# 假设数据已经添加成功了,这里要获取添加的id和title
content = {'id':4,'title':'成都'}
# 渲染页面,用来将参数传给index.html
return render(request, 'pop_response.html',content)

在app01目录下,创建static目录,在此目录下创建test.js

alert('{{id}}');

修改index.html,添加h6标签,引入js文件

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{#测试js文件#}
<script src="{% static 'test.js' %}"></script>
</head>
<body>
<h1>添加页面</h1>
<h6>'{{ id }}'</h6>
<form>
<p><input type="text"></p>
<p>
<select id="city">
<option value="">北京</option>
<option value="">上海</option>
<option value="">深圳</option>
</select>
<input type="button" value="+" onclick="popUp();">
</p>
</form>
<script>
{#测试函数#}
function tx(cityId,cityTitle) {
//创建option标签
var tag = document.createElement('option');
//设置value
tag.value = cityId;
// 设置text属性
tag.innerText = cityTitle;
// 获取ID标签
var city = document.getElementById('city');
//最后一个位置添加option标签
city.appendChild(tag);
}
function popUp() {
{#弹窗#}
window.open("/pop/",'x1',"status=1, height=500, width=500, toolbar=0, resizable=0")
}
</script>
</body>
</html>

重启django,刷新页面

发现id没有被渲染出来

但是index.html渲染出来了

在window.open中,name重名,只会打开1个

如果定义了多个window.open,会被浏览器拦截

只会弹出第一个,后续的都会被拦截!

总结:

主页面:
function xxxxxx(){ }
window.open('url','name','.....') popup页面:
opener.xxxxxx()
// widown.close() 补充:
js的自执行函数
用于做隔离:
(function(jq){
jq.xxx
})(jQuery)

二、Model类的继承

Django有三种继承的方式:

  • 抽象基类:被用来继承的模型被称为Abstract base classes,将子类共同的数据抽离出来,供子类继承重用,它不会创建实际的数据表;
  • 多表继承:Multi-table inheritance,每一个模型都有自己的数据库表;
  • 代理模型:如果你只想修改模型的Python层面的行为,并不想改动模型的字段,可以使用代理模型。

注意!同Python的继承一样,Django也是可以同时继承两个以上父类的!

关于这3种继承的方式,详情请参考链接:

https://www.cnblogs.com/feixuelove1009/p/8420751.html

本文主要讲解 多表继承

多表继承

这种继承方式下,父类和子类都是独立自主、功能完整、可正常使用的模型,都有自己的数据库表,内部隐含了一个一对一的关系。

举例

修改models.py

from django.db import models

# Create your models here.
class Author(models.Model): # 作者
name=models.CharField(verbose_name="姓名",max_length=32)
age=models.IntegerField(verbose_name="年龄") class AuthorDetail(Author): # 作者详情
gf=models.CharField(verbose_name="女朋友",max_length=32)
tel=models.CharField(verbose_name="作者电话",max_length=32)

它等同于原生sql语句

CREATE TABLE "Author" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(32) NOT NULL,
"age" int(11) NOT NULL
); CREATE TABLE "AuthorDetail" (
"author_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "Author" ("id"),
"gf" varchar(32) NOT NULL,
"tel" varchar(32) NOT NULL
);

使用2个命令,生成表

python manage.py makemigrations
python manage.py migrate

使用Navicat打开数据库,查看表结构,并添加数据

author表

authordetail表

父类和子类都生成了单独的数据表,authordetail中存储了author的id,也就是通过OneToOneField链接在一起。继承关系通过表的JOIN操作来表示。在JPA中称作JOINED。这种方式下,每个表只包含类中定义的字段,不存在字段冗余,但是要同时操作子类和所有父类所对应的表。

author 里面的所有字段在 authordetail 中也是有效的,只不过数据保存在另外一张数据表当中。所以下面两个语句都是可以运行的:

models.Author.objects.filter(name='xiao')
models.AuthorDetail.objects.filter(name='xiao')

修改urls.py

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
]

修改views.py

from django.shortcuts import render,HttpResponse
from app01 import models # Create your views here.
def index(request):
obj1 = models.Author.objects.filter(name='xiao').values()
obj2 = models.AuthorDetail.objects.filter(name='xiao').values()
print(obj1)
print(obj2)
return HttpResponse('ok')

重启django,访问首页

查看Pycharm控制台输出:

<QuerySet [{'age': 23, 'name': 'xiao', 'id': 1}]>
<QuerySet [{'gf': '韩雪', 'author_ptr_id': 1, 'tel': '', 'age': 23, 'name': 'xiao', 'id': 1}]>

可以看出,authordetail 表打印出本表的字段以及父表author表的字段

如果你有一个 author,那么它同时也是一个 authordetail, 那么你可以使用子 model 的小写形式从 author 对象中获得与其对应的 authordetail 对象:

修改views.py

from django.shortcuts import render,HttpResponse
from app01 import models # Create your views here.
def index(request):
obj1 = models.Author.objects.filter(name='xiao').first()
print(obj1.authordetail)
return HttpResponse('ok')

重启django,访问首页

查看Pycharm控制台输出:

AuthorDetail object

但是,如果上例中的 obj1 并不是 authordetail (比如它仅仅只是 author 对象,或者它是其他类的父类),那么在引用 p.authordetail 就会抛开RelatedObjectDoesNotExist: Author has no authordetail. 异常:

def index(request):
obj1 = models.Author.objects.create(name='zhang',age='')
print(obj1.authordetail)
return HttpResponse('ok')

也就是说,创建author实例的同时不会创建authordetail,但是创建authordetail实例的同时会创建author实例:

修改views.py

from django.shortcuts import render,HttpResponse
from app01 import models # Create your views here.
def index(request):
obj1 = models.AuthorDetail.objects.create(name="zhang",age="",gf="蒋婷婷",tel="")
obj2 = models.Author.objects.filter(name="zhang").values()
print(obj2)
return HttpResponse('ok')

刷新页面,查看Pycharm控制体输出:

<QuerySet [{'age': 25, 'name': 'zhang', 'id': 2}]>

使用Navicat打开2个表

author表

authordetail表

三、crm业务开发

新建一个项目pro_crm,应用名为crm,注意:django版本为1.11

拷贝stark app

下载代码:

链接:https://pan.baidu.com/s/1fLOGH_3G7hPTvCYKX84UdQ 密码:m8rh

将里面的stark目录拷贝至 项目根目录中

注册stark app

修改settings.py,修改INSTALLED_APPS配置项

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crm.apps.CrmConfig',
'stark.apps.StarkConfig',
]

使用stark组件

在目标app的根目录中创建stark.py

进入crm目录,创建stark.py

修改 crm-->models.py,增加表

# from rbac.models import UserInfo as RbacUserInfo
from django.db import models class Department(models.Model):
"""
部门表
"""
title = models.CharField(verbose_name='部门名称', max_length=16) def __str__(self):
return self.title class UserInfo(models.Model):
"""
员工表
"""
name = models.CharField(verbose_name='真实姓名', max_length=16)
phone = models.CharField(verbose_name='手机号', max_length=32) gender_choices = (
(1,'男'),
(2,'女'),
)
gender = models.IntegerField(verbose_name='性别',choices=gender_choices,default=1) depart = models.ForeignKey(verbose_name='部门', to="Department") def __str__(self):
return self.name class Course(models.Model):
"""
课程表
如:
Linux基础
Linux架构师
Python自动化
Python全栈
"""
name = models.CharField(verbose_name='课程名称', max_length=32) def __str__(self):
return self.name class School(models.Model):
"""
校区表
如:
北京昌平校区
上海浦东校区
深圳南山校区
"""
title = models.CharField(verbose_name='校区名称', max_length=32) def __str__(self):
return self.title class ClassList(models.Model):
"""
班级表
如:
Python全栈 面授班 5期 10000 2017-11-11 2018-5-11
"""
school = models.ForeignKey(verbose_name='校区', to='School')
course = models.ForeignKey(verbose_name='课程名称', to='Course')
semester = models.IntegerField(verbose_name="班级(期)") #
price = models.IntegerField(verbose_name="学费")
start_date = models.DateField(verbose_name="开班日期")
graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)
tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',limit_choices_to={'depart__title':'教质部'})
teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo', related_name='teach_classes',limit_choices_to={'depart_id__in':[6,7]})
memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True) def __str__(self):
return "{0}({1}期)".format(self.course.name, self.semester)

使用2个命令,生成表

python manage.py makemigrations
python manage.py migrate

修改crm-->stark.py,注册表Department

from stark.service.stark import site
from crm import models site.register(models.Department)

配置路由信息

修改urls.py,增加stark路由

from django.conf.urls import url
from django.contrib import admin
from stark.service.stark import site urlpatterns = [
url(r'^admin/', admin.site.urls),
# 导入stark组件的路由
url(r'^stark/', site.urls),
]

启动django项目,访问url: http://127.0.0.1:8000/stark/crm/department/list/

默认是没有数据的,需要添加!

由于时间关系,详细的步骤略...

完整代码,请参考

链接:https://pan.baidu.com/s/1K4YG5LY89aidRWK7j51DBg 密码:30jt

未完待续...

python 全栈开发,Day117(popup,Model类的继承,crm业务开发)的更多相关文章

  1. python学习之老男孩python全栈第九期_day024知识点总结——单继承、多继承

    一. 单继承 class A:pass # 父类,也叫基类,也叫超类 class B:pass # 父类,也叫基类,也叫超类 class AB_son(A,B):pass # 子类,也叫派生类 cla ...

  2. Python全栈工程师 (类变量、方法、继承、覆盖)

    ParisGabriel                每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰    开局一张图 Python人工智能从入门到精通 补充: 实例方法都是操作实例对象 ...

  3. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  4. python 全栈开发,Day98(路飞学城背景,django ContentType组件,表结构讲解)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  5. 学习笔记之Python全栈开发/人工智能公开课_腾讯课堂

    Python全栈开发/人工智能公开课_腾讯课堂 https://ke.qq.com/course/190378 https://github.com/haoran119/ke.qq.com.pytho ...

  6. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  7. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  8. Python全栈开发【基础二】

    Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...

  9. python 全栈开发之路 day1

    python 全栈开发之路 day1   本节内容 计算机发展介绍 计算机硬件组成 计算机基本原理 计算机 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可 ...

随机推荐

  1. Problems you may meet

    一.正确安装sklearn却提示No module named 'sklearn.lda' It seems that you have installed a newer version of sk ...

  2. Hadoop生态圈-HUE环境部署

    Hadoop生态圈-HUE环境部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.HUE简介 1>.HUE的由来 HUE全称是HadoopUser Experienc ...

  3. Scala进阶之路-尾递归优化

    Scala进阶之路-尾递归优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 递归调用有时候能被转换成循环,这样能节约栈空间.在函数式编程中,这是很重要的,我们通常会使用递归方法来 ...

  4. webStorm2018激活的方法

    问题 激活 webstorm 2018 最新版 解决步骤 License server:http://im.js.cn:8888

  5. mipsel汇编指令学习

    MIPS汇编语言基础 MIPS的系统结构及设计理念比较先进,其指令系统经过通用处理器指令体系MIPS I.MIPS II.MIPS III.MIPS IV.MIPS V,以及嵌入式指令体系MIPS16 ...

  6. js 运动框架及实例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. QMessageBox消息框

    QMessageBox提供两套接口来实现,一种是static functions(静态方法调用),另外一种 the property-base API(基于属性的API) #需要 from PyQt5 ...

  8. [ZJOI2012]波浪弱化版(带技巧的DP)

    题面 \(solution:\) 这道确实挺难的,情况特别多,而且考场上都没想到如何设置状态.感觉怎么设状态不能很好的表示当前情况并转移,考后发现是对全排列的构造方式不熟而导致的,而这一题的状态也是根 ...

  9. django(二)中间件与面向切面编程

    一.中间件概念 django 自带函数可以在几个环节调节收到请求.处理请求.处理异常.以及发送请求. 看这里给的链接好了,这是一个大佬的讲django中间件的博客,非常清楚:https://www.c ...

  10. class特性

    每个HTML元素都可以附带一个class特性.有时候,你希望有一种方法可以指定多个元素并将这些元素和页面上的其他元素区分出来,而不是单独指定文档中的某个元素. <!DOCTYPE html> ...