python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制

时间:2023-03-08 21:25:21

django  Pagination(分页)

django 自带的分页功能非常强大,我们来看一个简单的练习示例:

#导入Paginator
>>> from django.core.paginator import Paginator
#处理的对象
>>> objects = ['john', 'paul', 'george', 'ringo']
#实例化类,传入对象,每页显示条数
>>> p = Paginator(objects, )
#查看总数据条数
>>> p.count
4
#查看总页数
>>> p.num_pages >>> type(p.page_range) # `<type 'rangeiterator'>` in Python .
<class 'range_iterator'>
#返回一个包含当前页数的迭代器
>>> p.page_range
range(, )
#获取第一页的数据
>>> page1 = p.page()
>>> page1
<Page of >
#显示数据
>>> page1.object_list
['john', 'paul']
#获取第二页的数据
>>> page2 = p.page()
#显示数据
>>> page2.object_list
['george', 'ringo']
#显示当前页
>>> page2.number
2
#获取下一页 返回bool值
>>> page2.has_next()
False
#获取上一页 返回bool值
>>> page2.has_previous()
True
#获取其他页 返回bool值
>>> page2.has_other_pages()
True
#获取下一页页数
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
#获取上一页页数
>>> page2.previous_page_number()
1
#获取当前页第一条数据在总条数的索引
>>> page2.start_index() # The -based index of the first item on this page
3
#获取当前页最后一条数据在总条数的索引
>>> page2.end_index() # The -based index of the last item on this page #获取不存在的页
>>> p.page()
Traceback (most recent call last):
...
EmptyPage: That page number is less than
#获取不在范围内的页
>>> p.page()
Traceback (most recent call last):
...
EmptyPage: That page contains no results

示例

views

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def userprofile(requeset):
#处理的数据
user_profile = models.UserProfile.objects.all()
#实例化类 传入参数 处理数据,每页条数
paginator = Paginator(user_profile,)
#获取当前页
page = requeset.GET.get('page')
try:
userprofile_obj = paginator.page(page)
except PageNotAnInteger: #输入非数字转为1
userprofile_obj = paginator.page()
except EmptyPage:#超出页面范围
userprofile_obj = paginator.page(paginator.num_pages)
return render(requeset, 'app01/userprofile.html', {'userprofile': userprofile_obj})

html

{% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br />
...
{% endfor %} <div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">previous</a>
{% endif %} <span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span> {% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}
</span>
</div>

效果:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPQAAAAxCAIAAABiaBOuAAADTUlEQVR4nO2ZsZGrMBRFtydqUS2acRWkaoAWCBgiCiAgZBQzxBSgDSSBJB5G/gt/vc/3zAZeWRb4+fB8kb8MAEz5+u0TAOAuIDdgC+QGbIHcgC2QG7AFcgO2QG7AFsgN2AK5AVsgN2AL5AZsgdyALZAbsAVyA7ZAbsAWyA3YArkBWyA3YAvkBmyB3IAtbyP3PIpH31y7plaiSBBKX3uM9EAy+z00kjojN3rbqX4SbyP3HWglEtkaeYM0jVydfmH9Ru5naiXWwWDVW7ijm7wZHyY3NfRTIkuz1z+fSNl/IZA7j0WVnWr74lEXj7qoJmOMmUdR9rKsC1fBSdpn7b9RZRdV1rINRuZRuMmdmteR8Fn/ePAHXWeGPJd7CwBBi1wDhlTBi9epp94e9Nsttwils2JM2MRp5lE8etV2tgKiXfwTcamN0W0XV7IW7Sif1I0LV8kdSSzaxRZRDtsE+1i3XVGOOhgx8yjKUW/KTnJ94dATF0M00382Q1+UY6oCHUvsCJkltkGrn2yiVU6FO5iQHCtZlVwlI3M7TRf39l1N9qU2xpimck2nqfxL0LnzCEy1Na0mM4+C7LveSDfNGN12/mLYN3Wv76Hc23EJcm8ofQCIgoDXMLLwWVTQStCNmFzhNJacZm6ywmT1jHGfURW0AMidRyS3a6KpjnWx/XlfXQuP9Y16sF/5KJZsX8GU5c8FitQXSid91784vUJoubUSh72WDOU/z9xkTchSW4Y+qhLkzuOoc5M6bjRVpwar+FnvOV1t+14OOPnqX9XJ79w0hz2bOI3szv3vcpPKTvLRqeH8Q+HEdZnbtVsfFfa3jGvCjm8HdxGQytzBoG67IIgHmfsluZMYnJe56QXPb/2yM3cYRbQSGTeUO1PJUi+qdHXegnhYPaZc17mrPrptTxvDRN2eT5JsJPvdEue0XX+U8eXxym5J9JzPGU2sr93FkDJq7YeZJNx0OdwASXZLjs+N3Eehe/h5VHM1aao6SHqTdDtadhvg6U3LH+eGzM2Em7eZwf1A7oD/+QMhuB/IHRGkArTtPw/rn9/BZwO5AVsgN2AL5AZsgdyALZAbsAVyA7ZAbsAWyA3YArkBWyA3YAvkBmyB3IAtkBuwBXIDtnwDHeqopreIeL0AAAAASUVORK5CYII=" alt="" />

自定义分页

分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

4、在数据表中根据起始位置取值,页面上输出数据


需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、设定显示多少页号

4、获取当前数据总条数

5、根据设定显示多少页号和数据总条数计算出,总页数

6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

7、在数据表中根据起始位置取值,页面上输出数据

8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

实例:

views

from django.utils.safestring import mark_safe
def try_int(arg,default):
try:
arg = int(arg)
except Exception:
arg = default
return arg class Pageinfo(object):
def __init__(self,page,count,per_item=2):
self.cur_page = page
self.all_count = count
self.per_item = per_item
@property
def start(self):
return (self.cur_page-1)* self.per_item
@property
def end(self):
return self.cur_page * self.per_item
@property
def all_page_count(self):
temp = divmod(self.all_count,self.per_item)
if temp[1] == 0:
all_page_count = temp[0]
else:
all_page_count = temp[0] + 1
return all_page_count def Custompager(baseurl,currentPage,totalpage): #基础页,当前页,总页数
perPager=11
#总页数<11
#0 -- totalpage
#总页数>11
#当前页大于5 currentPage-5 -- currentPage+5
#currentPage+5是否超过总页数,超过总页数,end就是总页数
#当前页小于5 0 -- 11
begin=0
end=0
if totalpage <= 11:
begin=0
end=totalpage
else:
if currentPage>5:
begin=currentPage-5
end=currentPage+5
if end > totalpage:
end=totalpage
else:
begin=0
end=11
pager_list=[]
if currentPage<=1:
first="<a href=''>首页</a>"
else:
first="<a href='%s%d'>首页</a>" % (baseurl,1)
pager_list.append(first) if currentPage<=1:
prev="<a href=''>上一页</a>"
else:
prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
pager_list.append(prev) for i in range(begin+1,end+1):
if i == currentPage:
temp="<a href='%s%d' style='color:red;'>%d</a>" % (baseurl,i,i)
else:
temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
pager_list.append(temp)
if currentPage>=totalpage:
next="<a href='#'>下一页</a>"
else:
next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
pager_list.append(next)
if currentPage>=totalpage:
last="<a href=''>末页</a>"
else:
last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
pager_list.append(last)
result=''.join(pager_list)
return mark_safe(result) #把字符串转成html语言
from app01 import common
def indexAuthor(request,page):
page = common.try_int(page,1) #获取当前页
# 0 5 1
# 5 10 2
# 10 15 3
# 15 20 4
baseurl = request.path #获取当前url
count = models.Author.objects.all().count() #获取处理的数据总条数
obj = common.Pageinfo(page, count) #实例化当前页和数据总条数
authors_ret = models.Author.objects.all()[obj.start:obj.end] #显示当前页的数据
page_string = common.Custompager(baseurl, page, obj.all_page_count) #返回分页栏对象 ret = {"AuthorList": authors_ret, 'count':count, "page":page_string}
return render_to_response("app01/Author.html",ret)

html

<style>
#Pageing a{
background-color: #2b669a;
border: 1px solid white;
text-decoration: none;
color: white;
padding: .1em .6em .2em .6em;
}
</style>
<div class="mains">
<table name="Author" class="table table-bordered table-hover">
<thead>
<tr>
<th>选择</th>
<th>ID</th>
<th>作者</th>
<th>邮箱</th>
<th>手机</th>
<th>性别</th>
</tr>
</thead>
<tbody id="tb3">
{% for item in AuthorList %}
<tr>
<td><input type="checkbox" /></td>
<td name="id">{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.email }}</td>
<td>{{ item.mobiles }}</td>
<td>{{ item.get_gender_display }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>总条数:{{ count }}</div>
<div id="Pageing">
{{ page }}
</div>
</div>

效果:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUQAAABHCAIAAADwa6mLAAAFb0lEQVR4nO2cv2sjRxTH9QeENPkD0qW5citVV+mqgMHFQSBwJoUqkeLcRFVQ4VxjAjakUQqBuYQrDgw6ECkOXBwKRBhsFg7LYGEwFip0YEsgWKzipZB/SCvt7szO29Ho6fthMFrt7NunefvR7K7XzhEAQAS5ZScAAOABMgMgBMgMgBAgMwBCgMwACAEyAyAEyAyAECAzAEKAzAAIATIDIATIDIAQIDMAQoDMAAgBMgMgBMgMgBDuZfY8b+Hqhe9HdVbpqb4tAECLp5lZXTwvgvkNY14AAHiZOc1eKGSIkLdRnSfvTP+MD6vE5fsfpr88dv30oQAQx9NpduJ8SxET7EKTo+JERVZheFQu1ru6WwGwJqS5Zn5cFe+kyum3Fv7+Zq2dYjsA1oKUN8BCiiqeZpvJ3K0Xi+VfX73Ie17+Ral23NcPAYBgNGSOmWlDaxfaG3UVHeoQSdDc8fI7zeFkadjcfbXvB0kfD4D1Qe+aOUSKtellDtH/p+SVj4YaWwAgG72HRmKcn7Yx5hshSmZ9/F2vVMepNgAPLJBZ3TTFmZlHZn8/n99/+mVUv17K7xzjPBuABxY/NBL1OvROzA2t0ES9cPOo/hG0a5vf7x5PTqyDy3qp+P4ytj8A60WOFB7tUPFcXdG0MhP1j2uvN597nvd88/VfPq6XAZhmscwTEmfgxMWorwmOa2YAwAy5kGmKt7LjO8yvSpz8AQCG4E8gARACZAZACJAZACFAZgCEkCOiZ8Xq0tskm6WnscSc1yeaneZOzpB5BZrLwrgczU5zJ2eHZI7qwDtSukPvQp1cFsblaHaaO0eUFZGJFGfm+T6hdxR35tTQ289ZJZ9VjGY+ki5UJ6ozVyYWiJNZMYTW0GQ99CYts5x/a32b62yYRiu8veiMJr3Gg95FpWyW257f6o+JiCi4bvtFvupkURr26tg/ti2gcc2cRc90h0u6XSwn558qp999Qzljmcv+2R0N2idb5Wqh6p+NKOj8Z5Db0adbCnoX2+XqZu2ic0fXrQ9c1WEvTYbV0d9F6kwsoCpzYrfEPS1l6Jeb8/bGy8FXXw/yL/vmMjdviL4cPCxunQxp1H2TOtrb7oBGn6r3i4c9ot45V3VYSmOhOupps2RiAaUbYFGol1BxLyaVTne4ZJrz9sbPjR//KBR/6ZjLPNsq7YBG3QpDtL+33l1e07jT5J+Z0xXFWnXUA7JkYgG2u9lai9kNveLHtpszt8zlk9M7uj5pGEf7t3U7DoiC/tXve2zVme45P6TuVEcxDa5MLJDVzBy/aHi4qARMESSznHllbhz2xkHvnO+WVePgKjA6adcZVfeqkxyQJRMLSJuZtZqtnBllbhx0Ahp138TeytYez+pVn4LWO55ousO47Oo8dWY51GOCZw1mZgs5M8m855/eUnB7lWhycrSPX4huDh/jzN4PM6wOS2ksVuc+1PTPLDKxQCYz8/wmjEOvGFA3SJY5c8i8d965u/9lkuJHi4s2uepufSwUq8/KH/7sBPHn7VrVYSmNteo89pl/wZuJBfgf55weFPWDQL2n4ghqtYxzZpC50p7/R6Q3hwa5Faqfz0aTh0Y4HkHJrDSZVociLM3i2LYA22l2zPBFvZ/6cGE8YmzmvCbRLOzXvDrza+cXaVZvw0wswDMzK34kw6FPhOVA4cpZt4mJxrJf+9WJOc5ZMrEA/gTSlZzXJ5qd5k7OkHkFmsvCuBzNTnMnZ8i8As1lYVyOZqe5kzNkXoHmsjAuR7PT3MnZqswAAAFAZgCEAJkBEAJkBkAIkBkAIUBmAIQAmQEQAmQGQAiQGQAhQGYAhACZARACZAZACJAZACFAZgCEAJkBEAJkBkAIkBkAIfwP6jfXRi8LDloAAAAASUVORK5CYII=" alt="" />

总结,分页时需要做三件事:

  • 创建处理分页数据的类
  • 根据分页数据获取数据
  • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

django Custom template tags and filters (simple_tag and filters)

自定义一个template_tag 或 filters 需要遵循以下规则

a.目录结构

在app中创建包(必须是在app中,否则会提示没有注册),名称必须为:templatetags

polls/   #app
__init__.py
models.py
templatetags/ #app下的包或模块
__init__.py
poll_extras.py
views.py
b. 创建任意.py文件 
from django import template 导入模板
from django.utils.html import format_html#这条用作处理将字符串当做标签发送前端
register = template.Library() 注册才能使用
@register.filter
def test_upper(val):
print("--val from template:",val )
return val.upper() @register.simple_tag
def guess_page(current_page,loop_num):
offset = abs(current_page - loop_num)
if offset <3:
if current_page == loop_num:
page_ele = '''<li class="active"><a href="?page=%s">%s</a></li>''' %(loop_num,loop_num)
else:
page_ele = '''<li class=""><a href="?page=%s">%s</a></li>''' %(loop_num,loop_num)
return format_html(page_ele)
else:
return ''
c.在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xx %} #xx为你定义的文件,不带py
d.使用simple_tag 或 filter
{% item.status|test_upper %}
{% guess_page classlist.number classlist.paginator.num_pages %}

