Django3 学习记录笔记
Django 是一个文档很全的框架,学习的时候老是遇到一些坑,这里就顺便记录一下,以便后面使用,同时也希望本文可以帮助到其他的朋友。
开发环境
操作系统:macOS Cataline 10.15.3
Python:pyenv 安装的 pypy3.6-7.3.0 (PyPy解释器平均比我们平时使用的CPython快4.4倍)
Django:Django 3.0.3
相关依赖
MySQL
macOS 下 Django3 在连接 MySQL 会出一些问题,解决如下:
# 确保 pip 是最新版本
$ pip install --upgrade pip
# 临时在当前的shell环境中配置一个 openssl 变量
export LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS"
export CPPFLAGS="-I/usr/local/opt/openssl/include $CPPFLAGS"
$ pip install mysqlclient
pillow
在models.py
中含有ImageField
图片类型的时候,如果pillow
没有安装好的话 会报错:
image = models.ImageField(upload_to='avatar/%Y/%m', verbose_name='头像', max_length=100)
解决方法是 macOS 下安装配置好zlib
即可:
# 安装 zlib
$ brew install zlib
# 链接 zlib 会提示
$ brew link zlib --force
Warning: Refusing to link macOS-provided software: zlib
For compilers to find zlib you may need to set:
export LDFLAGS="-L/usr/local/opt/zlib/lib"
export CPPFLAGS="-I/usr/local/opt/zlib/include"
根据上述提示,进行如下操作:
# 临时在当前的shell环境中配置一个 zlib 变量
export LDFLAGS="-L/usr/local/opt/zlib/lib"
export CPPFLAGS="-I/usr/local/opt/zlib/include"
$ pip install pillow
目录配置
templates
模板目录 Python 命令行创建的 Django 项目默认是没有自动生成这个目录的,首先项目目录下新建templates
文件夹,然后配置一下 settings:
settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 将 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',
],
},
},
]
static
该目录存放一些 css js 之类的静态文件,也得手动到 settings.py 添加配置一下:
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [(os.path.join(BASE_DIR, 'static'))]
apps
当项目下的app太多的时候,项目的目录结构看上去就会比较混乱,一个解决办法就是将项目下的所有app都放到一个apps的文件夹中,首先项目下新建apps
文件夹,接着手动到 settings.py 添加配置一下:
settings.py
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) # 将 apps 文件夹添加到 BASE_DIR中
media
media 文件夹用来存放用户上传的图片资料等,首先配置下 settings.py
settings.py
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.template.context_processors.media', # 添加 media 模板
],
},
},
]
接着配置 media 根目录变量:
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
配置好之后在 urls.py 里面配置下 media 的路由规则:
urls.py
from django.urls import path, re_path
from django.views.static import serve
from project.settings import MEDIA_ROOT
urlpatterns = [
path('admin/', admin.site.urls),
# 配置 media 的处理
re_path('media/(?P<path>.*)', serve, {'document_root': MEDIA_ROOT}, name='org_list'),
]
下面看一下 简单的 引用 meida 中图片文件的实例:
models.py
class CourseOrg(models.Model):
...
image = models.ImageField(upload_to='org/%Y/%m', verbose_name='logo', max_length=100)
...
前端调用显示 media 里的文件
<img width="200" height="120" class="scrollLoading" data-url="{{ MEDIA_URL }}{{ course_org.image }}"/>
实用插件
验证码
项目地址:https://github.com/mbi/django-simple-captcha
$ pip install django-simple-captcha
安装好之后,在settings.py
引用即可:
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'captcha', # 引用验证码插件
]
引用完成后,更新下数据库的信息,因为这个验证码信息是存放在本地数据库中的:
$ python manage.py makemigrations
$ python manage.py migrate
数据库更新成功后可以在数据库下看到 captcha_captchastore
表名,接着得配置下验证码的url路由规则:
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('captcha/', include('captcha.urls')),
]
Form 表单中定义如下:
forms.py
from django import forms
from captcha.fields import CaptchaField
class RegisterForm(forms.Form):
email = forms.EmailField(required=True)
password = forms.CharField(required=True, min_length=5)
captcha = CaptchaField(error_messages={'invalid': '验证码错误'})
Views 里面实例化这个表单类:
views.py
class RegisterView(View):
def get(self, request):
register_form = RegisterForm()
return render(request, 'register.html', {
'register_form': register_form
})
views.py 里面 返回了register_form
到前端,接着前端可以直接调用 验证码:
<div class="form-group marb8 captcha1">
<label>验证码</label>
{{ register_form.captcha }}
</div>
分页
项目地址:https://github.com/jamespacileo/django-pure-pagination
$ pip install django-pure-pagination
安装好之后,在settings.py
引用即可:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'pure_pagination',
]
views 里面的基本用法:
views.py
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger
class OrgView(View):
"""
课程机构列表功能显示
"""
def get(self, request):
# 课程机构
all_orgs = CourseOrg.objects.all()
# 官方提倡的写法
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
# 将数据库中 查询的 all_orgs 分页 每页显示5个
p = Paginator(all_orgs, 5, request=request)
orgs = p.page(page)
return render(request, 'org-list.html', {
'all_orgs': orgs, # 分页的结果传给前端
})
前端分页的引用:
<div class="pageturn">
<ul class="pagelist">
<!-- 判断是是否有上一页 -->
{% if all_orgs.has_previous %}
<li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}">上一页</a></li>
{% endif %}
<!-- 显示中间页数 和 高亮 当前页 -->
{% for page in all_orgs.pages %}
{% if page %}
{% ifequal page all_orgs.number %}
<li class="active"><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% endifequal %}
{% else %}
<li class="none"><a href="">...</a> </li>
{% endif %}
{% endfor %}
<!-- 判断是是否有下一页 -->
{% if all_orgs.has_next %}
<li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}">下一页</a></li>
{% endif %}
</ul>
</div>
最后的分页效果如下:
导入导出
项目地址:https://github.com/django-import-export/django-import-export
$ pip install django-import-export
安装好之后,在settings.py
引用即可:
settings.py
INSTALLED_APPS = [
'import_export', # 引用导入导出插件
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
接着可以直接在 Django Admin后台引用:
admin.py
from import_export.admin import ImportExportActionModelAdmin
@admin.register(CourseOrg)
class CourseOrgAdmin(ImportExportActionModelAdmin):
list_display = ['name', 'image_data', 'address']
search_fields = ['name', 'city', 'address', 'desc']
list_filter = ['city', 'add_time']
最后配合 Simple UI 的效果如下:
Admin 配置
修改后台名称
在 urls.py 里面添加 如下即可:
admin.site.site_header = '后台管理'
admin.site.site_title = 'Django 后台管理'
核心原理就是在引用 这个模块的文件里面添加配置即可生效:
from django.contrib import admin
最后效果如下:
图片显示
Django Admin 的列表中图片只显示 URL 地址,却不能直接显示出来:
Django Admin图片不显示
解决方法就是重写 Django Admin 后台图片的显示。
models.py
from django.utils.html import format_html
class CourseOrg(models.Model):
image = models.ImageField(upload_to='org/%Y/%m', verbose_name='logo', max_length=100)
# 定义 image_data 将 url 手动 通过 img 表情显示出来
def image_data(self):
return format_html(
'<img src="{}" width="200px" height="90px"/>',
self.image.url,
)
# 设置标题
image_data.short_description = '图片'
admin.py
from django.contrib import admin
@admin.register(CourseOrg)
class CourseOrgAdmin(admin.ModelAdmin):
# 显示里面 传入 我们自定义的 image_data
list_display = ['name', 'image_data', 'address']
search_fields = ['name', 'city', 'address', 'desc']
list_filter = ['city', 'add_time']
# 设置该列不可编辑
readonly_fields = ('image_data',)
最后显示效果如下:
支持一下
本文可能实际上也没有啥技术含量,但是写起来还是比较浪费时间的,在这个喧嚣浮躁的时代,个人博客越来越没有人看了,写博客感觉一直是用爱发电的状态。如果你恰巧财力雄厚,感觉本文对你有所帮助的话,可以考虑打赏一下本文,用以维持高昂的服务器运营费用(域名费用、服务器费用、CDN费用等)
微信
![]() |
支付宝
![]() |
没想到文章加入打赏列表没几天 就有热心网友打赏了 于是国光我用 Bootstrap 重写了一个页面用以感谢支持我的朋友,详情请看 打赏列表 | 国光