Django开发实战

Django开发实战

第二章 Ubuntu下开发环境的搭建

virtualenv安装和配置

安装virtualenv

liang@l:~$ pip install virtualenv

创建一个虚拟环境

liang@l:~$ virtualenv testvir
New python executable in /home/liang/testvir/bin/python
Installing setuptools, pip, wheel...done.

进入该虚拟环境、退出

liang@l:~/testvir$ cd scripts
liang@l:~/testvir$ cd bin
liang@l:~/testvir/bin$ source activate、
(testvir) liang@l:~/testvir/bin$ deactivate

安装virtualenvwrapper并使用

liang@l:~$ sudo pip install virtualenvwrapper 

在用户根目录下(即/home/[username])有文件.bashrc,到该文件的末尾处,屏蔽 if~fi 间的内容,在最后添加下面内容:

if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then
    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
fi
Django开发实战_第1张图片
image

保存后退出。 执行命令:

liang@l:~$ source .bashrc

MySQL的安装和使用

安装MySQL

sudo apt-get install mysql-server
sudo apt-get install mysql-client
sudo apt-get install libmysqlclient-dev

测试MySQL

sudo netstat -tap | grep mysql

修改MySQL密码

  1. 打开/etc/mysql/debian.cnf文件,在这个文件中有系统默认给我们分配的用户名和密码,通过这个密码就可以直接对mysql进行操作了。但是一般这个密码都比较怪,很长很长。

  2. 当进入mysql之后修改mysql的密码:这个方法比较好,具体的操作如下用命令:

mysql> set global validate_password_policy=0;
mysql> set password for 'root'@'localhost' = password('123ooo456');

当修改之后就可应正常对mysql进行操作了。

登录MySQL

liang@l:~$ mysql -u root -p
Enter password:

第三章 Django基础知识回顾

1、Django目录介绍

创建一个新的APP Tools>Run manage.py Task

manage.py@djangostart > startapp message

分别创建static文件夹用于存放静态文件,log文件夹用于存放日志文件,media文件夹用于存放用户上传文件,template文件夹用于存放HTML文件

2、配置表单页面

编辑settings文件数据库内容

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':"testdjango",
        'USER':"root",
        'PASSWORD':"123ooo456",
        'HOST':"127.0.0.1"
    }
}#数据库连接
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users'#新创建的APP需要注册
]
AUTH_USER_MODEL = "users.UserProfile"#修改默认用户画像

安装MySQL的Python工具

liang@l:~/Downloads/navicat120_mysql_cs_x64$ pip install mysql-python

打开manage.py Task,创建数据库表

manage.py@djangostart > makemigratioon
manage.py@djangostart > migrate

第四章 需求分析和Model设计

1、创建Django-APP

创建MxOnline Django项目

扩展Django默认表达到自定义userprofile表的目的

创建users APP,==所有网站的设计应该都从users开始设计==

用makemigration和migrate命令创建默认数据库,自动创建的用户表为==auth_user==

编写models.py文件,==注意一定要写utf-8格式==

#_*_ encoding:utf-8 _*_
from __future__ import unicode_literals

from django.db import models
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、

执行过程中出现此问题,需要返回虚拟环境安装==Pillow库==

ERRORS:
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".

运行后提示

ValueError: Dependency on app with no migrations: users

此时要做一下users的migration,打开manage.py

manage.py@MxOnline > makemigrations users
bash -cl "/home/liang/.virtualenvs/mxonline/bin/python2.7 /home/liang/pycharm-2017.2.4/helpers/pycharm/django_manage.py makemigrations users /home/liang/PycharmProjects/MxOnline"
Migrations for 'users':

manage.py@MxOnline > migrate users
bash -cl "/home/liang/.virtualenvs/mxonline/bin/python2.7 /home/liang/pycharm-2017.2.4/helpers/pycharm/django_manage.py migrate users /home/liang/PycharmProjects/MxOnline"
Operations to perform:
  Apply all migrations: users
Running migrations:
  Rendering model states... DONE
  Applying users.0001_initial... OK
The following content types are stale and need to be deleted:

    auth | user

Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
If you're unsure, answer 'no'.

    Type 'yes' to continue, or 'no' to cancel:  yes

