Django项目实战

Django app

  • users-用户管理
  • course-课程管理
  • organization-机构和教师管理
  • operation-用户操作管理
C:\Users\jianhu.yong>mkvirtualenv mxonline
New python executable in C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe
Installing setuptools, pip, wheel...done.

(mxonline) C:\Users\jianhu.yong>
(mxonline) C:\Users\jianhu.yong>pip install django==1.9
Collecting django==1.9
Downloading https://files.pythonhosted.org/packages/ea/9b/b5a6360b3dfcd88d4bad70f59da26cbde4bdec395a31bb26dc840e806a50/Django-1.9-py2.py3-none-any.whl (6.6MB)
100% |████████████████████████████████| 6.6MB 79kB/s
Installing collected packages: django
Successfully installed django-1.9

(mxonline) C:\Users\jianhu.yong>cd Downloads
(mxonline) C:\Users\jianhu.yong\Downloads>pip install MySQL_python-1.2.5-cp27-none-win_amd64.whl
Processing c:\users\jianhu.yong\downloads\mysql_python-1.2.5-cp27-none-win_amd64.whl
Installing collected packages: MySQL-python
Successfully installed MySQL-python-1.2.5

upload successful
upload successful
upload successful

数据库配置

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mxonline',
'USER':'root',
'PASSWORD':'root',
'HOST':'127.0.0.1'
}
}

新建数据库

upload successful

生成默认数据表

makemigrations
migtate

userapp model设计

manage.py@MxOnline > startapp users
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" startapp users C:/Users/jianhu.yong/PycharmProjects/MxOnline
Following files were affected
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\tests.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\__init__.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\apps.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\admin.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\models.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\views.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\migrations\__init__.py
Process finished with exit code 0

upload successful
默认的user表不满足我们的需求,因此需要定制user表
自定义userprofile覆盖默认user表

users.model
class UserProfile(AbstractUser):
nick_name = models.CharField(max_length=50, verbose_name=u'昵称', default="")
birday = 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/%m",default=u"image/default.png", max_length=100)

class Meta:
verbose_name = "用户信息"
verbose_name_plural = verbose_name

def __unicode__(self):
return self.username
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users'
]

AUTH_USER_MODEL = "users.UserProfile"

upload successful

(mxonline) C:\Users\jianhu.yong\Downloads>pip install pillow
Collecting pillow
Downloading https://files.pythonhosted.org/packages/48/91/f058672c494e186dc900bb6253e8cbde3307da17aed0a2d1ebcfb80ab766/Pillow-5.2.0-cp27-cp27m-win_amd64.whl (1.5MB)
100% |████████████████████████████████| 1.5MB 2.4MB/s
Installing collected packages: pillow
Successfully installed pillow-5.2.0

upload successful

manage.py@MxOnline > makemigrations users
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" makemigrations users C:/Users/jianhu.yong/PycharmProjects/MxOnline
Migrations for 'users':
0001_initial.py:
- Create model UserProfile
Following files were affected
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\migrations\0001_initial.py
Process finished with exit code 0
manage.py@MxOnline > migrate users
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" migrate users C:/Users/jianhu.yong/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

app设计需要避免循环引用(a调用b,b调用a,最后ab都无法执行)
upload successful
upload successful

EmailVerifyRecord邮箱验证码设计

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() model编译时间生成默认时间
# datetime.now classs实例化时生成的时间

class Meta:
verbose_name = u"邮箱验证码"
verbose_name_plural = verbose_name
```
PageBanner轮播图
``` python


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)
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设计:
新建app

- courses课程基本信息
- lesson 章节信息
- video 视频信息
- courseResouce 课程资源

``` python models.py
# conding:utf8
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"课程详情")
# TextField不限制max_length
defree = models.CharField(choices=(("cj", u"初级"),("zj", u"中级"),("bj", 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.ImageField(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/resourse/%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

manage.py@MxOnline > startapp organization
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" startapp organization C:/Users/jianhu.yong/PycharmProjects/MxOnline
Following files were affected
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\models.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\admin.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\apps.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\views.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\tests.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\migrations\__init__.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\__init__.py
Process finished with exit code 0
  • CourseOrg 课程机构基本信息
  • Teacher 教师基本信息
  • CityDict 城市信息
# coding:utf8
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_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"封面图", 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_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
```

