学习网开发

本文总阅读量

前记

升级版的增删改查项目,并使用xadmin来替代django自带的admin为后台

github

代码仓

主要功能

学生可以通过机构,老师或课程进入学习课程。

  • 用户登录设计
    • 异步发送邮件
  • 缓存设计
  • 后台管理

new

缓存设计

篇幅稍长,点击跳转

异步发送邮件

篇幅稍长,点击跳转

xadmin

篇幅稍长,点击跳转

模板使用

for循环里面的自增

1
2
3
4
{{forloop.counter}}
实现for里面数字递增
{{forloop.counter0}}
则从0开始递增

显示model的带有choice字段

models 例如degree中有choice(1,名字)
在模板中要输入get_degree_display 才会显示 名字
如果输入degree 只会显示1

调用外键数据

***_set可以反向调用以自己为外键的数据库

导航块的active

通过request.path判断当前url是否等于我们要的url如果是就付于active。
如果是首页则使用’/‘就可以了,其他的需要用slice获取前几位数。
需要注意的是slice获取的是包有前面的’/‘却没包含后面的’/‘,如’/course’

1
2
<li {% if request.path == '/' %}class="active"{% endif %}><a href="{% url 'index' %}">首页</a></li>
<li {% if request.path|slice:'7' == '/course' %}class="active"{% endif %}>

django pure pagination的使用

view的修改
将从数据库查询到的数据和获取到的page放入Paginator中,并返回给html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class OrgView(View):
"""
课程机构列表
"""
def get(self, request):

all_orgs = CourseOrg.objects.all()

#分页
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1

#第二个的参数为每页显示多少数量
p = Paginator(all_orgs, 10, request=request)
orgs = p.page(page)

return render(request, "org-list.html", {
"all_orgs": orgs,
})

HTML中原for循环

1
{% for course_org in all_orgs %}
1
{% for course_org in all_orgs.object_list %}

html中分页的组件改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</div>
<div class="pageturn">
<ul class="pagelist">
{% if all_orgs.has_previous %}
<li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}">上一页</a></li>
{% endif %}

{% for page in all_orgs.pages %}
{% if page %}
{% ifequal page all_orgs.number %}
<li class="active"><a href="">{{ page }}</a></li>
{% else %}
<li class="page"><a href="?{{ page.querystring }}">{{ page }}</a></li>
{% endifequal %}
{% else %}
<li class="none"><a href="">...</a> </li>
{% endif %}
{% endfor %}
{% if all_orgs.has_next %}
<li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}">下一页</a>
{% endif %}
</ul>
</div>
</div>

数据库使用

在project的__init__文件添加

1
2
import pymysql
pymysql.install_as_MySQLdb()

后可以使用数据库

定义自己的user表

定义自己的user表时,先生成表再,AUTH_USER_MODEL = “users.UserProfile”指定自己的user表,不然django会报找不到外键的错。

原因:在models.py中定义了一个User表,此表继承django.contrib.auth中的User表。python manage.py migrate在建表的过程中先创建了我在models.py 中创建的User表,这样问题就来了,找不到父类的表,就出现can not add foreign key constraint 这个错误。所以,先保证django.contrib.auth中的user表建立,然后在创建自己定义的user表就可以了

也可以删除所有表除了auth_user,还有删除migration所有类型0001_initial.py文件。再重新生成表

xadmin的版本问题

xadmin 有多个版本,由于我使用django 1.11, 代码仓关于1.11的分支已经删除了,所以重新找了一个
https://github.com/nocmt/Xadmin1.11.x/archive/master.zip
版本支持django 1.11

MEDIA_URL空值

做如下处理可以防止

1
{{ MEDIA_URL}}

空值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.media',添加这行或者下面一行
#'django.core.context_processors.media',python3会报错
],
},
},
]

限制网页需要登录的用户访问

在django中限制用户需要登录才能访问某些页面时可以自己在django_project定义如下.py文件

1
2
3
4
5
6
7
8
9
10
11
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator


class LoginRequiredMixin(object):
'''
验证是否登录(需要登录的页面可以配置该函数)
'''
@method_decorator(login_required(login_url='/login/'))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

然后在页面对应的view 类视图函数 放入LoginRequiredMixin

models.form验证数据

使用models.form来验证并取数据时,要确保要获取的数据的html的id和自己定义的model名称要对应,不然clean_data取不了数据,会认为数据不通过

不使用@Login_required的登录跳转

@Login_required有些坑,在不考虑使用@Login_required可以通过以下方法设置跳转

login页面的html的form写入以下代码:

1
<input type="hidden" name="next_url" value="{{ next_url }}">

login view函数设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class LoginView(View):
"""
LoginForm验证数据(./forms.py)
"""
def post(self, request):
login_from = LoginForm(request.POST)
if login_from.is_valid():
user_name = request.POST.get("username", "")
pass_word = request.POST.get("password", "")
+ next_url = request.POST.get("next_url", "")
user = authenticate(username=user_name, password=pass_word)
if user: #用户是否存在
if user.is_active: #用户是否处于激活状态
login(request, user)
+ if next_url:
+ return HttpResponseRedirect(next_url)
+ else:
+ return HttpResponseRedirect(reverse("index"))
else:
return render(request, "login.html", {"msg": "请激活账户"})
else:
return render(request, "login.html", {"msg": "用户名或密码错误"})
else:
return render(request, "login.html", {
"login_form": login_from
})

def get(self, request):
+ next_url = request.META['HTTP_REFERER']
return render(request, "login.html", {
+ "next_url": next_url
})

关注左边带有+的代码
利用Miscellaneous 头域的Referer传递的跳转url写入login的html里面,然后在post时获取next_url的数值,验证登录成功时通过HttpResponseRedirect(next_url)返回到刚才的url。

查看评论