建立项目结构
建立Django项目
虚拟环境创建(终端环境cmd下)
- 自行找个合适的位置建立python虚拟环境,避免与其他项目环境产生冲突(前提是已安装了虚拟环境库)
# life_blog_venv为虚拟环境名 python -m venv life_blog_venv
- 进入虚拟环境
- 进入Scripts目录
- 输入activate.bat,回车
Django项目创建
- 进入虚拟环境后,回到life_blog_venv项目目录里,安装Django
pip install Django
- 创建Django项目,项目名为lifeblog
django-admin startproject lifeblog
- 进入lifeblog文件夹,创建app应用
python manage.py startapp post python manage.py startapp blogger
- 将app名添加到settings.py中的INSTALLED_APPS列表(settings.py位于与项目同名的内部文件夹中)
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blogger', # 添加该行 'post', # 添加该行 ]
- 创建配置文件夹conf(用于存放配置文件):该文件夹与manage.py同级
- 创建static文件夹(用于存放静态文件和静态模板):该文件夹与manage.py同级
- 在static文件夹中分别创建以下三个文件夹
- media:用于存放图片
- static:用于存放静态文件(css、js文件等)
- template:用于存放静态模板(html文件)
Django项目整体结构图
图中的whoosh_index文件夹将在后续步骤中建立。而comment不需要建立。.idea文件夹为开发工具生产的文件夹,无需自行建立。
项目汉化
修改settings.py文件中的相关配置
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
配置静态文件路径
在settings.py文件中添加相关配置
STATIC_URL = '/static/'
# 配置ImageFile字段图片上传路径
MEDIA_URL = '/media/' # # 用于指定url路径
MEDIA_ROOT = os.path.join(BASE_DIR, 'static', 'media') # 用于指定上传文件的存储路径
if DEBUG == False:
STATIC_ROOT = os.path.join(BASE_DIR,'collected_static') # 用于在(debug=False)生产环境下加载静态文件。
# 参数:自动在项目根目录创建collected_static目录用于存放移过来静态文件(在生产环境下执行python manage.py collectstatic时,会自动创建collected_static目录)
# 配置静态文件路径
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static','static'),
)
在(内部lifeblog文件下)根urls.py文件添加如下代码
from django.contrib import admin
from django.urls import path
from django.conf.urls import include,url
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns # 加入该行,如若不加,在生产环境下无法加载样式
from django.views.static import serve # 加入该行,如若不加,在生产环境下无法加载样式
urlpatterns = [
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # 用于上传和显示图片
urlpatterns += staticfiles_urlpatterns() # # 加入该行,如若不加,在生产环境下可能无法加载样式
if settings.DEBUG == False:
print('当前处于生产环境下')
urlpatterns += [
url(r'^static/(?P<path>.*)$',serve,{'document_root':settings.STATIC_ROOT}), # 加入该行,如若不加,在生产环境下无法加载样式
url(r'^media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}), # 加入该行,如若不加,在生产环境下无法显示图片
]
else:
print('当前处于开发环境下')
配置模板文件路径
修改settings.py文件中的相关配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'static','template')], # 添加该行
'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',
],
'builtins':['django.templatetags.static'], # 添加该行,设置该行后,不需要在静态模板文件中显示使用{% load static %}
},
},
]
配置MySQL数据库
==记得先在MySQL中创建用到的数据库,这里我们使用的数据库名为lifeblog_database。==
这里我们采用读取配置文件的方式来设置MySQL数据库信息,比较安全。
- 在conf文件夹下建立以下两个文件
- config.ini
- config_read.py
config.ini文件内容
[MySQL]
host=localhost
user=root
password=数据库密码
db=lifeblog_database
charset=utf8
port=3306
config_read.py 文件内容
==注意:需先在虚拟环境下安装第三方库configparser==
pip install configparser
import configparser
import os
project_dir = os.path.dirname(os.path.abspath('conf')) # 获取当前文件的目录
config_path = os.path.join(project_dir, "conf", "config.ini")
cf = configparser.ConfigParser()
cf.read(config_path) # 读取配置文件
# secs = cf.sections() # 获取ini文件中的所有section,并以列表形式返回
# mysql_options = cf.options("MySQL") #获取某个section名所对应的键
# mysql_items = cf.items("MySQL") # 获取section对应的全部键值对
host = cf.get("MySQL", "host")
user = cf.get("MySQL", "user")
password = cf.get("MySQL", "password")
db = cf.get("MySQL", "db")
charset = cf.get("MySQL", "charset")
port = cf.get("MySQL", "port")
sql = {
'HOST' : host,
'USER' : user,
'PASSWORD' : password,
'DB' : db,
'CHARSET' : charset,
'PORT' : port
}
修改settings.py文件下的DATABASES。
# MySQL数据库配置
from conf.config_read import sql # 读取配置文件
DATABASES = {
'default':{
'ENGINE': 'django.db.backends.mysql',
'NAME': sql['DB'], # 数据库名称
'USER': sql['USER'], # 数据库用户
'PASSWORD': sql['PASSWORD'], # 数据库密码
'HOST': sql['HOST'], # 数据库ip
'PORT': sql['PORT'], # 数据库端口
}
}
app模型字段创建
在前面,我们建立了blogger和post两个应用,在应用文件夹下会生成多个py文件,模型字段的定义在models.py文件中创建,用于映射(ORM)到数据库中,创建相应的数据表。
定义数据字段
blogger和post文件夹下的models.py中写入如下代码
- blogger/models.py
from django.db import models
from ckeditor.fields import RichTextField
# Create your models here.
class Blogger(models.Model):
'''博主信息模型'''
name = models.CharField('博主名',default='狼性书生',max_length=20)
head_photo = models.ImageField('头像', upload_to='blog_img',null=True,blank=True,default='/cover_img/default.jpg')
blog_major = models.CharField('职业',default='程序猿',max_length=20)
autograph = RichTextField('个性签名',default='个性签名')
blog_email = models.EmailField('博主邮箱',default='794859685@qq.com')
def __str__(self):
return self.name
class Link(models.Model):
'''博主链接模型'''
icon_name = models.CharField("链接图标",max_length=50,default='fa fa-dribbble')
link_name = models.CharField("链接",max_length=50)
blogger = models.ForeignKey('Blogger',on_delete=models.CASCADE,related_name='blogger_link')
def __str__(self):
return self.link_name
class Layout(models.Model):
'''网站配置模型'''
# main_image = models.ImageField("首页图",upload_to='layout_img',default='/layout_img/home-banner.jpg')
logo_image = models.ImageField("Logo",upload_to='layout_img',default='/layout_img/favicon.ico')
website_name = models.CharField("网站标题名",max_length=20,default='Mr Wolf Blog')
def __str__(self):
return self.website_name
- post/models.py
在static/media文件下创建cover_img文件夹,用于存放文章封面
import os
import time
import datetime
from django.db import models
# Create your models here.
def modify_path(instance, filename):
'''
重定义封面保存路径
:param instance: self
:param filename: 文件名
:return: 新路径
'''
ext = filename.split('.').pop()
now_date = datetime.datetime.now().strftime('%Y%m%d')
now_time = int(time.time())
filename = '{0}{1}.{2}'.format(now_date, now_time, ext)
return os.path.join('cover_img', now_date, filename) # 系统路径分隔符差异,增强代码重用性
class Post(models.Model):
'''
文章模型
'''
title = models.CharField('标题',max_length=100,default='无标题名',null=True,blank=True)
cover = models.ImageField('封面', upload_to=modify_path,null=True,blank=True,default='/cover_img/default.jpg')
create_time = models.DateTimeField('创建时间',auto_now=True)
content = models.TextField('文章内容',default='文章内容')
is_publish = models.BooleanField(default=False)
is_comment = models.BooleanField(default=False)
total_views = models.PositiveIntegerField('文章浏览量',default=0)
# 文章与分类:多对一关系。在多的一方定义ForeignKey字
category = models.ForeignKey('Category',on_delete=models.CASCADE,related_name='post')
def __str__(self):
return self.title
# 完善后台数据显示过长情况
def short_detail(self):
if len(str(self.content)) > 30:
return '{}...'.format(str(self.content)[0:29])
else:
return str(self.content)
short_detail.allow_tags = True
short_detail.short_description = u'文章内容'
class Category(models.Model):
post_category = models.CharField('文章类别',max_length=20,default='杂记')
def __str__(self):
return self.post_category
将模型字段注册到admin后台
创建超级用户
虚拟环境、manage.py所在目录下执行如下指令
python manage.py createsuperuser
# 输入用户名、密码,邮箱可不填
注册字段到Admin后台
- post/admin.py
from django.contrib import admin
from .models import Post,Category
from django.utils.safestring import mark_safe
# Register your models here.
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['title','image_data','create_time','short_detail','is_publish','is_comment','category','id']
list_editable = ['is_publish','is_comment','category']
list_filter = ['title','create_time','is_publish','is_comment','category']
# readonly_fields = ('image_data',)
# 缩略图显示
def image_data(self,obj):
return mark_safe(u'<img src="%s" width="100px" />' % obj.cover.url)
image_data.short_description = u'封面'
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['id','post_category']
list_editable = ['post_category']
- blogger/admin.py
from django.contrib import admin
from .models import Blogger,Link,Layout
from django.utils.safestring import mark_safe
admin.site.site_title="Mr Wolf Blog"
admin.site.site_header="Mr Wolf博客管理系统"
@admin.register(Blogger)
class BloggerAdmin(admin.ModelAdmin):
list_display = ['id','name','image_data','blog_major','autograph','blog_email']
list_editable = ['name','blog_major','blog_email']
# 缩略图,后台展示页显示缩略图
def image_data(self,obj):
return mark_safe(u'<img src="%s" width="100px" />' % obj.head_photo.url)
image_data.short_description = u'头像'
@admin.register(Link)
class LinkAdmin(admin.ModelAdmin):
list_display = ['id','link_name','icon_name']
# list_editable = ['link_name']
@admin.register(Layout)
class LayoutAdmin(admin.ModelAdmin):
list_display = ['id', 'logo_img', 'website_name']
list_editable = ['website_name']
def logo_img(self,obj):
return mark_safe(u'<img src="%s" width="100px" />' % obj.logo_image.url)
logo_img.short_description = u'logo'
数据库迁移
虚拟环境、manage.py所在目录下执行如下指令
python manage.py makemigrations # 记录App下models的变更记录,生成migrations文件,可查看文件内的py文件的内容
python manage.py migrate # 同步迁移的记录
迁移过程中可能会报错,比如pillow库未找到等,这是未导入第三方库的原因,可根据报错信息,缺什么就"pip install 什么库"。
或者pip install -r requirements.txt,前提是拉取github上本项目的requirements.txt文件。
其他异常解决方法
-
ImportError: cannot import name 'six' from 'django.utils'异常
- 安装six
pip install six
- 将Lib/site-packages/six.py复制到Lib/site-packages/django/utils
-
ImportError: cannot import name python_2_unicode_compatible异常
- 报错地方导入的包替代为以下导入语句
from django.utils.six import python_2_unicode_compatible
启动Django
虚拟环境、manage.py所在目录下执行如下指令
python manage.py runserver
浏览器进入http://127.0.0.1:8000/admin
登录进去后,是比较简陋的界面,后续将对其进行美化。