operation app设计

- UserAsk 用户咨询
- CourseComments 用户评论
- UserFavorite 用户收藏
- UserMessage 用户消息
- UserCourse 用户学习的课程


``` python
manage.py@MxOnline > startapp operation
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" startapp operation C:/Users/jianhu.yong/PycharmProjects/MxOnline
Following files were affected
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\migrations\__init__.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\apps.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\views.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\__init__.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\models.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\admin.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\tests.py
Process finished with exit code 0
# coding:utf8
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"用户")
course = models.ForeignKey(Course, 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(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

添加至install apps settings.py

manage.py@MxOnline > makemigrations
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" makemigrations C:/Users/jianhu.yong/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
C:\Users\jianhu.yong\PycharmProjects\MxOnline\organization\migrations\0001_initial.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\users\migrations\0002_banner_emailverifyrecord.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\operation\migrations\0001_initial.py
C:\Users\jianhu.yong\PycharmProjects\MxOnline\courses\migrations\0001_initial.py
Process finished with exit code 0

新建apps包统一管理app

upload successful

upload successful

upload successful

默认打钩,会在导入模块内容之前加入apps.xxx

upload successful
通过设置解决import出错问题

但是python 运行会提示模块找不到错误

settings.py

后台管理系统

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

http://127.0.0.1:8000/admin

创建diango admin后台用户出错
upload successful
upload successful

重新修改下即可!

manage.py@MxOnline > createsuperuser
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" createsuperuser C:/Users/jianhu.yong/PycharmProjects/MxOnline
Username: admin
Email address: test@qq.com
Warning: Password input may be echoed.
Password: admin123
Warning: Password input may be echoed.
Password (again): admin123
Superuser created successfully.

修改django admin修改为中文

settings.py

settings.py
LANGUAGE_CODE = 'zh-hans'

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

#需要改成False,否侧django在数据库中存的时间为UTC国际时间!
USE_TZ = False

xadmin设置

(mxonline) C:\Users\jianhu.yong\PycharmProjects\MxOnline>pip install xadmin
Collecting xadmin
Downloading https://files.pythonhosted.org/packages/1d/e9/2ac160c532d0d462142fa90aa86a0e317295e8d86fa4caf84d04f6e24c49/xadmin-0.6.1.tar.gz (1.0MB)
100% |████████████████████████████████| 1.0MB 19kB/s
Requirement already satisfied: setuptools in c:\users\jianhu.yong\envs\mxonline\lib\site-packages (from xadmin) (39.2.0)
Requirement already satisfied: django<2.0.0,>=1.9.0 in c:\users\jianhu.yong\envs\mxonline\lib\site-packages (from xadmin) (1.9)
Collecting django-crispy-forms>=1.6.0 (from xadmin)
Downloading https://files.pythonhosted.org/packages/9a/05/6bad05742d185ec2fabfa4deab05cafde286eb3f383fba24b3674340aca2/django_crispy_forms-1.7.2-py2.py3-none-any.whl (105kB)
100% |████████████████████████████████| 112kB 14kB/s
Collecting django-formtools>=1.0 (from xadmin)
Downloading https://files.pythonhosted.org/packages/97/3f/b8e04c41c028d5cdad651393abea1f686d846c717d8ab5d5ebe2974f711c/django_formtools-2.1-py2.py3-none-any.whl (132kB)
100% |████████████████████████████████| 133kB 25kB/s
Collecting httplib2==0.9.2 (from xadmin)
Downloading https://files.pythonhosted.org/packages/ff/a9/5751cdf17a70ea89f6dde23ceb1705bfb638fd8cee00f845308bf8d26397/httplib2-0.9.2.tar.gz (205kB)
100% |████████████████████████████████| 215kB 23kB/s
Building wheels for collected packages: xadmin, httplib2
Running setup.py bdist_wheel for xadmin ... done
Stored in directory: C:\Users\jianhu.yong\AppData\Local\pip\Cache\wheels\4f\d7\9a\4699d04c2239f4ad9764de8d236d9df1344574067dd61ab201
Running setup.py bdist_wheel for httplib2 ... done
Stored in directory: C:\Users\jianhu.yong\AppData\Local\pip\Cache\wheels\36\f2\49\5adbf90fba31e02a7784e1147d7f8b6c4af3718739e568c8cb
Successfully built xadmin httplib2
Installing collected packages: django-crispy-forms, django-formtools, httplib2, xadmin
Successfully installed django-crispy-forms-1.7.2 django-formtools-2.1 httplib2-0.9.2 xadmin-0.6.1
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',
]
from django.conf.urls import url
from django.contrib import admin
import xadmin

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

upload successful

manage.py@MxOnline > makemigrations
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" makemigrations C:/Users/jianhu.yong/PycharmProjects/MxOnline
No changes detected

Process finished with exit code 0
manage.py@MxOnline > migrate
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" migrate C:/Users/jianhu.yong/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

http://sshwsfc.github.io/xadmin/

基于源码安装xadmin

  • 可自定义
  • 功能最新 比pypi

https://github.com/sshwsfc/xadmin

upload successful

upload successful

upload successful

upload successful

upload successful

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

upload successful

upload successful

upload successful

pip install future
pip install six
pip install django_import_export
manage.py@MxOnline > makemigrations
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" makemigrations C:/Users/jianhu.yong/PycharmProjects/MxOnline
No changes detected

Process finished with exit code 0
manage.py@MxOnline > migrate
"C:\Program Files\JetBrains\PyCharm 2017.1.2\bin\runnerw.exe" C:\Users\jianhu.yong\Envs\mxonline\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm 2017.1.2\helpers\pycharm\django_manage.py" migrate C:/Users/jianhu.yong/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.0002_log... OK
Applying xadmin.0003_auto_20160715_0100... OK

设置脚本文件模版neirong

upload successful

通过xadmin注册model

upload successful

注册剩余models

xadmin全局配置

from xadmin import  views
from .models import EmailVerifyRecord,Banner

class BaseSetting(object):
enable_themes = True
use_bootswatch = True
xadmin.site.register(views.BaseAdminView, BaseSetting)
class GlobalSettings(object):
site_title = 'MX后台管理系统'
site_footer = 'MX在线网'
xadmin.site.register(views.CommAdminView, GlobalSettings)

upload successful

xadmin主题bug
[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure

xadmin\plugins\themes.py
flag = False
if flag:
h = httplib2.Http()
resp, content = h.request("https://bootswatch.com/api/3.json", 'GET', '',
headers={"Accept": "application/json", "User-Agent": self.request.META['HTTP_USER_AGENT']})
if six.PY3:
content = content.decode()
watch_themes = json.loads(content)['themes']
else:
content = requests.get("https://bootswatch.com/api/3.json")
if six.PY3:
content = content.text.decode()
watch_themes = json.loads(content.text)['themes']

upload successful
修改为中文显示

__init__.py
default_app_config = 'operation.apps.OperationConfig'
apps.py
# coding:utf8
from django.apps import AppConfig


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

首页和登录页的配置

url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
url(r'^login/$', TemplateView.as_view(template_name='login.html'), name='login'),

用户登录配置

urls.py
urlpatterns = [
# url(r'^admin/', admin.site.urls),
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'),
url(r'^login/$', user_login, name='login'),

]
views.py
def user_login(request):
if request.method == 'POST':
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', {})

pass
elif request.method == 'GET':
return render(request, 'login.html', {})
```