e. 注册app

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
)

实例:利用simple_tag写分页功能

custom.py

@register.simple_tag
#显示前后3条数据
def get_page(current_page,total_page):
page_html = []
if current_page <= 1:
prev = """<li class="">
<a href="?page=%s" aria-label="Previous">
<span aria-hidden="true">&laquo;</span></a></li>""" % (1, )
else:
prev = """<li class="">
<a href="?page=%s" aria-label="Previous">
<span aria-hidden="true">&laquo;</span></a></li>""" % (current_page-1,)
page_html.append(prev)
for i in range(1, total_page+1):
offset = abs(current_page - i)
if offset < 3:
if current_page == i:
page_ele = '''<li class='active'><a href="?page= %s">%s</a></li>''' % (i, i)
else:
page_ele = '''<li><a href="?page=%s">%s</a></li>''' % (i, i)
page_html.append(page_ele)
else:
page_html = page_html
if current_page >= total_page:
next = """<li class="">
<a href="?page=%s" aria-label="Next">
<span aria-hidden="true">&raquo;</span></a></li>""" % (total_page,)
else:
next = """<li class="">
<a href="?page=%s" aria-label="Next">
<span aria-hidden="true">&raquo;</span></a></li>""" % (current_page+1,)
page_html.append(next)
return format_html(''.join(page_html))

