前记
升级版的增删改查项目,并使用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 %}>
|
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
做如下处理可以防止
空值
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中限制用户需要登录才能访问某些页面时可以自己在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来验证并取数据时,要确保要获取的数据的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。