Process finished with exit code 0

再次打开数据库的users_profile表,显示创建成功

makemigrations只是生成一个比对记录,migrate才是把更改应用到数据库当中。

user models.py设计

User models.py 和Courses models.py存在循环引用

解决循环import最常用的方法是分层设计:

  1. django app设计
  2. users models.py编写
  3. courses models.py编写
  4. organization models.py编写
  5. operaion models.py编写(最上层)

users models.py

  1. 自定义usersprofile覆盖默认user表
  2. EmailVerifyRecord-邮箱验证码(保存到数据库中)
  3. PageBanner-轮播图

编辑Django文件时,应注意遵循PEP8规范的==导入顺序==

#_*_ encoding:utf-8 _*_
#第一个区域,放Python自带的包
from __future__ import unicode_literals
from datetime import datetime

#第二个区域,放第三方的包
from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models her第三个区域,自己定义的model

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

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)
    #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"轮播图",max_length=100)
    #image在数据库当中存取的是图片的路径地址
    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

形成以下结构图:

courses models.py

设计内容:

  1. Course - 课程基本信息
  2. Lesson - 章节信息
  3. Video - 视频
  4. CourseResource - 课程资源

课程存在多层嵌套关系

graph LR
课程-->章节
章节-->视频

代码如下:

#_*_ 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",u"初级"),("zj",u"中级"),("gj",u"高级")),max_length=2)
    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"封面数", max_length=100)
    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, 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 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

organization models.py 设计

课程机构结构如下:

  1. CourseOrg - 课程机构基本信息
  2. Teacher - 教师基本信息
  3. CityDictionary - 城市信息
#_*_ 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.DateTimeField(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_num = 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"封面数", max_length=100)
    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_year = 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_num = 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

operation models.py

设计结构:

  1. UserAsk - 用户咨询
  2. CourseComments - 用户评论
  3. UserFavorite - 用户收藏
  4. UserMessage - 用户消息
  5. UserCourse - 用户学习的课程
    设计代码如下:
#_*_ 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,u"课程"),(2,u"课程机构"),(3,u"讲师")),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(max_length=500, 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

数据库生成以及apps目录建立

打开manage.py task

manage.py@MxOnline > makemigrations
bash -cl "/home/liang/.virtualenvs/mxonline/bin/python2.7 /home/liang/pycharm-2017.2.4/helpers/pycharm/django_manage.py makemigrations /home/liang/PycharmProjects/MxOnline"
Migrations for 'courses':
  0001_initial.py:
    - Create model Course
    - Create model CourseResource
    - Create model Lesson
    - Create model Video
Migrations for 'operation':
  0001_initial.py:
    - Create model CourseComments
    - Create model UserAsk
    - Create model UserCourse
    - Create model UserFavorite
    - Create model UserMessage
Migrations for 'users':
  0002_banner_emailverifyrecord.py:
    - Create model Banner
    - Create model EmailVerifyRecord
Migrations for 'organization':
  0001_initial.py:
    - Create model CityDict
    - Create model CourseOrg
    - Create model Teacher
Following files were affected 
 /home/liang/PycharmProjects/MxOnline/organization/migrations/0001_initial.py
/home/liang/PycharmProjects/MxOnline/courses/migrations/0001_initial.py
/home/liang/PycharmProjects/MxOnline/operation/migrations/0001_initial.py
/home/liang/PycharmProjects/MxOnline/users/migrations/0002_banner_emailverifyrecord.py
Process finished with exit code 0

此时每个app文件夹下会生成migrations文件夹

当app数量过多时,应该把他们单独放入一个文件夹便于管理

然后执行==右击apps文件夹 > Mark Directory as > Sources Root==,这样,在根目录下找不到的表可以在apps目录下继续寻找,但是这样仍然不够,在命令行下运行python manage.py runserver 时,仍然会报错找不到users