views

def course(requeset):
course_list = models.Course.objects.all()
paginator = Paginator(course_list,1)
page = requeset.GET.get('page')
try:
course_obj = paginator.page(page)
except PageNotAnInteger:
course_obj = paginator.page(1)
except EmptyPage:
course_obj = paginator.page(paginator.num_pages)
return render(requeset, 'app01/course.html', {'course_list': course_obj})

html

    <div class="pagination">
<nav>
<ul class="pagination">
{% get_page course_list.number course_list.paginator.num_pages %}
</ul>
</nav>
</div>

Django权限机制的实现

Django权限机制概述

权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活;用好权限机制,能让系统更加强大和健壮。因此,基于Django的开发,理清Django权限机制是非常必要的。

Django的权限控制

Django用user, group和permission完成了权限机制,这个权限机制是将属于model的某个permission赋予user或group,可以理解为全局的权限,即如果用户A对数据模型(model)B有可写权限,那么A能修改model B的所有实例(objects)。

group的权限也是如此,如果为group C 赋予model B的可写权限,则隶属于group C 的所有用户,都可以修改model B的所有实例。

这种权限机制只能解决一些简单的应用需求,而大部分应用场景下,需要更细分的权限机制。以博客系统为例,博客系统的用户可分为『管理员』、『编辑』、『作者』和『读者』四个用户组;博客系统管理员和编辑具有查看、修改和删除所有的文章的权限,

