Python升级3.6 强力Django+Xadmin打造在线教育平台

第 1 章 课程介绍

1-1 项目演示和课程介绍;

第 2 章 Windows下搭建开发环境

2-1 Pycharm、Navicat和Python解释器的安装;

 

 

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': '3306',
    }

}

# 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>&nbsp;</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>&nbsp;</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地址申请;

http://apply.projectsedu.com/

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': '3306',
        '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 拷贝静态文件如jscssimagesimg等文件之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=">学习人数 &#8595;</a></li>
                            <li class=""><a href="?sort=courses&ct=&city=">课程数 &#8595;</a></li>
                        </ul>
                    </div>

                    <dl class="des difdes">
                        <dt>
                            <a href="org-detail-homepage.html">
                                <img width="200" height="120" 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="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="../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="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="../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="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="../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="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="../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="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 %}
<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=">学习人数 &#8595;</a></li>
                            <li class=""><a href="?sort=courses&ct=&city=">课程数 &#8595;</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

原文地址:https://www.cnblogs.com/tqtl911/p/9568596.html