自定义auth认证变量
重写authenticate方法

``` python views.py
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from django.contrib.auth.backends import ModelBackend
from .models import UserProfile
from django.db.models import Q
# 完成并集操作获得关系
# 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
settings.py
AUTHENTICATION_BACKENDS = (
'users.views.CustomBackend',
)

views方法基于类,不基于函数书写

views.py
from  django.views.generic.base import View
class LoginView(View):
def get(self, request):
return render(request, 'login.html', {})
def post(self, request):
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':'用户名或密码错误!'})

form实现登入

upload successful

session & cookies自动登录机制

  • cookies 浏览器本地存储方式机制,可以存储很多信息,存储在某个域名之下,存储在本地不安全!
  • session 服务器生成,存储在服务器端,安全,发送给用户,存储在cookies之中!

upload successful
upload successful
upload successful
upload successful

value 用户名密码加密字符串,服务器对session id取出value 并解密,实现自动登录 !

upload successful
注释掉 自动登录就失效了!

用户注册

{% load staticfiles %}

验证码插件

https://github.com/mbi/django-simple-captcha

Install django-simple-captcha via pip: pip install  django-simple-captcha

Add captcha to the INSTALLED_APPS in your settings.py

Run python manage.py migrate

Add an entry to your urls.py:

urlpatterns += [
url(r'^captcha/', include('captcha.urls')),
]
pip install django-simple-captcha==0.4.6

配置邮箱设置!

settings.py
# Mail Config
EMAIL_HOST = 'smtp.laohulab.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = 'postmaster@qq.com'
EMAIL_HOST_PASSWORD = 'XXXX'
EMAIL_USE_TLS =False
EMAIL_FROM = 'postmaster@qq.com'

注册邮件发送

# coding:utf8
__author__ = 'jianhu.yong'
__date__ = '2018/7/5 16:29'
from random import Random
from django.core.mail import send_mail
from users.models import EmailVerifyRecord
from MxOnline.settings import EMAIL_FROM


def random_str(randomlength=8):
str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
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 = 'MX在线网注册激活链接'
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
else:
pass
elif send_type == 'forget':
email_title = 'MX在线网密码重置链接'
email_body = '请点击下面的链接重置密码:http://127.0.0.1:8000/reset/{0}'.format(code)
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
if send_status:
pass

激活用户设置

    url(r'^active/(?P<active_code>\w+)/$', ActiveUserView.as_view(), name='user_active'),

class ActiveUserView(View):
def get(self, request, active_code):
all_records = EmailVerifyRecord.objects.filter(code=active_code)
if all_records:
for record in all_records:
email = record.email
user = UserProfile.objects.get(email=email)
user.is_active = True
user.save()
else:
return render(request, 'active_fail.html')
return render(request, 'login.html')
```