作者只能修改和删除自己写的文章,而读者则只有阅读权限。管理员、编辑和读者的权限,我们可以用全局权限做控制,而对于作者,全局权限无法满足需求,仅通过全局权限,要么允许作者编辑不属于自己的文章,要么让作者连自己的文章都无法修改。

上述的应用场景,Django自带的权限机制无法满足需求,需要引入另一种更细的权限机制:对象权限(object permission)

Object Permission是一种对象颗粒度上的权限机制,它允许为每个具体对象授权。仍沿用最开始的例子,如果model B有三个实例 B1,B2 和B3,如果我们把B1的可写权限赋予用户A,则A可以修改B1对象,而对B2,B3无法修改。

对group也一样,如果将B2的可写权限赋予group C,则隶属于group C的所有用户均可以修改B2,但无法修改B1和B3。结合Django自带权限机制和object permission,博客系统中作者的权限控制迎刃而解:系统全局上不允许作者编辑文章,

而对于属于作者的具体文章,赋予编辑权限即可。

Django其实包含了object permission的框架,但没有具体实现,object permission的实现需要借助第三方appdjango-guardian,我们在开发中用调用django guradian封装好的方法即可。

在django权限控制的基础上扩展,自己添加一些业务系统的权限控制。

自己写权限要注意:

  1. 权限系统的设计对开发者、用户要实现透明,即他们不需要改变自己原有的使用系统或调用接口的方式
  2. 权限要易扩展,灵活
  3. 权限要能实现非常小的粒度的控制,甚至细致到一个按键某个用户是否能按。

想对一个功能实现权限控制,要做到只不过在views方法上加一个装饰器在url中添加一条记录就行了,比如:

views

@check_permission
@login_required
def customer_detail(request,customer_id):
customer_obj = models.Customer.objects.get(id=customer_id)
customer_form = forms.CustomerDetailForm(instance=customer_obj) if request.method == 'POST':
customer_form = forms.CustomerDetailForm(request.POST,instance=customer_obj)
if customer_form.is_valid():
customer_form.save()
parent_base_url = '/'.join(request.path.split('/')[:-2])
print("url:",parent_base_url )
return redirect(parent_base_url)
else:
print(customer_form.errors)
return render(request,'crm/customer_detail.html',{'customer_form':customer_form})

urls.py

from django.conf.urls import url,include
from crm import views
urlpatterns = [
url(r'^$',views.dashboard ),
url(r'^customers/$',views.customers,name="customer_list"),
url(r'^customers/(\d+)/$',views.customer_detail,name="customer_detail" ),
]

实现控制:permissions.py