liang@l:~/PycharmProjects/MxOnline$ python manage.py runserver
Unhandled exception in thread started by 
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/commands/runserver.py", line 117, in inner_run
    autoreload.raise_last_exception()
  File "/usr/local/lib/python2.7/dist-packages/django/utils/autoreload.py", line 251, in raise_last_exception
    six.reraise(*_exception)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/usr/local/lib/python2.7/dist-packages/django/apps/registry.py", line 85, in populate
    app_config = AppConfig.create(entry)
  File "/usr/local/lib/python2.7/dist-packages/django/apps/config.py", line 94, in create
    module = import_module(entry)
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
ImportError: No module named users

此时要编辑MxOnline/settings.py文件,将根目录注册到settings文件中

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'))

此时,用PyCharm Debug该项目,正常

停止运行,在命令行中运行该项目,正常

(mxonline) liang@l:~/PycharmProjects/MxOnline$ python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

November 28, 2017 - 14:25:53
Django version 1.9, using settings 'MxOnline.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

第五章 通过xadmin快速搭建后台管理系统

1、Django amdin介绍

后台管理系统的特点:

  • 权限管理
  • 少前段样式
  • 快速开发

xadmin是Django中的一个杀手级后台管理系统
xadmin是Django自带的,在新建项目时就已经存在的。打开settings.py文件就可以看到Installed_apps中有django.contrb.admin一项。

Installed_apps:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
    'courses',
    'organization',
    'operation'
]

运行项目时,输入http://127.0.0.1:8000/admin,就可以访问默认的后台管理系统

此时回到pycharm中运行manage.py,创建超级用户。

manage.py@MxOnline > createsuperuser
bash -cl "/home/liang/.virtualenvs/mxonline/bin/python2.7 /home/liang/pycharm-2017.2.4/helpers/pycharm/django_manage.py createsuperuser /home/liang/PycharmProjects/MxOnline"
Username:  liang
Email address:  [email protected]
Warning: Password input may be echoed.
Password:  admin123
Warning: Password input may be echoed.
Password (again):  admin123
Superuser created successfully.

Process finished with exit code 0

再次运行项目,登录http://127.0.0.1:8000/admin/

显示登陆成功,界面语言为英语,可在settings.py文件中更改语言。

LANGUAGE_CODE = 'zh-hans'

需要注意的是,在Django1.7版本之前,中文的编码是叫做"zh-CN",1.8版本之后为"zh-hans"。
时区改为上海

TIME_ZONE = 'UTC'

将Django的时间由国际时间改为本地时间,USE_TZ改为False:

USE_TZ = True

Django为我们自动注册了组,这个组就对应后台数据库auth_group,可以将任何的models都注册进去,然后对这些表任意的增删改查。

users app目录下有admin.py文件,它就是用来注册后台管理系统的,在startapp后自动生成好的。

在此文件中,将users.UserProfile注册进来。

#_*_ encoding:utf-8 _*_
from django.contrib import admin

# Register your models here.

from .models import UserProfile #当前目录下的models直接用.就可以

class UserProfileAdmin(admin.ModelAdmin):
    pass

admin.site.register(UserProfile, UserProfileAdmin)

此时,重新访问后台系统,多出了用户表,此时点击增加即可增加记录

2、xadmin的安装

xadmin是基于Django自带的admin,比admin更强大的一套后台管理系统,本项目都是采用xadmin后天管理系统完成的。

通过pip命令安装:

liang@l:~$ workon mxonline
(mxonline) liang@l:~$ pip install xadmin
Collecting xadmin
  Downloading xadmin-0.6.1.tar.gz (1.0MB)
    100% |████████████████████████████████| 1.0MB 192kB/s 
Requirement already satisfied: setuptools in ./.virtualenvs/mxonline/lib/python2.7/site-packages (from xadmin)
Requirement already satisfied: django<2.0.0,>=1.9.0 in ./.virtualenvs/mxonline/lib/python2.7/site-packages (from xadmin)
Collecting django-crispy-forms>=1.6.0 (from xadmin)
  Downloading django_crispy_forms-1.7.0-py2.py3-none-any.whl (104kB)
    100% |████████████████████████████████| 112kB 224kB/s 
Collecting django-formtools>=1.0 (from xadmin)
  Downloading django_formtools-2.1-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 192kB/s 