密码找回
``` python
url(r'^forget/$', ForgetPwdView.as_view(), name='forget_pwd'),
url(r'^reset/(?P<active_code>\w+)/$', ResetView.as_view(), name='reset_pwd'),
url(r'^modify/$', ModifyPwdView.as_view(), name='modify_pwd'),

class RegisterView(View):
def get(self, request):
register_form = RegisterForm()
return render(request, 'register.html', {'register_form':register_form})
def post(self, request):
register_form = RegisterForm(request.POST)
if register_form.is_valid():
user_name = request.POST.get('email', '')
if UserProfile.objects.filter(email=user_name):
return render(request, 'register.html', {'msg':'用户已存在!','register_form': register_form})
pass_word = request.POST.get('password', '')
user_profile =UserProfile()
user_profile.username = user_name
user_profile.email = user_name
user_profile.is_active = False
user_profile.password = make_password(pass_word)
user_profile.save()

send_register_email(user_name, 'register')
return render(request, 'login.html')
else:
return render(request, 'register.html', {'register_form': register_form})


class ForgetPwdView(View):
def get(self, request):
forgetpwd_form = ForgetPwdForm()
return render(request, 'forgetpwd.html', {'forgetpwd_form':forgetpwd_form})
def post(self, request):
forgetpwd_form = ForgetPwdForm(request.POST)
if forgetpwd_form.is_valid():
email = request.POST.get('email', '')
send_register_email(email, 'forget')
return render(request, 'send_success.html')
else:
return render(request, 'forgetpwd.html', {'forgetpwd_form':forgetpwd_form})


class ResetView(View):
def get(self, request, active_code):
all_records = EmailVerifyRecord.objects.filter(code=active_code)
if all_records:
for record in all_records:
email = record.email
return render(request, 'password_reset.html', {'email':email})
else:
return render(request, 'active_fail.html')
return render(request, 'login.html')


class ModifyPwdView(View):
def post(self, request):
modify_form = ModifyPwdForm(request.POST)
if modify_form.is_valid():
pwd1 = request.POST.get('password1', '')
pwd2 = request.POST.get('password2', '')
email = request.POST.get('email', '')
if pwd1 != pwd2:
return render(request, 'password_reset.html', {'email':email, 'msg':'密码不一致!'})
user = UserProfile.objects.get(email=email)
user.password = make_password(pwd2)
user.save()
return render(request, 'login.html')
else:
email = request.POST.get('email', '')
return render(request, 'password_reset', {'email':email, 'modify_form':modify_form})

MEDIA_URL配置 调用静态image

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.media'
],
},
},
]

# upload setting
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# 配置上传文件的访问处理函数
url(r'^media/(?P<path>.*)$', serve, {'document_root':MEDIA_ROOT}),

from django.views.static import serve
from MxOnline.settings import MEDIA_ROOT

django分页功能!
https://github.com/jamespacileo/django-pure-pagination

upload successful
p = Paginator(all_orgs, request=request)
p = Paginator(all_orgs, 5, request=request)

upload successful
使用默认,分页样式无法控制

列表筛选功能

机构排名和课程学习人数排序

modelform提交

外键关系

{{ course.lesson_set.all.count }}


{% for user_course in course.usercourse_set.all %}
<span class="pic"><img width="40" height="40" src="{{ MEDIA_URL }}{{ user_course.user.image }}"/></span>
{% endfor %}


def get_zj_nums(self):
return self.lesson_set.all().count()

def get_learn_users(self):
return self.usercourse_set.all()[:5]

{{course.get_zj_nums}}
{% for usercourse in course.get_learn_users %}

用户上传文件
html
enctype=”multipart/form-data”

后端:

class UploadImageView(LoginRequiredMixin, View):
def post(self, request):
image_form = UploadImageForm(request.POST, request.FILES)
if image_form.is_valid():
image = image_form.cleaned_data['image']
request.user.image = image
request.user.save()
pass

# def post(self, request):
# image_form = UploadImageForm(request.POST, request.FILES, instance=request.user)
# if image_form.is_valid():
# image_form.save()
```