from django.core.urlresolvers import resolve
from django.shortcuts import render
perm_dic = {
# 权限 url别名 请求方式 参数
'view_customer_list': ['customer_list','GET',[]],
'view_customer_info': ['customer_detail','GET',[]],
'edit_own_customer_info': ['customer_detail','POST',['qq','name']],
} def perm_check(*args,**kwargs):
request = args[0]
print(":::",getattr(request,request.method))
print(":::",request.GET)
url_resovle_obj = resolve(request.path_info) #将完整url转换成字符串
current_url_namespace = url_resovle_obj.url_name #获取别名
app_name = url_resovle_obj.app_name #use this name later 获取app name
print(":::::",app_name)
print("url namespace:",current_url_namespace)
matched_flag = False # find matched perm item
matched_perm_key = None #权限字段,默认为空
if current_url_namespace is not None:#if didn't set the url namespace, permission doesn't work
print("find perm...") #先判断别名即首先的符合url请求
for perm_key in perm_dic: #循环权限字段
perm_val = perm_dic[perm_key] #权限描述
if len(perm_val) == 3:#otherwise invalid perm data format 必须包含三个字段 url别名,请求方式,请求参数
url_namespace,request_method,request_args = perm_val
print(url_namespace,current_url_namespace)
if url_namespace == current_url_namespace: #matched the url url别名匹配
if request.method == request_method:#matched request method 方法匹配
if not request_args:#if empty , pass #没有参数就匹配完事了
matched_flag = True
matched_perm_key = perm_key #将权限字段取出来
print('mtched...')
break #no need looking for other perms
else:
for request_arg in request_args: #might has many args 匹配参数字段
request_method_func = getattr(request,request_method) #get or post mostly #获取请求方法
print("----->>>",request_method_func.get(request_arg))
if request_method_func.get(request_arg) is not None: #判断参数是否正确
matched_flag = True # the arg in set in perm item must be provided in request data
else:
matched_flag = False #只要有一个参数错误,跳出
print("request arg [%s] not matched" % request_arg)
break #no need go further
if matched_flag == True: # means passed permission check ,no need check others #检查通过
print("--passed permission check--")
matched_perm_key = perm_key #获取权限字段
break else:#permission doesn't work #类似于iptables中默认规则为true,都不匹配的时候放行
return True if matched_flag == True:
#pass permission check
perm_str = "crm.%s" %(matched_perm_key) #crm.view_customer_list
if request.user.has_perm(perm_str): #检查用户是否拥有该权限
print("\033[42;1m--------passed permission check----\033[0m")
return True
else:
print("\033[41;1m ----- no permission ----\033[0m")
print(request.user,perm_str)
return False
else:
print("\033[41;1m ----- no matched permission ----\033[0m") #定义装饰器 检测一个完整的动作[url别名+请求方式+请求参数]是否匹配,再检查用户权限
def check_permission(func):
def wrapper(*args,**kwargs):
print('---start check perm---')
if perm_check(*args,**kwargs) is not True:#no permisssion
return render(args[0],'crm/403.html') #没有权限跳珠到403界面
return func(*args,**kwargs) #正常运行
return wrapper

models.py #注册权限进数据库

class UserProfile(models.Model):
user = models.OneToOneField(User) #一对一 类似于外键 添加unique = true
name = models.CharField(max_length=64)
school = models.ForeignKey('School')
def __str__(self): #自定义对象返回可看信息
return self.name
class Meta: #自定义权限控制,只是借用model一个对象操作,并不是在model层面控制。
permissions =(('view_customer_list', u"可以查看客户列表"),
('view_customer_info',u"可以查看客户详情"),
('edit_own_customer_info',u"可以修改自己的客户信息"),
)
===================================================================================
另一种方式
from app01.models import UserProfile
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType content_type = ContentType.objects.get_for_model(UserProfile)
permission = Permission.objects.create(codename='view_customer_list',
                                       name=u"可以查看客户列表",
                                       content_type=content_type) codename   'view_customer_list' 代码逻辑中检查权限时使用
name permissions的描述将permissions打印到屏幕或页面显示
content_type 权限属于那个对象

更多:

https://docs.djangoproject.com/en/1.9/topics/pagination/

  http://www.cnblogs.com/wupeiqi/articles/5237704.html

  http://www.cnblogs.com/alex3714/articles/5535652.html

http://www.jianshu.com/p/01126437e8a4