Collecting httplib2==0.9.2 (from xadmin)
  Downloading httplib2-0.9.2.zip (210kB)
    100% |████████████████████████████████| 215kB 208kB/s 
Building wheels for collected packages: xadmin, httplib2
  Running setup.py bdist_wheel for xadmin ... done
  Stored in directory: /home/liang/.cache/pip/wheels/cb/fa/55/706b155c6a746d623d82ad38b4d31e8f2f58729f710d84d102
  Running setup.py bdist_wheel for httplib2 ... done
  Stored in directory: /home/liang/.cache/pip/wheels/c7/67/60/e0be8ccfc1e08f8ff1f50d99ea5378e204580ea77b0169fb55
Successfully built xadmin httplib2
Installing collected packages: django-crispy-forms, django-formtools, httplib2, xadmin
Successfully installed django-crispy-forms-1.7.0 django-formtools-2.1 httplib2-0.9.2 xadmin-0.6.1

在settings.py文件中,注册xadmin和crispy-forms两个app

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' #注意是下划线
]

把默认的admin指向xadmin的URL,这样就完成了xadmin的替换。

替换前:

from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

替换后:

from django.conf.urls import url
from django.contrib import admin
import xadmin

urlpatterns = [
    url(r'^xadmin/', xadmin.site.urls),
]

此时运行项目,访问 http://127.0.0.1:8000/xadmin/ ,提示"Table 'mxonline.xadmin_usersettings' doesn't exist"

因为xadmin存在很多默认的表,在xadmin安装完成之后,还要把xadmin的表给同步过来

用miagrations和migrate命令更新数据库

manage.py@MxOnline > migrate
bash -cl "/home/liang/.virtualenvs/mxonline/bin/python2.7 /home/liang/pycharm-2017.2.4/helpers/pycharm/django_manage.py migrate /home/liang/PycharmProjects/MxOnline"
Operations to perform:
  Apply all migrations: xadmin, users, sessions, admin, auth, courses, contenttypes, organization, operation
Running migrations:
  Rendering model states... DONE
  Applying xadmin.0001_initial... OK

Process finished with exit code 0

此时数据库中将会多出三个表

此时再刷新页面,出现一个全新的后台界面

进入xadmin官网,可以看到xadmin的各种特性

xadmin安装的另一种方法:在github上下载xadmin的原码,便于日后修改,另外,很多xadmin的新功能在还没有发布到pypi上面的时候,就可以直接用原码体现它的新特性。

将解压出的xadmin文件夹

拷贝到项目的根目录下

再新建一个extra_app文件夹用于存放第三方app,把xadmin给拖进去,并mark成source root。

==同时修改settings.py文件注册根目录,否则运行manage.py文件时会报错:==

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
sys.path.insert(0,os.path.join(BASE_DIR,'extra_apps'))

由于直接import会优先导入环境中的xadmin包,所以先要将环境中的xadmin卸载掉:

(mxonline) liang@l:~$ pip uninstall xadmin

再参考 https://github.com/sshwsfc/xadmin/blob/master/requirements.txt 网址中,把缺少的依赖包都安装好。

(mxonline) liang@l:~$ pip install future six httplib2

再安装另一个工具

(mxonline) liang@l:~$ pip install django-import-export

再度运行,成功运行。

3、users app的model注册

先对pycharm进行一项设置,可以在新建×.py文件时自动填充模板内容:

在users根目录下新建一个adminx.py文件,编写以将邮箱验证码注册到xadmin管理系统中:

import xadmin

from .models import EmailVerifyRecord

class EmailVeriflyRecordAdmin(object):
    pass

xadmin.site.register(EmailVerifyRecord, EmailVeriflyRecordAdmin)

再次访问xadmin界面:

该项注册成功

添加一条项目时,会报错ProgrammingError at /xadmin/users/emailverifyrecord/add/,(1146, "Table 'mxonline.xadmin_log' doesn't exist"),这是因为数据库还使用上个版本的xadmin生成的数据表,此时要重新migrations xadmin:

manage.py@MxOnline > migrate xadmin
bash -cl "/home/liang/.virtualenvs/mxonline/bin/python2.7 /home/liang/pycharm-2017.2.4/helpers/pycharm/django_manage.py migrate xadmin /home/liang/PycharmProjects/MxOnline"
Operations to perform:
  Apply all migrations: xadmin