4040 500配置    





django xadmin 进阶开发


debug 改成true时候
注释
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
url(r'^static/(?P<path>.*)$', serve, {'document_root':STATIC_ROOT}),


model icon配置


model_icon = 'fa fa-user'
开源图标库
https://fontawesome.com/



![upload successful](/images/pasted-153.png)


倒叙排列
ordering = ['-click_nums']

设置字段只读
readonly_fields = ['click_nums', 'fav_nums']

移除某个字段显示
exclude = ['fav_nums']

需要注意是否和readonly_fields冲突

关联外键字段,添加搜索功能(针对外键数量很多是,自动搜索方便)
relfield_style = 'fk-ajax'

报错
TypeError: Related Field got invalid lookup: icontains
1
原因
出错原因是你配置的ModelAdmin类中,元组search_fields中的项不是字符类型。

解决
删除元组search_fields中类型不符的项


xadmin inline模式
``` python
class LessonInline(object):
model = Lesson
extra = 0

class CourseAdmin(object):
list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
search_fields = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums']
list_filter = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
ordering = ['-click_nums']
readonly_fields = ['click_nums']
exclude = ['fav_nums']
inlines = [LessonInline]
xadmin.site.register(Course, CourseAdmin)


class LessonInline(object):
model = Lesson
extra = 0


class CourseResourceInline(object):
model = CourseResource
extra = 0

class CourseAdmin(object):
list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
search_fields = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums']
list_filter = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
ordering = ['-click_nums']
readonly_fields = ['click_nums']
exclude = ['fav_nums']
inlines = [LessonInline, CourseResourceInline]
xadmin.site.register(Course, CourseAdmin)

同一个model 后台注册2个管理器,分别管理同一张表!

class Course(models.Model):
course_org = models.ForeignKey(CourseOrg, verbose_name=u"课程机构", null=True, blank=True)
name = models.CharField(max_length=50, verbose_name=u"课程名")
desc = models.CharField(max_length=300, verbose_name=u"课程描述")
detail = models.TextField(verbose_name=u"课程详情")
teacher = models.ForeignKey(Teacher, verbose_name=u"讲师", null=True, blank=True)
# TextField不限制max_length
degree = models.CharField(choices=(("cj", u"初级"),("zj", u"中级"),("bj", u"高级")), max_length=2, verbose_name=u"难度")
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"点击数")
category = models.CharField(default=u"后端开发", max_length=20, verbose_name=u"课程类别")
tag = models.CharField(default="", max_length=10, verbose_name= u"课程标签")
youneed_know = models.CharField(max_length=300, verbose_name=u"课程须知", default="")
teacher_tell = models.CharField(max_length=300 , verbose_name=u"老师告诉你学到什么", default="")
is_banner = models.BooleanField(default=False, verbose_name=u"是否轮播")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")

def get_zj_nums(self):
return self.lesson_set.all().count()

def get_learn_users(self):
return self.usercourse_set.all()[:5]

class Meta:
verbose_name = u"课程"
verbose_name_plural = verbose_name

def __unicode__(self):
return self.name


class BannerCourse(Course):
class Meta:
verbose_name = u"轮播课程"
verbose_name_plural = verbose_name
proxy = True








class CourseAdmin(object):
list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
search_fields = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums']
list_filter = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
ordering = ['-click_nums']
readonly_fields = ['click_nums']
exclude = ['fav_nums']
inlines = [LessonInline, CourseResourceInline]

def queryset(self):
qs = super(CourseAdmin, self).queryset()
qs = qs.filter(is_banner=False)
return qs
xadmin.site.register(Course, CourseAdmin)


class BannerCourseAdmin(object):
list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
search_fields = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums']
list_filter = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
ordering = ['-click_nums']
readonly_fields = ['click_nums']
exclude = ['fav_nums']
inlines = [LessonInline, CourseResourceInline]

def queryset(self):
qs = super(BannerCourseAdmin, self).queryset()
qs = qs.filter(is_banner=True)
return qs
xadmin.site.register(BannerCourse, BannerCourseAdmin)



list_editable
list_editable = ['name','degree']

list中 函数的引用

class Course(models.Model):
course_org = models.ForeignKey(CourseOrg, verbose_name=u"课程机构", null=True, blank=True)
name = models.CharField(max_length=50, verbose_name=u"课程名")
desc = models.CharField(max_length=300, verbose_name=u"课程描述")
detail = models.TextField(verbose_name=u"课程详情")
teacher = models.ForeignKey(Teacher, verbose_name=u"讲师", null=True, blank=True)
# TextField不限制max_length
degree = models.CharField(choices=(("cj", u"初级"),("zj", u"中级"),("bj", u"高级")), max_length=2, verbose_name=u"难度")
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"点击数")
category = models.CharField(default=u"后端开发", max_length=20, verbose_name=u"课程类别")
tag = models.CharField(default="", max_length=10, verbose_name= u"课程标签")
youneed_know = models.CharField(max_length=300, verbose_name=u"课程须知", default="")
teacher_tell = models.CharField(max_length=300 , verbose_name=u"老师告诉你学到什么", default="")
is_banner = models.BooleanField(default=False, verbose_name=u"是否轮播")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")

def get_zj_nums(self):
return self.lesson_set.all().count()
get_zj_nums.short_description = u'章节数'

def get_learn_users(self):
return self.usercourse_set.all()[:5]

class Meta:
verbose_name = u"课程"
verbose_name_plural = verbose_name

def __unicode__(self):
return self.name

class CourseAdmin(object):
list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time','get_zj_nums']
search_fields = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums']
list_filter = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time']
ordering = ['-click_nums']
readonly_fields = ['click_nums']
list_editable = ['name','degree']
exclude = ['fav_nums']
inlines = [LessonInline, CourseResourceInline]

自定义html代码

def go_to(self):
from django.utils.safestring import mark_safe
return mark_safe('<a href="http://www.baidu.com/{0}" target="_blank">Link</a>'.format(self.name))
go_to.short_description = u'章节数'

list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_nums','add_time','get_zj_nums','go_to']

定时刷新
refresh_times = [3, 5]
upload successful

数据发生变更触发操作
def save_models(self):
obj = self.new_obj
obj.save()
course_org = obj.course_org
if course_org:
course_org.course_nums = Course.objects.filter(course_org=course_org).count()
course_org.save()
```            
xadmin集成富文本编辑工具
https://github.com/zhangfisher/DjangoUeditor

pip install DjangoUeditor
setting.py 配置 instal app
url配置
拷贝DjangoUeditor static html文件

``` html
{% autoescape off %}
{{ course.detail }}
{% endautoescape %}

https://blog.csdn.net/wgpython/article/details/79585205

uedit插件

excel插件

https://blog.csdn.net/win_turn/article/details/55517759
http://django-simple-captcha.readthedocs.io/en/latest/usage.html#installation

http://projectsedu.com/2017/08/15/centos7-%E4%B8%8B%E9%80%9A%E8%BF%87nginx-uwsgi%E9%83%A8%E7%BD%B2django%E5%BA%94%E7%94%A8/

0%