django1.9.4升4.0记录

一、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)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值