Running migrations:
  Rendering model states... DONE
  Applying xadmin.0002_log... OK
  Applying xadmin.0003_auto_20160715_0100... OK

Process finished with exit code 0

在models.py文件中,加入最后一个重载的Unicode方法,可以决定邮箱验证码列表中是如何显示的。

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(verbose_name=u"验证码类型",choices=(("register",u"注册"),("forget",u"找回密码")),max_length=10)
    send_time = models.DateTimeField(verbose_name=u"发送时间",default=datetime.now)
    #now加括号的话会生成实际编译的时间,不加括号的话生成类实例化的时间

    class Meta:
        verbose_name = u"邮箱验证码"
        verbose_name_plural = verbose_name

    def __unicode__(self):
        return '{0}({1})'.format(self.code, self.email) #列表的显示内容

在xadmin.py文件中定义需要展示哪些列:

class EmailVeriflyRecordAdmin(object):
    list_display = ['code','email','send_type','send_time']

展示界面即发生改变:

在增加一个搜索框:

class EmailVeriflyRecordAdmin(object):
    list_display = ['code','email','send_type','send_time']
    search_fields = ['code','email','send_type']

原界面就会发生了改变:

变得可以搜索:

再增加一个筛选字段:

class EmailVeriflyRecordAdmin(object):
    list_display = ['code','email','send_type','send_time']
    search_fields = ['code','email','send_type']
    list_filter = ['code','email','send_type','send_time']

会出现一个筛选工具:

用同样的方法,注册Banner,新建类并关联:

