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
保存后退出。 执行命令:
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密码
打开/etc/mysql/debian.cnf文件,在这个文件中有系统默认给我们分配的用户名和密码,通过这个密码就可以直接对mysql进行操作了。但是一般这个密码都比较怪,很长很长。
当进入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最常用的方法是分层设计:
- django app设计
- users models.py编写
- courses models.py编写
- organization models.py编写
- operaion models.py编写(最上层)
users models.py
- 自定义usersprofile覆盖默认user表
- EmailVerifyRecord-邮箱验证码(保存到数据库中)
- 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
设计内容:
- Course - 课程基本信息
- Lesson - 章节信息
- Video - 视频
- 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 设计
课程机构结构如下:
- CourseOrg - 课程机构基本信息
- Teacher - 教师基本信息
- 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
设计结构:
- UserAsk - 用户咨询
- CourseComments - 用户评论
- UserFavorite - 用户收藏
- UserMessage - 用户消息
- 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的名称做中文修改。