一、Django版本变化
1.request.user.is_authenticated()和request.user.is_anonymous()之后推荐使用属性,例如:
if request.user.is_authenticated:
... # Do something for logged-in users.
else:
... # Do something for anonymous users.
版本1.10
2. django.core.urlresolvers模块废弃,改为新的包django.urls,主要涉及常用的
from django.core.urlresolvers import reverse #废弃
版本1.10
3.render_to_response()和render()删除了参数context_instance
return render_to_response('index.html', context,
context_instance=RequestContext(request)) #废弃
直接用render即可(render中也没有context_instance参数)如下
return render(request, 'index.html', context)
版本1.10
4.session默认开启验证和和django.contrib.auth.middleware.SessionAuthenticationMiddleware无关
可以从MIDDLEWARE_CLASSES中移除
版本1.10
5.login()和logout()废弃,改用类LogView和LogoutView,但3.1版本文档案例仍在使用,故此项不必在意
版本1.11
6.authenticate()增加了一个参数request,且作为第一个参数,为可选参数
版本1.11
7.自Django2.0开始只支持python3.4及以上版本
8.不再使用路径django.conf.urls,改为from django.urls import include, path, re_path。涉及到urls.py
且url中可以使用path替代url
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), #原来
path('articles/<int:year>/', views.year_archive), #新的
版本2.0
9.render_to_response不推荐,使用render()
版本2.0
10.ForeignKey和OneToOneField中on_delete是必须的
版本2.0
11.旧形式的settings.MIDDLEWARE_CLASSES移除
版本2.0
12.自Django2.1起只支持3.5及以上版本
13.自Django2.1起,MySQL5.5不再支持,只支持MySQL5.6及以上版本
14. {% load staticfiles %} 和 {% load admin_static %}不再推荐,而使用{% load static %}替代
15.自Django3.0起只支持Python3.6及以上版本
16.JSONField最所有数据库支持
from django.db import models
class ContactInfo(models.Model):
data = models.JSONField()
ContactInfo.objects.create(data={
'name': 'John',
'cities': ['London', 'Cambridge'],
'pets': {'dogs': ['Rufus', 'Meg']},
})
ContactInfo.objects.filter(
data__name='John',
data__pets__has_key='dogs',
data__cities__contains='London',
).delete()
版本3.1
17.startproject命令使用pathlib.Path替代os.path来替代路径管理
版本3.1
18.RequestContext从django.template.base中移除
版本3.1
19. 在models中__str__替代__unicode__
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
20.自Ubuntu20.04起,python命令的默认版本为python3.8,不再是python2.7
默认不再提供python命令,鼓励安装python-is-python3包使python指向python3
21.django不再支持mysql5.6以下版本,仅支持mysql5.7以上
版本3.2
22.不再使用pytz
版本4.0
默认时间模块改为zoneinfo(python3.9自带,3.8会随django安装) 而非pytz(处于不推荐状态),5.0会删除pytz。这里需要注意如何转换,需要改代码。
使用settings的USE_DEPRECATED_PYTZ 和 pytz_deprecation_shim包来继续使用pytz在4版本上,直到5.0之前
23.CSRF加了orrigin header,需要对CSRF_TRUSTED_ORIGINS 进行修改。
版本4.0
二、操作记录变化
1.celery5.0
1)celery5.0默认不再支持传入类的实例化对象,只传入整形或字符串,如q = Question.objects.get(id=1)的q不能直接传入函数中。
如果想传入obj对象,则要按如下配置
a. settings.py 中,指定数据类型为pickle
CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']
CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_SERIALIZER = 'pickle'
b.如果使用容器,需要在celery.py中
platforms.C_FORCE_ROOT = True #允许以root启动celery ,因在容器中用户为root
2)django配置celery
a.在setting.py所在的文件夹下创建celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') #其中mysite为settings.py所在文件夹的文件名
app = Celery('mysite') #其中mysite为settings所在文件夹的文件名
app.config_from_object('django.conf:settings', namespace='CELERY') #namespace为settings.py中celery相关配置的前缀为‘CELERY_’如CELERY_BROKER_URL
app.autodiscover_tasks(related_name='tasks') #自动从工程的各app中找函数,related_name为函数所在的文件名,全都要在一个文件中此时值为tasks则从tasks.py中找,注意其他文件中的函数不再被celery识别
b.在settings.py所在的文件夹下的__init__.py中
from .celery import app as celery_app
__all__ = ('celery_app',)
c.在setting.py中配置CELERY_BROKER_URL
CELERY_BROKER_URL = 'pyamqp://myuser:mypassword@localhost/myvhost' #前缀‘CELERY_’由第一步中namespace指定
2.settings.py分拆
settings.py分拆两个文件后,setting.py本身代码如下
import os
import glob
conf_files = glob.glob(os.path.join(os.path.dirname(__file__), 'settings', '*.py'))
conf_files.sort()
for f in conf_files:
exec(open(os.path.abspath(f), encoding='utf-8').read()) #这里和原python2.7不同
3.散记
1)hashlib包
##python2.7
hashlib.sha1(plainText).hexdigest()
##python3
hashlib.sha1(plainText.encode("utf8")).hexdigest()
2)上传函数修改路径为polls.models/question/20201202/
def upload_file_handler(instance,filename):
date_str = datetime.datetime.now().strftime("%Y%m%d")
# path = date_str +"/"+instance.__class__.__name__.lower()
path = instance.__module__ +"/"+instance.__class__.__name__.lower() + "/" + date_str
suffix = filename.split(".")[-1] or "jpg"
filename = generate_file_code()+"."+suffix
return os.path.join(path, filename)
3)在ubuntu系统中重启celery,./run.sh celery restart 镜像中的celery的也会启动并可以执行
4)工程和app操作
django-admin startproject mysite #创建工程
python manage.py startapp polls #创建app
#将app加入到工程中,在settings中
INSTALLED_APPS = [
'polls.apps.PollsConfig',
...
]
4.url变化
1)基本介绍
path('articles/<slug:title>/', views.article, name='article-detail'), #指定类型包含 int slug
re_path(r'^index/$', views.index, name='index'), #正则匹配类型,相当于原url()
2)namespace和app_name
a.首先如果使用namespce必须指定app_name,两种方式
方式一,在总的urls中
urlpatterns = [
path('admin/', admin.site.urls),
path('joying/', include(('joying.urls', 'joying'), namespace='joying1')),
]
include的第一个参数编程元组,元组第二个元素是app_name
方式二,在app的urls中
app_name = 'joying' #定义一个变量app_name 即可
urlpatterns = [
path('', views.index, name='index'),
]
b)使用方式相同,在上面的代码中
print(reverse('joying:index')) #使用app_name
#结果:/joying/
print(reverse('joying1:index')) #使用namespce
#结果:/joying/
c)平时只用app_name即可
5.python3+Django3.1.4 报错:UnicodeEncodeError: 'ascii' codec can't encode characters in position 119-120: ordinal not in range(128)
原因不是因为汉字编码,而是urls对应的views中没有方法
#urls.py中
urlpatterns = [
re_path(r'^mylogin/$', views.mylogin, name='mylogin'), #ajax登录
]
#views.py中不是mylogin而是mylogin1,即函数名写错
def mylogin1(request):
'''登录'''
'''
奇葩!导致此问题需要两个条件
1.url中对应的路径re_path后面有中文注释
2.此re_path中写的views中的函数不存在。
6.UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list
在服务器启动后,第一次请求列表页面,会出现此警告,后续不再提示。决绝方式很简单,对翻页的objects加排序即可,如对query_set 加order_by(‘id’)
7.获取当前时间(USE_TZ=True的情况下)
在django3的项目里禁用以下函数
datetime.datetime.now()
datetime.date.today()
而是使用
from django.utils import timezone
def get_now_time():
'''获取带时区的本地时间'''
return timezone.localtime(timezone.now())
def get_today():
'''获取(本地)今天'''
return get_now_time().date()
原因是虽然datetime.datetime.now()无论在django1.9还是django3中返回的都是不带时区的datetime对象,但是在django1.9中返回的是本地时间,而django3返回的是UTC时间。
#django1.9
datetime.datetime.now()
返回北京时间:datetime.datetime(2021, 6, 22, 7, 9, 30, 72009)
datetime.date.today()
返回北京时间:datetime.datetime(2021, 6, 22)
#django3
datetime.datetime.now()
返回UTC时间:datetime.datetime(2021, 6, 21, 23, 9, 30, 72009)
datetime.date.today()
返回UTC时间:datetime.datetime(2021, 6, 21)