class BannerAadmin(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(Banner, BannerAadmin)

4、剩余apps models注册

依据同样的方法编辑如下文件:

courses/adminx.py文件:

# -*-coding:utf-8 -*-
__author__ = 'liang'
__date__ = '17-12-4 下午9:43'
import xadmin

from .models import Course, Lesson, Video, CourseResource

class CourseAdmin(object):
    list_display = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students']
    search_fields = ['name', 'desc', 'detail', 'degree', 'students']
    list_filter = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students']

class LessonAdmin(object):
    list_display = ['course', 'name', 'add_time']
    search_fields = ['course', 'name']
    list_filter = ['course__name', 'name', 'add_time'] #外键的name字段

class VideoAdmin(object):
    list_display = ['lesson', 'name', 'add_time']
    search_fields = ['lesson', 'name']
    list_filter = ['lesson', 'name', 'add_time']
    model_icon = 'fa fa-film'

class CourseResourceAdmin(object):
    list_display = ['course', 'name', 'download', 'add_time']
    search_fields = ['course', 'name', 'download']
    list_filter = ['course', 'name', 'download', 'add_time']


xadmin.site.register(Course, CourseAdmin)
xadmin.site.register(Lesson, LessonAdmin)
xadmin.site.register(Video, VideoAdmin)
xadmin.site.register(CourseResource, CourseResourceAdmin)

organization/adminx.py文件:

# -*-coding:utf-8 -*-
__author__ = 'liang'
__date__ = '17-12-4 下午10:08'
import xadmin

from .models import CityDict, CourseOrg, Teacher

class CityDictAdmin(object):
    list_display = ['name', 'desc', 'add_time']
    search_fields = ['name', 'desc']
    list_filter = ['name', 'desc', 'add_time']


class CourseOrgAdmin(object):
    list_display = ['name', 'desc', 'click_nums', 'fav_nums']
    search_fields = ['name', 'desc', 'click_nums', 'fav_nums']
    list_filter = ['name', 'desc', 'click_nums', 'fav_nums']
    relfield_style = 'fk-ajax'
    style_fields = {"desc":"ueditor"}


class TeacherAdmin(object):
    list_display = ['org', 'name', 'work_years', 'work_company']
    search_fields = ['org', 'name', 'work_years', 'work_company']
    list_filter = ['org', 'name', 'work_years', 'work_company']


xadmin.site.register(CityDict, CityDictAdmin)
xadmin.site.register(CourseOrg, CourseOrgAdmin)
xadmin.site.register(Teacher, TeacherAdmin)

operation/adminx.py文件:

# -*-coding:utf-8 -*-
__author__ = 'liang'
__date__ = '17-12-4 下午10:08'
import xadmin

from .models import CityDict, CourseOrg, Teacher

class CityDictAdmin(object):
    list_display = ['name', 'desc', 'add_time']
    search_fields = ['name', 'desc']
    list_filter = ['name', 'desc', 'add_time']


class CourseOrgAdmin(object):
    list_display = ['name', 'desc', 'click_nums', 'fav_nums']
    search_fields = ['name', 'desc', 'click_nums', 'fav_nums']
    list_filter = ['name', 'desc', 'click_nums', 'fav_nums']
    relfield_style = 'fk-ajax'
    style_fields = {"desc":"ueditor"}


class TeacherAdmin(object):
    list_display = ['org', 'name', 'work_years', 'work_company']
    search_fields = ['org', 'name', 'work_years', 'work_company']
    list_filter = ['org', 'name', 'work_years', 'work_company']


xadmin.site.register(CityDict, CityDictAdmin)
xadmin.site.register(CourseOrg, CourseOrgAdmin)
xadmin.site.register(Teacher, TeacherAdmin)

需要注意的是,作为外键,被其他类访问时,不会显示类的内容,只会显示成object,此时,可以用重载unicode方法,使返回类的某个字段名即可:

    def __unicode__(self):
        return self.name

同样,引用时,==利用双下划线引用类的某个字段==,如:

    list_filter = ['course__name', 'name', 'add_time'] #外键的name字段

5、xadmin全局配置

xadmin中包含更换主题的功能,首先,激活xadmin的主题功能,将如下代码加入users/adminx.py文件中:

from xadmin import views


class BaseSetting(object):
    enable_themes = True #主体功能
    use_bootwatch = True

xadmin.site.register(views.BaseAdminView, BaseSetting)

此时,右上角增加主题按钮:

因为后期主题下载网站请求模式变化了,参考 http://blog.csdn.net/dimples_54/article/details/77963593 文章进行修改,运行后可以切换主题

再在users/adminx.py文件中加入:

class GlobalSettings(object):
    site_title = "慕学后台管理系统"
    site_footer = "慕学在线网"
    
xadmin.site.register(views.CommAdminView, GlobalSettings)

网站标题发生了改变:

脚注也发生了改变:

再在GlobalSettings类中加入一个参数:

class GlobalSettings(object):
    site_title = "慕学后台管理系统"
    site_footer = "慕学在线网"
    menu_style = "accordion"

此时左侧的apps都默认收起,点开展示:

为了让列表里的apps也显示中文名,修改apps/users/apps.py文件

# -*-coding:utf-8 -*-
from django.apps import AppConfig


class OperationConfig(AppConfig):
    name = 'operation'
    verbose_name = u"用户操作"

并在apps/users/__ init __.py文件:

default_app_config = "users.apps.UsersConfig"

同理,修改apps/courses/apps.py

#_*_ encoding:utf-8 _*_
from django.apps import AppConfig


class CoursesConfig(AppConfig):
    name = 'courses'
    verbose_name = u"课程管理"

并修改apps/courses/__ init __.py文件:

default_app_config = "courses.apps.CoursesConfig"

修改apps/operation/apps.py

# -*-coding:utf-8 -*-
from django.apps import AppConfig


class OperationConfig(AppConfig):
    name = 'operation'
    verbose_name = u"用户操作"

并修改apps/operation/__ init __.py文件:

default_app_config = "operation.apps.OperationConfig"

修改apps/organization/apps.py

#_*_ encoding:utf-8 _*_
from django.apps import AppConfig


class OrganizationConfig(AppConfig):
    name = 'organization'
    verbose_name = u"机构管理"

并修改apps/organization/__ init __.py文件:

default_app_config = "organization.apps.OrganizationConfig"

最终运行结果,apps的名称全部修改为中文了:

至此,全局配置,完成设置了主题、网站标题、网站脚注、对apps的名称做中文修改。

第六章 用户注册功能的实现

1、首页和登录页面的配置

你可能感兴趣的:(Django开发实战)