第 1 章 课程介绍
1-1 项目演示和课程介绍;
第 2 章 Windows下搭建开发环境
2-1 Pycharm、Navicat和Python解释器的安装;
Pycharmhttp://www.jetbrains.com/pycharm/
MacOS 版本的MySQL 8.0.12;
Navicat for MySQL 11.1.3;
Python 2.7.15;
Pycharm Professional 2018.3;
http://www.jetbrains.com/pycharm/
2-2 Virtualenv安装和配置;
2-3 Pycharm和Navicat的简单使用;
第 3 章 通过留言板功能回顾Django基础知识
3-1 Django目录介绍
- djangoproject;
- log;
- media;
- apps;
- templates;
- static;
3-2 配置表单页面
3.2.1 安装pip install pymysql并在项目根目录的__init__.py文件中添加如下配置,解决报错问题:(使用pymysql代替mysqlclient、MySQL-python)
PS:不同的Python版本,使用不同的pip,比如pip3 install xxxx; pip install xxx;
Error:MySQLdb Module 'Did you install mysqlclient or MySQL-python? 使用django开发时,发现安装了mysql和mysql-python还是报错,可以__init__.py文件中加入以下代码解决: import pymysql pymysql.install_as_MySQLdb()
3.2.2 使用Pycharm工具作为MySQL图形化工具连接MySQL数据库;
3.2.3 使用Pycharm工具启动并运行Django项目;
3.2.4 settings.py配置;
- DATABASES = {}
- TEMPLATES下的DIRS;
- 新增STATICFILES_DIRS = []
- INSTALLED_APPS = []
3.2.5 python manage.py makemigrations& python mange.py migrate 进行数据库迁移;
3.2.6 编写urls.py;
3.2.7 编写views.py;
3.2.8 通过render渲染html文件;
settings.py;
"""
Django settings for DjangoStart project. Generated by 'django-admin startproject' using Django 1.11.15. For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
""" import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'p2rjom3lf=n&y+piru&j-ky+$l_-9$o710k9=nrchp!2j=^gnk' # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ROOT_URLCONF = 'DjangoStart.urls' 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',
],
},
},
] WSGI_APPLICATION = 'DjangoStart.wsgi.application' # Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases # DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'imc_django',
'USER': 'root',
'PASSWORD': 'Tqtl911!@#)^',
'HOST': '127.0.0.1',
'PORT': '',
} } # Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
] # Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
message_form.html;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/static/css/style.css">
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<form action="/form/" method="post" class="smart-green">
<h1>留言信息
<span>请留下你的信息.</span>
</h1>
<label>
<span>姓名 :</span>
<input id="name" type="text" name="name" class="error" placeholder="请输入您的姓名"/>
<div class="error-msg"></div>
</label> <label>
<span>邮箱 :</span>
<input id="email" type="email" value="" name="email" placeholder="请输入邮箱地址"/>
<div class="error-msg"></div>
</label> <label>
<span>联系地址 :</span>
<input id="address" type="text" value="" name="address" placeholder="请输入联系地址"/>
<div class="error-msg"></div>
</label> <label>
<span>留言 :</span>
<textarea id="message" name="message" placeholder="请输入你的建议"></textarea>
<div class="error-msg"></div>
</label>
<div class="success-msg"></div>
<label>
<span> </span>
<input type="submit" class="button" value="提交"/>
</label>
</form> </body>
</html>
3-3 Django orm介绍与model设计
3.3.1 Django-model初识;
3.3.2 通过执行数据库迁移操作,生成以“应用名_表名”的数据表;
PS:补充
- id如果不指定,自动创建;
- verbose_name可以理解为表名的tag值;
- class Meta指定表的相关属性,如表名、排序规则,即表级别操作!
Django中其他的字段类型:
models.ForeignKey
models.DateTimeField
models.IntegerField
models.IPAddressField
models.FileField
models.ImageField
models.py通过类的形式生成UserMessage表;
# -*- coding: utf-8 -*-
from __future__ import unicode_literals from django.db import models # Create your models here.
class UserMessage(models.Model):
object_id = models.CharField(max_length=50, default="", primary_key=True, verbose_name=u"主键")
name = models.CharField(max_length=32, null=True, blank=True, default="", verbose_name='用户名')
email = models.EmailField(verbose_name='邮箱')
address = models.CharField(max_length=100, verbose_name=u'联系地址')
message = models.CharField(max_length=500, verbose_name=u'留言信息')
"""
Django中其他的字段类型:
models.ForeignKey
models.DateTimeField
models.IntegerField
models.IPAddressField
models.FileField
models.ImageField
""" class Meta:
verbose_name = u'用户留言信息'
verbose_name_plural = verbose_name # db_table = "user_message"
# ordering = "-object_id"
# ordering = "object_id"
3-4 Django model的增删改查
3.4.1 {% crsf_token %}防止跨站请求伪造,form表单必须配置 ;
3.4.2 /form/,尾部加“/”的问题;
3.4.3 Django中的debug模式应用;
3.4.4 同级目录模块之间的导入问题;
3.4.5 数据的创建和删除;
3.4.6 Django-settings.py配置文件中,INSTALLED_APPS的配置问题;
# -*- coding: utf-8 -*- from __future__ import unicode_literals
import os, django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "DjangoStart.settings") # project_name 项目名称
django.setup() from django.shortcuts import render, redirect
from django.http import HttpResponse
from message.models import UserMessage # Create your views here.
def getform(request):
all_messages = UserMessage.objects.filter(name='cuixiaozhao', address='北京') # Django的QuerySet类型;
for message in all_messages:
# 数据的删除
message.delete()
# print message.name # # 数据的创建:
# if request.method == "POST":
# name = request.POST.get('name', '')
# message = request.POST.get('message', '')
# address = request.POST.get('address', '')
# email = request.POST.get('email', '')
# user_message = UserMessage()
# user_message.name = name
# user_message.message = message
# user_message.address = address
# user_message.email = email
# user_message.object_id = 'HelloDjango1'
# user_message.save() # Debug模式;
# user_message = UserMessage()
# user_message.name = 'cuixiaosi'
# user_message.message = 'HelloDjango'
# user_message.address = '上海'
# user_message.email = 'tqtl911@163.com'
# user_message.object_id = 'HelloDjango'
# user_message.save() return render(request, 'message_form.html', )
3-5 Django url templates 配置
3.5.1 Django中的url配置;
- URL中的注意事项之url(r'^form/$', views.getform,name='go_form');
3.5.2 Django中的templates配置;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<form action="{% url 'go_form' %}" method="post" class="smart-green">
{% csrf_token %}
<h1>留言信息
<span>请留下你的信息.</span>
</h1>
<label>
<span>姓名 :</span>
{# <input id="name" type="text" value="{{ message.name }}" na me="name" class="error" placeholder="请输入您的姓名"/>#}
<input id="name" type="text" value="{% ifequal message.name|slice:'5' '崔晓昭' %}崔天晴{% else %} 天晴天朗 {% endifequal %}" name="name" class="error" placeholder="请输入您的姓名"/>
<div class="error-msg"></div>
</label> <label>
<span>邮箱 :</span>
<input id="email" type="email" value="{{ message.email }}" name="email" placeholder="请输入邮箱地址"/>
<div class="error-msg"></div>
</label> <label>
<span>联系地址 :</span>
<input id="address" type="text" value="{{ message.address }}" name="address" placeholder="请输入联系地址"/>
<div class="error-msg"></div>
</label> <label>
<span>留言 :</span>
<textarea id="message" name="message" placeholder="请输入你的建议">{{ message.message }}</textarea>
<div class="error-msg"></div>
</label>
<div class="success-msg"></div>
<label>
<span> </span>
<input type="submit" class="button" value="提交"/>
</label>
</form> </body>
</html>
第 4 章 需求分析和model设计
4-1 使用Python3.6 和 Django1.11 开发系统前注意事项(补充小节)
4.1.1 mkvirtualenv -p 指定Python3.x的安装路径;
4.1.2 def __str__(self):的使用;代替__unicode__(self:;
4.1.3 使用Python3开发,使用Mysqlclient代替MySQL-python,最终pymysql代替两者;
4.1.4 使用xadmin以及extra_apps;
4.1.5 github下的mxonline_resource;
4.1.6 requirement.txt安装依赖;
4.1.7 富文本工具DjangoUeditor的使用注意;
4-2 使用Django2.0开始课程的注意事项
4.2.1 慕课网Django+xadmin打造生鲜电商项目;
4.2.2 基于慕课网的 github地址申请;
4-3 Django-app设计
4.3.1 django-app的设计;
4.3.2 各个app models设计
4.3.3 数据表生成与修改;
4-4 新建项目
4.4.1 使用Pycharm新建Django项目-MxOnline;
4.4.2 使用NavicatForMySQL工具,创建数据库实例:MxOnline;
4.4.3 安装mysql驱动-pip install mysql-python报错的替代解决方案之pymysql;
4.4.4 settings.py中修改DATABASES配置;
4.4.5 python manage.py执行数据库迁移操作,并生成数据表;
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'MxOnline',
'USER': 'root',
'PASSWORD': 'Tqtl911!@#)^',
'HOST': '127.0.0.1',
'PORT': '',
'OPTIONS': {
'autocommit': True,
},
}
}
4-5 自定义userprofile
4.5.1 auth_user表字段了解;
4.5.2 UserProfile类继承from django.contrib.auth.models import AbstractUser来拓展auth_user表字段;
4.5.3 settings.py中INSTALLED_APPS进行应用的注册;
4.5.4 AUTH_USER_MODEL = "users.UserProfile"在settings.py中的配置;
4.5.5 添加models.py后,必须执行数据库迁移操作:python manage.py makemigrations ;python manage.py migrate;
4.5.6 models.ImageField依赖pillow第三方库,pip3 install pillow
models.py;
# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals from django.db import models
# 继承AbstractUser
from django.contrib.auth.models import AbstractUser # Create your models here. class UserProfile(AbstractUser):
nick_name = models.CharField(max_length=50, verbose_name=u'昵称', default="")
birthday = models.DateField(verbose_name=u'生日', null=True, blank=True)
gender = models.CharField(max_length=5,choices=(("male", u"男"), ("female", u"女")), default="female")
address = models.CharField(max_length=100, default=u"")
mobile = models.CharField(max_length=11, null=True, blank=True)
image = models.ImageField(upload_to="image/%Y/%m", default=u"image/default.png", max_length=100) class Meta:
verbose_name = "用户信息"
verbose_name_plural = verbose_name def __unicode__(self):
return self.username
Unhandled exception in thread started by <function wrapper at 0x10f403e60>
Traceback (most recent call last):
File "/Users/cuixiaozhao/PycharmProjects/imooc/MxOnline/venv/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
fn(*args, **kwargs)
File "/Users/cuixiaozhao/PycharmProjects/imooc/MxOnline/venv/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
self.check(display_num_errors=True)
File "/Users/cuixiaozhao/PycharmProjects/imooc/MxOnline/venv/lib/python2.7/site-packages/django/core/management/base.py", line 472, in check
raise SystemCheckError(msg)
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues: ERRORS:
users.UserProfile.gender: (fields.E120) CharFields must define a 'max_length' attribute.
users.UserProfile.image: (fields.E210) Cannot use ImageField because Pillow is not installed.
HINT: Get Pillow at https://pypi.python.org/pypi/Pillow or run command "pip install Pillow". System check identified 2 issues (0 silenced).
4-6 user models.py设计
4.6.1 循环引用;
4.6.2 定义EmailVerifyRecord类;
4.6.3 models.py中添加# _*_ coding:utf-8 _*_ ;
# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime from django.db import models
# 继承AbstractUser
from django.contrib.auth.models import AbstractUser # Create your models here. class UserProfile(AbstractUser):
nick_name = models.CharField(max_length=50, verbose_name=u'昵称', default="")
birthday = models.DateField(verbose_name=u'生日', null=True, blank=True)
gender = models.CharField(max_length=5, choices=(("male", u"男"), ("female", u"女")), default="female")
address = models.CharField(max_length=100, default=u"")
mobile = models.CharField(max_length=11, null=True, blank=True)
image = models.ImageField(upload_to="image/%Y/%m", default=u"image/default.png", max_length=100) class Meta:
verbose_name = u"用户信息"
verbose_name_plural = verbose_name def __unicode__(self):
return self.username class EmailVerifyRecord(models.Model):
code = models.CharField(max_length=20, verbose_name=u'验证码')
email = models.EmailField(max_length=50, verbose_name=u'邮箱')
send_type = models.CharField(choices=(("register", u"注册"), ("forget", u"找回密码")), max_length=10)
send_time = models.DateTimeField(default=datetime.now) # datetime.now()不添加括号 class Meta:
verbose_name = u"邮箱验证码"
verbose_name_plural = verbose_name class Banner(models.Model):
title = models.CharField(max_length=100, verbose_name=u"标题")
image = models.ImageField(upload_to="banner/%Y/%m", verbose_name=u"轮播图")
url = models.URLField(max_length=200, verbose_name=u"访问地址")
index = models.IntegerField(default=100, verbose_name=u"顺序")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"轮播图"
verbose_name_plural = verbose_name
4-7 course models.py设计
4.7.1 创建course应用;
course/models.py设计;
# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime from django.db import models # Create your models here. # 创建四张表(类); class Course(models.Model):
name = models.CharField(max_length=50, verbose_name=u"")
desc = models.CharField(max_length=300, verbose_name=u"课程描述")
detail = models.TextField(verbose_name=u"课程详情")
degree = models.CharField(choices=(('cj', '初级'), ('zj', '中级'), ('gj', '高级')), max_length=100)
learn_times = models.IntegerField(default=0, verbose_name=u"学习时长(分钟数)")
students = models.IntegerField(default=0, verbose_name=u"学习人数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏人数")
image = models.ImageField(upload_to="courses/%Y/%m", verbose_name=u"封面")
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"课程"
verbose_name_plural = verbose_name class Lesson(models.Model):
course = models.ForeignKey(Course, verbose_name=u"课程")
name = models.CharField(max_length=100, verbose_name=u"章节名称")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"章节"
verbose_name_plural = verbose_name class Video(models.Model):
lesson = models.ForeignKey(Lesson, u"章节")
name = models.CharField(max_length=100, verbose_name=u"视频名称")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"视频"
verbose_name_plural = verbose_name class CourseResource(models.Model):
course = models.ForeignKey(Course, verbose_name=u"课程")
name = models.CharField(max_length=100, verbose_name=u"名称")
download = models.FileField(upload_to="course/resource/%Y/%m", verbose_name=u"资源文件", max_length=100)
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"课程资源"
verbose_name_plural = verbose_name
4-8 organization models.py设计
4.8.1 创建organization 应用;
4.8.1 编写organizaiton/models.py;
# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime
from django.db import models # Create your models here.
class CityDict(models.Model):
name = models.CharField(max_length=20, verbose_name=u"城市")
desc = models.CharField(max_length=200, verbose_name=u"描述")
add_time = models.CharField(default=datetime.now) class Meta:
verbose_name = u"城市"
verbose_name_plural = verbose_name class CourseOrg(models.Model):
name = models.CharField(max_length=50, verbose_name=u"机构名称")
desc = models.TextField(verbose_name=u"机构描述")
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏数")
image = models.ImageField(upload_to="org/%Y/%m", verbose_name=u"封面图片")
address = models.CharField(max_length=150, verbose_name=u"机构地址")
city = models.ForeignKey(CityDict, verbose_name=u"所在城市")
add_time = models.DateTimeField(default=datetime.now) class Meta:
verbose_name = u"课程机构"
verbose_name_plural = verbose_name class Teacher(models.Model):
org = models.ForeignKey(CourseOrg, verbose_name=u"所属机构")
name = models.CharField(max_length=50, verbose_name=u"教师名")
work_years = models.IntegerField(default=0, verbose_name=u"工作年限")
work_company = models.CharField(max_length=50, verbose_name=u"就职公司")
work_position = models.CharField(max_length=50, verbose_name=u"公司职位")
points = models.CharField(max_length=50, verbose_name=u"教学特点")
click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏数")
add_time = models.DateTimeField(default=datetime.now) class Meta:
verbose_name = u"教师"
verbose_name_plural = verbose_name
PS:shebang编码标注;
4-9 operation models.pty设计
4.9.1 operation 应用的创建;
4.9.2 operation/models.py的编写;
4.9.3 最后在settings.py中进行INSTALLED_APPS的注册;
# Application definition INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'courses',
'organization',
'operation',
]
operation/models.py;
# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals from datetime import datetime from django.db import models from users.models import UserProfile
from courses.models import Course # Create your models here.
class UserAsk(models.Model):
name = models.CharField(max_length=20, verbose_name=u"姓名")
mobile = models.CharField(max_length=11, verbose_name=u"手机")
course_name = models.CharField(max_length=50, verbose_name=u"课程名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户咨询"
verbose_name_plural = verbose_name class CourseComments(models.Model):
"""课程评论"""
user = models.ForeignKey(UserProfile, verbose_name=u"用户")
course = models.ForeignKey(Course, verbose_name=u"课程")
comments = models.CharField(max_length=200, verbose_name=u"评论")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"课程评论"
verbose_name_plural = verbose_name class UserFavorite(models.Model):
user = models.ForeignKey(UserProfile, verbose_name=u"用户")
fav_id = models.IntegerField(default=0, verbose_name=u"数据ID")
fav_type = models.IntegerField(choices=((1, "课程"), (2, "课程结构"), (3, "讲师")), default=1, verbose_name=u"收藏类型")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户收藏"
verbose_name_plural = verbose_name class UserMessage(models.Model):
user = models.IntegerField(default=0, verbose_name=u"接受用户")
message = models.CharField(default=datetime.now, verbose_name=u"消息内容")
has_read = models.BooleanField(default=False, verbose_name=u"是否已读")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户消息"
verbose_name_plural = verbose_name class UserCourse(models.Model):
user = models.ForeignKey(UserProfile, verbose_name=u"用户")
course = models.ForeignKey(Course, verbose_name=u"课程")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间") class Meta:
verbose_name = u"用户课程"
verbose_name_plural = verbose_name
4-10 数据表生成以及apps目录建立
4.10.1 Django中执行数据库迁移操作;
python manage.py makemigrations
python manage.py migrate
4.10.2 Django中的django_migrations表预览;
4.10.3 新建apps package,将所单独创立的应用移动至该目录;
4.10.4 settings.py中添加:sys.path.insert(0,os.path.join(BASE_DIR,'apps'));
import os
import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
第 5 章 通过xadmin快速搭建后台管理系统
5-1 Django admin介绍
5.1.1 后台管理系统的特点;
- 权限管理;
- 少前端样式;
- 快速开发的需求;
5.1.2 createsuperuser创建超级用户时候的报错处理;
django.db.utils.DataError: (1406, u"Data too long for column 'gender' at row 1") 1、修改gender字段的max_lenth= xxx;
2、执行数据库迁移操作:
makemigrations users
migrate users
5.1.3 解决Django报错问题-Django admin 产生'WSGIRequest' object has no attribute 'user'的错误;
实际上,这是Django版本的问题,1.10之前,中间件的key为MIDDLEWARE_CLASSES, 1.10之后,为MIDDLEWARE。所以在开发环境和其他环境的版本不一致时,要特别小心,会有坑。
改配置为:
新的settings.py配置文件如下:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
5.1.4 Django默认的登录方式,可以修改为支持用户名和邮箱登录;
5.1.5 修改Django的settings.py配置文件下的关键3项,使得admin页面显示中文;
- LANGUAGE_CODE = 'zh-hans',之前叫做zh-cn;
- TIME_ZONE = 'Asia/Shanghai'
- USE_TZ = False
5.1.6 Django admin中组的概念初识以及在admin.py中进行注册;
- Django的密码是单向的,不能反解答;
5-2 xadmin的安装
5.2.1 xadmin的安装;pip install xadmin(已存放在pypi中)
xadmin官网: http://sshwsfc.github.io/xadmin/#
- django-crispy-forms-1.7.2
- django-formtools-2.1
- httplib2-0.9.2 xadmin-0.6.1
5.2.2 xadmin位于settings.py以及admin.py中的配置;
- xadmin;
- crispy_forms;
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'courses',
'organization',
'operation',
'xadmin',
'crispy_forms',
]
5.2.3 浏览器中访问xadmin的错误解决办法:执行数据库迁移操作makemigrations & migrate,生成xadmin相关的数据表;
5.2.4 去github.com上所有xadmin并下载zip文件;
5.2.5 解压缩xadmin-master.zip文件,拷贝其中xadmin至MxOnline的根目录;
5.2.6 在MxOnline项目中新建extra_apps package,将xadmin拷贝至其中;
5.2.6 Django+xadmin ImportError: No module named 'future'的报错解决方案
在使用Django框架时,集成xadmin后,运行程序,报如下这个错:importError:No module named future.utils这是因为没安装future,
因此,执行一下如下命令安装相关依赖包即可:
1、pip install future six httplib2
2、pip install django-import-export
5.2.7 Django 运行 端口被占用 Error: That port is already in use 的解决方案:
ps aux | grep -i manage kill -9 端口号
5.2.8 源码安装xadmin以及pip install xadmin;推荐使用源码安装,好处是:体验新功能,修改源码提高程序可拓展性;
5-3 users app的model注册
5.3.1 users/models.py的注册;
5.3.2 新建adminx.py文件并进行邮箱验证码的注册;
5.3.3 重载了__unicode__(self):方法,return返回code和email
5.3.4 在adminx.py中增加新的字段——list_display以及search_fields字段;
5.3.5 在adminx.py完成各个models的注册工作;
adminx.py;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: MxOnline
# Software: PyCharm
# Time : 2018-09-26 11:18
# File : adminx.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
import xadmin
from .models import EmailVerifyRecord, Banner class EmailVerifyRecordAdmin(object):
list_display = ['code', 'email', 'send_type', 'send_time']
search_fields = ['code', 'email', 'send_type', 'send_time']
list_filter = ['code', 'email', 'send_type', 'send_time'] class BannerAdmin(object):
list_display = ['title', 'image', 'url', 'index', 'add_time']
search_fields = ['title', 'image', 'url', 'index']
list_filter = ['title', 'image', 'url', 'index', 'add_time'] xadmin.site.register(EmailVerifyRecord, EmailVerifyRecordAdmin)
xadmin.site.register(Banner, BannerAdmin)
class EmailVerifyRecord(models.Model):
code = models.CharField(max_length=20, verbose_name=u'验证码')
email = models.EmailField(max_length=50, verbose_name=u'邮箱')
send_type = models.CharField(choices=(("register", u"注册"), ("forget", u"找回密码")), max_length=10,
verbose_name=u"验证码类型")
send_time = models.DateTimeField(default=datetime.now, verbose_name=u"发送时间") # datetime.now()不添加括号 class Meta:
verbose_name = u"邮箱验证码"
verbose_name_plural = verbose_name def __unicode__(self):
return '{0}({1})'.format(self.code, self.email)
5-4 剩余app model注册
5.4.1 在其他app下新建adminx.py,注意这个文件必须叫做adminx.py!!!
5.4.2 导入xadmin模块并进行注册;
5.4.3 字段中verbose_name的设置;
5.4.4 快速注册其他apps;
注意注意:注册之后一定要重启Django项目MxOnline!!!否则你是看不到滴!!!
xadmin.site.register注册的顺序就是在前端页面展示的顺序;
5-5 xadmin的全局配置
5.5.1 xadmin的主题功能配置;
5.5.2 左上角logo以及网页标题、底部显示内容设置,基于类;
5.5.3 设置参数menu_style = "accordion",将应用下的内容收缩;
5.5.4 Django创建app后,会在目录下自动生成apps.py,在此处设置展示的语言;
5.5.5 shebang位置添加# _*_ coding:utf-8 _*_;
5.5.6 分别在应用下apps.py 以及__init__.py中添加配置;
default_app_config = "courses.apps.CoursesConfig"
# _*_ coding:utf-8 _*_
from __future__ import unicode_literals from django.apps import AppConfig class UsersConfig(AppConfig):
name = 'users'
verbose_name = u"用户操作"
注意啦!我要讲话了,在Python2.x 中,但是要是出现中文的地方,记得一定在shebang位置添加 # _*_ coding:utf-8 _*_;
注意啦!我要讲话了,在Python2.x 中,但是要是出现中文的地方,记得一定在shebang位置添加 # _*_ coding:utf-8 _*_;
注意啦!我要讲话了,在Python2.x 中,但是要是出现中文的地方,记得一定在shebang位置添加 # _*_ coding:utf-8 _*_;
重要的话讲三遍!
第 6 章 用户注册功能实现
6-1 首页和登录页面的配置
6.1.1 在Django项目中新建static目录,并在settings.py中配置STATICFILES_DIRS = []
6.1.2 拷贝静态文件如js\css\images\img等文件之static目录;
6.1.3 配置url访问路径;
6.1.4 拷贝前端同事的代码,比如index.html,login.html到templates目录下;
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
import xadmin urlpatterns = [
url(r'^xadmin/', xadmin.site.urls),
url(r'^$', TemplateView.as_view(template_name="index.html"),name="index"),
url(r'^login/$', TemplateView.as_view(template_name="login.html"),name="login"),
]
6.1.4 settings.py中引入如下内容:
# Application definition
AUTHENTICATION_BACKENDS = (
'users.views.CustomBackend',
)
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
import xadmin urlpatterns = [
url(r'^xadmin/', xadmin.site.urls),
url(r'^$', TemplateView.as_view(template_name="index.html"),name="index"),
url(r'^login/$', TemplateView.as_view(template_name="login.html"),name="login"),
]
6-2 用户登录-1
6.2.1 编写后台views逻辑代码;
6.2.2 Django防止CSRF攻击,使用{% csrf_token %}
6.2.3 Django模板中不会有很复杂的逻辑,更深层次的逻辑在后端代码中实现;
views.py;
# _*_ coding:utf-8 _*_
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from .models import UserProfile # Create your views here.
class CustomBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username) | Q(email=username))
if user.check_password(password):
return user
except Exception as e:
return None def user_login(request):
if request.method == "POST":
username = request.POST.get("username", "")
password = request.POST.get("password", "")
user = authenticate(username=username, password=password)
# 完成login的认证登录;
if user is not None:
login(request, user)
return render(request, "index.html")
else:
return render(request, "login.html", {"msg":"用户名或者密码错误!"})
elif request.method == "GET":
return render(request, "login.html", {})
6-3 用户登录-2
6.3.1在settings.py中添加参数:
6.3.2基于类的形式编写用户登录功能;
6.3.3 Django的密码存储的是密文使用check_password进行验证;
6-4 用form实现登录-1
6.4.1 基于类的形式实现类的登录;
6.4.2 LoginView.as_view();必须加括号!
urls.py;
"""MxOnline URL Configuration The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
import xadmin
from users.views import LoginView urlpatterns = [
url(r'^xadmin/', xadmin.site.urls),
url(r'^$', TemplateView.as_view(template_name="index.html"), name="index"),
url('^login/$', LoginView.as_view(), name="login"),
]
views.py;
# _*_ coding:utf-8 _*_
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.views.generic.base import View from .models import UserProfile
from .forms import LoginForm # Create your views here.
class CustomBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username) | Q(email=username))
if user.check_password(password):
return user
except Exception as e:
return None class LoginView(View):
def get(self, request):
return render(request, "login.html", {}) def post(self, request):
login_form = LoginForm(request.POST)
if login_form.is_valid():
user_name = request.POST.get("username", "")
pass_word = request.POST.get("password", "")
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, "index.html")
else:
return render(request, "login.html", {"msg": "用户名或密码错误"})
else:
return render(request, "login.html", {"login_form": login_form})
6-5 用form实现登录-2
6-6 session和cookie自动登录机制
6.6.1 cookies(浏览器本地存储方式),HTTP协议本身无状态;
6.6.2 session可以理解为服务端的cookie;
小结:
- HTTP协议本身无状态保存;
- 为了保存浏览器的一些信息,比如用户名和密码,引入了cookie机制;
- 但是cookie是有服务端生成返回给客户端即浏览器的,保存在浏览器本地,不太安全;
- 所以引出了服务端信息,session即服务端的cookie;
- PS:cookie可以理解为保存会话信息的一个键值对;
6-7 用户注册-1
6.7.1 图片验证码模块django-simple-captcha的Document;注意版本号——pip install django-simple-captcha==0.4.6 https://django-simple-captcha.readthedocs.io/en/latest/usage.html#installation
6.7.2 django验证码框架(django-simple-captcha)的使用:
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: MxOnline
# Software: PyCharm
# Time : 2018-09-26 22:45
# File : forms.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org
from django import forms
from captcha.fields import CaptchaField class LoginForm(forms.Form):
username = forms.CharField(required=True)
password = forms.CharField(required=True, min_length=5) class RegisterForm(forms.Form):
email = forms.EmailField(required=True)
password = forms.CharField(required=True, min_length=5)
captcha = CaptchaField()
6-8 用户注册-2
6.8.1 django-simple-captcha==0.4.6的效果展示;
6-9 用户注册-3
6.9.1 settings中配置发送邮件配置;
EMAIL_HOST = "smtp.mxhichina.com"
EMAIL_PORT = 25
EMAIL_HOST_USER = "tqtl@tqtl.org"
EMAIL_HOST_PASSWORD = "fdsfad."
EMAIL_USE_TLS = False
EMAIL_FROM = "tqtl@tqtl.org"
6.9.2 app下创建utils目录,并新增send_mail.py文件;
send_mail.py;
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# Project: MxOnline
# Software: PyCharm
# Time : 2018-09-27 18:41
# File : email_send.py
# Author : 天晴天朗
# Email : tqtl@tqtl.org from users.models import EmailVerifyRecord
from random import Random
from django.core.mail import send_mail
from MxOnline.settings import EMAIL_FROM def random_str(randomlength=8):
str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz01234567890'
length = len(chars) - 1
random = Random()
for i in range(randomlength):
str += chars[random.randint(0, length)]
return str def send_register_email(email, send_type="register"):
email_record = EmailVerifyRecord()
code = random_str(16)
email_record.code = code
email_record.email = email
email_record.send_type = send_type
email_record.save() email_title = ""
email_body = ""
if send_type == "register":
email_title = "慕学在线网注册激活链接"
email_body = "请点击下面的链接来激活你的账号:http://127.0.0.1:8000/active/{0}".format(code)
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
if send_status:
pass def generate_random_str():
pass
6-10 用户注册-4
6-11 找回密码(1)
6-12 找回密码(2)
第 7 章 课程机构功能实现
7-1 Django templates模板继承1
7.1.1 base.html模板编写;
base.html;
<!DOCTYPE html>
<html>
{% load staticfiles %}
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<title>{% block title %}课程机构列表 - 慕学在线网{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
{% block custom_css %}{% endblock %}
<script src="{% static 'js/jquery.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/jquery-migrate-1.2.1.min.js' %}" type="text/javascript"></script>
{% block custom_js %}{% endblock %}
</head>
<body>
<section class="headerwrap ">
<header>
<div class=" header">
<div class="top">
<div class="wp">
<div class="fl"><p>服务电话:<b>33333333</b></p></div>
<!--登录后跳转--> <a style="color:white" class="fr registerbtn" href="register.html">注册</a>
<a style="color:white" class="fr loginbtn" href="login.html">登录</a> </div>
</div> <div class="middle">
<div class="wp">
<a href="index.html"><img class="fl" src="{% static 'images/logo.jpg' %}"/></a>
<div class="searchbox fr">
<div class="selectContainer fl">
<span class="selectOption" id="jsSelectOption" data-value="course">
公开课
</span>
<ul class="selectMenu" id="jsSelectMenu">
<li data-value="course">公开课</li>
<li data-value="org">课程机构</li>
<li data-value="teacher">授课老师</li>
</ul>
</div>
<input id="search_keywords" class="fl" type="text" value="" placeholder="请输入搜索内容"/>
<img class="search_btn fr" id="jsSearchBtn" src="{% static 'images/search_btn.png' %}"/>
</div>
</div>
</div> <nav>
<div class="nav">
<div class="wp">
<ul>
<li><a href="index.html">首页</a></li>
<li>
<a href="course-list.html">
公开课<img class="hot" src="{% static 'images/nav_hot.png' %}">
</a>
</li>
<li>
<a href="teachers-list.html">授课教师</a>
</li>
<li class="active"><a href="org-list.html">授课机构</a></li>
</ul>
</div>
</div>
</nav> </div>
</header>
</section>
<!--crumbs start-->
{% block custem_bread %}
<section>
<div class="wp">
<ul class="crumbs">
<li><a href="index.html">首页</a>></li>
<li>课程机构</li>
</ul>
</div>
</section>
{% endblock %}
{% block content %}
<section>
<div class="wp butler_list_box list">
<div class='left'>
<div class="listoptions">
<ul>
<li>
<h2>机构类别</h2>
<div class="cont">
<a href="?city="><span class="active2">全部</span></a> <a href="?ct=pxjg&city="><span class="">培训机构</span></a> <a href="?ct=gx&city="><span class="">高校</span></a> <a href="?ct=gr&city="><span class="">个人</span></a> </div>
</li>
<li>
<h2>所在地区</h2>
<div class="more">更多</div>
<div class="cont">
<a href="?ct="><span class="active2">全部</span></a> <a href="?city=1&ct="><span class="">北京市</span></a> <a href="?city=2&ct="><span class="">上海市</span></a> <a href="?city=3&ct="><span class="">广州市</span></a> <a href="?city=4&ct="><span class="">深圳市</span></a> <a href="?city=5&ct="><span class="">天津市</span></a> </div>
</li>
</ul>
</div>
<div class="all">共<span class="key">15</span>家</div>
<div class="butler_list company list">
<div class="layout">
<div class="head">
<ul class="tab_header">
<li class="active"><a href="?ct=&city=">全部</a></li>
<li class=""><a href="?sort=students&ct=&city=">学习人数 ↓</a></li>
<li class=""><a href="?sort=courses&ct=&city=">课程数 ↓</a></li>
</ul>
</div> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="" height="" class="scrollLoading"
data-url="../media/org/2016/11/imooc.png"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>慕课网</h1>
<div class="pic fl"> <img src="../images/authentication.png"/> <img src="../images/gold.png"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id=""><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="" height="" class="scrollLoading"
data-url="../media/org/2016/11/bjdx.jpg"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>北京大学</h1>
<div class="pic fl"> <img src="../images/authentication.png"/> <img src="../images/gold.png"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id=""><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="" height="" class="scrollLoading"
data-url="../media/org/2016/11/qhdx-logo.png"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>清华大学</h1>
<div class="pic fl"> <img src="../images/authentication.png"/> <img src="../images/gold.png"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id=""><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="" height="" class="scrollLoading"
data-url="../media/org/2016/11/njdx.jpg"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>南京大学</h1>
<div class="pic fl"> <img src="../images/authentication.png"/> <img src="../images/gold.png"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id=""><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="" height="" class="scrollLoading"
data-url="../media/org/2016/11/imooc_klgAUn5.png"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>慕课网2</h1>
<div class="pic fl"> <img src="../images/authentication.png"/> <img src="../images/gold.png"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id=""><br/>联系<br/>服务</div>
</dl> </div>
<div class="pageturn">
<ul class="pagelist"> <li class="active"><a href="?page=1">1</a></li> <li><a href="?page=2" class="page">2</a></li> <li><a href="?page=3" class="page">3</a></li> <li class="long"><a href="?page=2">下一页</a></li> </ul>
</div>
</div>
</div>
<div class="right companyright">
<div class="head">我要学习</div>
<form class="rightform" id="jsStayForm">
<div>
<img src="{% static 'images/rightform1.png' %}"/>
<input type="text" name="name" id="companyName" placeholder="名字" maxlength=""/>
</div>
<div>
<img src="{% static 'images/rightform2.png' %}"/>
<input type="text" name="mobile" id="companyMobile" placeholder="联系电话"/>
</div>
<div>
<img src="{% static 'images/rightform3.png' %}"/>
<input type="text" name="course_name" id="companyAddress" placeholder="课程名" maxlength=""/>
</div>
<p class="error company-tips" id="jsCompanyTips"></p>
<input class="btn" type="text" id="jsStayBtn" value="立即咨询 >"/>
</form>
</div> <div class="right companyrank layout">
<div class="head">授课机构排名</div> <dl class="des">
<dt class="num fl">1</dt>
<dd>
<a href="/company/2/"><h1>慕课网</h1></a>
<p>北京市</p>
</dd>
</dl> <dl class="des">
<dt class="num fl">2</dt>
<dd>
<a href="/company/2/"><h1>慕课网2</h1></a>
<p>深圳市</p>
</dd>
</dl> <dl class="des">
<dt class="num fl">3</dt>
<dd>
<a href="/company/2/"><h1>北京大学</h1></a>
<p>北京市</p>
</dd>
</dl> </div>
</div>
</section>
{% endblock %}
<footer>
<div class="footer">
<div class="wp">
<ul class="cont">
<li class="logo"><a href=""><img src="../images/footlogo.png"/></a></li>
<li class="code"><img src="../images/code.jpg"/>
<p class="center">扫描关注微信</p></li>
<li class="third"><img class="fl" src="../images/tell.png"/>
<p class="tell">33333333</p>
<p class="time">周一至周日 9:00-18:00</p></li>
</ul> </div>
<p class="line"></p>
<div class="wp clear">
<span class="fl">? 2016 www.projectsedu.com 慕学在线-在线学习交流平台 保留所有权利</span>
<span class="fr">copyright ? 2016 ICP备案证书号:蜀ICP备xxxxx号-1</span>
</div>
</div>
</footer> <section>
<ul class="sidebar">
<li class="qq">
<a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=2023525077&site=qq&menu=yes"></a>
</li>
<li class="totop"></li>
</ul>
</section>
<script src="{% static 'js/selectUi.js' %}" type='text/javascript'></script>
<script src="{% static 'js/deco-common.js' %}" type='text/javascript'></script>
<script type="text/javascript" src="{% static 'js/plugins/laydate/laydate.js' %}"></script>
<script src="{% static 'js/plugins/layer/layer.js' %}"></script>
<script src="{% static 'js/plugins/queryCity/js/public.js' %}" type="text/javascript"></script>
<script src="{% static 'js/unslider.js' %}" type="text/javascript"></script>
<script src="{% static 'js/plugins/jquery.scrollLoading.js' %}" type="text/javascript"></script>
<script src="{% static 'js/deco-common.js' %}" type="text/javascript"></script> <script>
$(function () {
$(document).ready(function () {
$('#jsStayBtn').on('click', function () {
$.ajax({
cache: false,
type: "POST",
url: "/org/add_ask/",
data: $('#jsStayForm').serialize(),
async: true,
success: function (data) {
if (data.status == 'success') {
$('#jsStayForm')[0].reset();
alert("提交成功")
} else if (data.status == 'fail') {
$('#jsCompanyTips').html(data.msg)
}
},
});
});
});
}) </script> </body>
</html>
7-2 Django templates模板继承2
7.2.1 课程列表页的模板虽然继承了base.html,但是依然要引入{% load staticfiles %}
org-list.html
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}课程机构列表-慕学在线网首页{% endblock %}
{% block custem_bread %}
<section>
<div class="wp">
<ul class="crumbs">
<li><a href="index.html">首页</a>></li>
<li>课程机构</li>
</ul>
</div>
</section>
{% endblock %}
{% block content %}
<section>
<div class="wp butler_list_box list">
<div class='left'>
<div class="listoptions">
<ul>
<li>
<h2>机构类别</h2>
<div class="cont">
<a href="?city="><span class="active2">全部</span></a> <a href="?ct=pxjg&city="><span class="">培训机构</span></a> <a href="?ct=gx&city="><span class="">高校</span></a> <a href="?ct=gr&city="><span class="">个人</span></a> </div>
</li>
<li>
<h2>所在地区</h2>
<div class="more">更多</div>
<div class="cont">
<a href="?ct="><span class="active2">全部</span></a> <a href="?city=1&ct="><span class="">北京市</span></a> <a href="?city=2&ct="><span class="">上海市</span></a> <a href="?city=3&ct="><span class="">广州市</span></a> <a href="?city=4&ct="><span class="">深圳市</span></a> <a href="?city=5&ct="><span class="">天津市</span></a> </div>
</li>
</ul>
</div>
<div class="all">共<span class="key">15</span>家</div>
<div class="butler_list company list">
<div class="layout">
<div class="head">
<ul class="tab_header">
<li class="active"><a href="?ct=&city=">全部</a></li>
<li class=""><a href="?sort=students&ct=&city=">学习人数 ↓</a></li>
<li class=""><a href="?sort=courses&ct=&city=">课程数 ↓</a></li>
</ul>
</div> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="200" height="120" class="scrollLoading"
data-url="{% static 'media/org/2016/11/imooc.png' %}"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>慕课网</h1>
<div class="pic fl"> <img src="{% static 'images/authentication.png' %}"/> <img src="{% static 'images/gold.png' %}"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id="22"><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="200" height="120" class="scrollLoading"
data-url="{% static 'media/org/2016/11/bjdx.jpg' %}"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>北京大学</h1>
<div class="pic fl"> <img src="{% static 'images/authentication.png' %}"/> <img src="{% static 'images/gold.png' %}"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id="22"><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="200" height="120" class="scrollLoading"
data-url="{% static 'media/org/2016/11/qhdx-logo.png' %}"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>清华大学</h1>
<div class="pic fl"> <img src="{% static 'images/authentication.png' %}"/> <img src="{% static 'images/gold.png' %}"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id="22"><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="200" height="120" class="scrollLoading"
data-url="{% static 'media/org/2016/11/njdx.jpg' %}"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>南京大学</h1>
<div class="pic fl"> <img src="{% static 'images/authentication.png' %}"/> <img src="{% static 'images/gold.png' %}"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id="22"><br/>联系<br/>服务</div>
</dl> <dl class="des difdes">
<dt>
<a href="org-detail-homepage.html">
<img width="200" height="120" class="scrollLoading"
data-url="{% static 'media/org/2016/11/imooc_klgAUn5.png' %}"/>
</a>
</dt>
<dd>
<div class="clearfix">
<a href="org-detail-homepage.html">
<h1>慕课网2</h1>
<div class="pic fl"> <img src="{% static 'images/authentication.png' %}"/> <img src="{% static 'images/gold.png' %}"/> </div>
</a>
</div>
<ul class="cont">
<li class="first"><p class="pic9">课程数:<span>1</span></p>
<p class="c7">学习人数:<span>1000</span></p></li>
<li class="c8" style="padding-left:18px;">北京市海淀区中关村北大街</li>
<li class="pic10" style="padding-left:18px;">经典课程: <a href="/diary/19/">c语言基础入门</a> <a href="/diary/16/">数据库基础</a> </li>
</ul>
</dd>
<div class="buy start_groupbuy jsShowPerfect2" data-id="22"><br/>联系<br/>服务</div>
</dl> </div>
<div class="pageturn">
<ul class="pagelist"> <li class="active"><a href="?page=1">1</a></li> <li><a href="?page=2" class="page">2</a></li> <li><a href="?page=3" class="page">3</a></li> <li class="long"><a href="?page=2">下一页</a></li> </ul>
</div>
</div>
</div>
<div class="right companyright">
<div class="head">我要学习</div>
<form class="rightform" id="jsStayForm">
<div>
<img src="{% static 'images/rightform1.png' %}"/>
<input type="text" name="name" id="companyName" placeholder="名字" maxlength="25"/>
</div>
<div>
<img src="{% static 'images/rightform2.png' %}"/>
<input type="text" name="mobile" id="companyMobile" placeholder="联系电话"/>
</div>
<div>
<img src="{% static 'images/rightform3.png' %}"/>
<input type="text" name="course_name" id="companyAddress" placeholder="课程名" maxlength="50"/>
</div>
<p class="error company-tips" id="jsCompanyTips"></p>
<input class="btn" type="text" id="jsStayBtn" value="立即咨询 >"/>
</form>
</div> <div class="right companyrank layout">
<div class="head">授课机构排名</div> <dl class="des">
<dt class="num fl">1</dt>
<dd>
<a href="/company/2/"><h1>慕课网</h1></a>
<p>北京市</p>
</dd>
</dl> <dl class="des">
<dt class="num fl">2</dt>
<dd>
<a href="/company/2/"><h1>慕课网2</h1></a>
<p>深圳市</p>
</dd>
</dl> <dl class="des">
<dt class="num fl">3</dt>
<dd>
<a href="/company/2/"><h1>北京大学</h1></a>
<p>北京市</p>
</dd>
</dl> </div>
</div>
</section>
{% endblock %}
7-3 课程机构列表页数据展示1
7.3.1 https://github.com/jamespacileo/django-pure-pagination 分页库的使用;
views.py;
# _*_ coding:utf-8 _*_
from django.shortcuts import render
from django.views.generic import View from .models import CourseOrg, CityDict
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger # Create your views here.
class OrgView(View):
"""
课程机构列表功能
""" def get(self, request):
# 课程机构
all_orgs = CourseOrg.objects.all()
org_nums = all_orgs.count()
# 城市
all_citys = CityDict.objects.all()
# 对课程机构进行分页;
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1 p = Paginator(all_orgs, 2, request=request) orgs = p.page(page) return render(request, "org-list.html", {
"all_orgs": orgs,
"all_citys": all_citys,
"org_nums": org_nums,
})
org-list.html
</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.querystring }}">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}" class="page">{{ 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></li>
{% endif %}
</ul>
</div>
7-4 课程机构列表数据展示2
7.4.1 数据要展示在templates中;
7-5 列表分页功能
7-6 列表筛选功能
7-7 modelform提交我要学习咨询1
7-8 modelform提交我要学习咨询2
7-9 机构详情展示-1
7-10 结构详情展示-2
7-11 机构详情展示-3
7-12 课程机构收藏功能
第 8 章 课程功能展示
8-1 课程列表
8.1.1 课程列表页的展示;
8.1.2 分页功能的开发;
8.1.3 推荐课程的开发;
8-2 课程详情页1
8.2.1 课程详情页1
8-3 课程详情2
8.3.1 课程详情2
8-4 课程章节信息1
8.4.1 课程章节信息展示
8-5 课程章节信息2
8-6 课程评论功能
8.6.1 课程的评论功能开发;
8-7 相关课程推荐
8-8 视频播放页面
第 9 章 课程讲师功能实现
9-1 讲师列表页
9-2 讲师详情页1
9-3 讲师详情页2
第 10 章 个人中心和全局搜索功能实现
10-1 配置全局导航
10-2 全局搜索功能开发
10-3 个人信息展示
10-4 修改密码和修改头像1
10-5 修改密码和修改头像2
10-6 修改邮箱和用户信息1
10-7 修改邮箱和用户信息2
10-8 我的课程
10-9 我的收藏功能1
10-10 我的收藏功能2
10-11 我的消息
第 11 章 首页、全局功能细节和404以及500页面配置
11-1 登出和点击数以及收藏数完善
11-2 首页功能开发1
11-3 首页功能开发2
11-4 404和500页面配置
第 12 章 常见Web攻击即防范
12-1 SQL注入攻击与防范
12-2 XSS攻击原理及防范
12-3 CSRF攻击与防范
第 13 章 xadmin的进阶开发
13-1 Userprofile注册以及Django的权限管理1
13-2 Userprofile注册以及Django的权限管理2
13-3 model_ico,只读子字段、默认排序设置
13-4 自定义列表返回数据,同一个model注册两个管理器
13-5 xadmin其他常见功能的使用
13-6 xadmin继承富文本ueditor1
13-7 xadmin集成富文本ueditor2
13-8 excel导入插件介绍
第 14 章 把项目部署上线
14-1 Nginx、MySQL、Virtualenv的安装和配置
- apt-get install nginx
- apt-get install mysql-server
- 修改MySQL支持远程连接;
- 在Ubuntu18.04LTS的Linux发行版上安装virtualenv 和virtualenvwrapper
- .bashrc文件中配置环境变量,如下:
- source .bashrc使得配置立即生效;
export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh
14-2 uwsgi安装和启动、Nginx的虚拟主机配置
14-3 uwsgi配置文件方式启动一级代码更新后的重启
第 15 章 课程总结
15-1 课程总结
第 16 章 快速升级到Python3.6 + Django1.11
16-1 Python3.6 虚拟开发环境的搭建与开发包的安装
- 创建虚拟环境,执行Python的版本;
- mysqlcient替代python-mysql;
- excel导出相关包;
16-2 修改代码适配Python3.6和Django1.11
- 配置虚拟环境解释器;
- xadmin&DjangoUeditor使用github资源;
第 17 章 快速升级到Python3.6 + Django2.0
17-1 快速升级到Python3.6 + Django2.0
django2.0开始只支持python3, 所以升级前确保之前是用django1.11和python3.6开发的,代码可以在相应分支获取 1. 安装依赖包
新装
pip install requests
重装
django-crispy-forms
django-formtools
django-import-export
django-simple-captcha
django-pure-pagination
2. 拷贝django2分支下的xadmin和djangoueditor源码 3. 所有model的外键需要加上on_delete的行为 改为 on_delete=models.CASCADE 4. from django.core.urlresolvers import reverse 全部改为 from django.urls import reverse 5. url中关于include的地方全部改为 url(r'^course/', include(('courses.urls','courses'), namespace="course"))的模式 6. 说明一下 urls.py中url(r'^captcha/', include('captcha.urls')), 一定不能加namespace也不能用上面的模式,保持原来模式就行了 7. 将settings中的MIDDLEWARE_CLASSES 改为 MIDDLEWARE并删除'django.contrib.auth.middleware.SessionAuthenticationMiddleware' 这一行 8. 课程中关于request.user.is_authenticated()中的地方要改为request.user.is_authenticated