[关闭]
@chengxuyuan 2019-11-05T09:44:35.000000Z 字数 3450 阅读 577

Django 项目 Python2 转 Python3 问题总结

橙旭园儿童编程

  1. 使用 Python2 转 Python3 工具 2to3 可以转转换大部分代码。

    1. $ find -name "*.pyc" -exec rm {} +;
    2. $ mkdir ../project_name_py2to3
    3. $ 2to3 --output-dir=../project_name_py2to3 -W -n .
    4. $ cp -r ../project_name_py2to3/* .
    5. $ python manage check
    6. ...... # 解决 check 检测出的错误
  2. Python3 环境不支持 Django2.0 以下版本。Django1.9 升级到 Django2.0 需要解决以下问题:

    • 项目的根 urls.py 中路径配置问题。

      1. 1. 使用 path() 指定路径到不同的 app,不再支持使用 url() 指定。
      2. 2. path() 中的路径不支持正则表达式的形式。
      3. 3. include() 第二个参数必须指定 app 的名字。
      4. 4. include(),path() django.urls import
      5. from django.urls import include, path
      6. - url(r'^admin/', admin.site.urls),
      7. - url(r'^projects/', include('projects.urls', namespace='projects')),
      8. - url(r'^v3/channels/', include('channels.urls', namespace='channels')),
      9. + path('admin/', admin.site.urls),
      10. + path('projects/', include(('projects.urls', 'projects'), namespace='projects')),
      11. + path('v3/channels/', include(('channels.urls', 'channels'), namespace='channels')),
      1. $ sed -i'' -e 's/from django.conf.urls import url, include/from django.urls import path, include/g' project/urls.py
      2. $ sed -i'' -e "s/include('\(\w\+\)\.urls', namespace='\(\w\+\)')/include(('\1.urls', '\1'), namespace='\2')/g" project/urls.py
      3. $ sed -i'' -e "s/url(r'^/path('/g" project/urls.py
    • is_authenticated 不再是一个函数,而是一个布尔值。

      1. $ find -name "*.py" -exec sed -i'' -e 's/is_authenticated()/is_authenticated/g' {} +;
    • models.ForeignKey(),models.OneToOneField() 必须指定 on_delete 参数。

      1. # 外键
      2. $ find -name "*models.py" -exec sed -i'' -e 's/models\.ForeignKey(\(.*\),/models\.ForeignKey(\1, on_delete=models.CASCADE,/g' {} +
      3. # OneToOne
      4. $ find -name "*models.py" -exec sed -i'' -e 's/models\.OneToOneField(\(.*\),/models\.OneToOneField(\1, on_delete=models.CASCADE,/g' {} +
      5. # 注意:还要继续处理一些重复 on_delete,还有一些不能用上面两个正则表达式修改的。
    • django.urls 代替了 django.core.urlresolvers。resolve(), reverse() 等函数需从 django.urls import:

      1. $ find -name "*.py" -exec sed -i'' -e 's/django\.core\.urlresolvers/django\.urls/g' {} +;
    • settings.py 中的 MIDDLEWARE 要改成:

      1. MIDDLEWARE = [
      2. 'django.middleware.security.SecurityMiddleware',
      3. 'django.contrib.sessions.middleware.SessionMiddleware',
      4. 'django.middleware.common.CommonMiddleware',
      5. 'django.middleware.csrf.CsrfViewMiddleware',
      6. 'django.contrib.auth.middleware.AuthenticationMiddleware',
      7. 'django.contrib.messages.middleware.MessageMiddleware',
      8. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
      9. ]
    • filters.DjangoFilterBackend 都要从 django_filters.rest_framework 中引用

      1. $ find -name "*.py" -exec sed -i'' -e 's/filters.DjangoFilterBackend/django_filters.rest_framework.DjangoFilterBackend/g' {} +;
    • admin 中的actions 重实现了 delete_selected 等方法的,需要重新实现 get_actions:

      1. def get_actions(self, request):
      2. actions = super().get_actions(request)
      3. if 'delete_selected' in actions:
      4. del actions['delete_selected']
      5. actions += [delete_selected]
      6. return actions
    • djago_filters 2.2.0 的 Filter 做以下改动:(name 改成 field_name, 参数用 lookup_expr指定)

      1. - week = django_filters.NumberFilter(name='starttime__range', method='filter_week')
      2. - day = django_filters.NumberFilter(name='starttime__date__gte', method='filter_day')
      3. - teacher = django_filters.CharFilter(name='teacher__username')
      4. + week = django_filters.NumberFilter(field_name='starttime', lookup_expr='range', method='filter_week')^M
      5. + day = django_filters.NumberFilter(field_name='starttime', lookup_expr='date__gte', method='filter_day')^M
      6. + teacher = django_filters.CharFilter(field_name='teacher__username')
    • 在 Model中用 str()代替 unicode():

      1. $ find -name "models.py" -exec sed -i'' -e "s/def __unicode__/def __str__/g" {} +;
  3. Python3 环境使用 json.dump() 不需要 encode('utf-8')

    1. $ find -name "*.py" -exec sed -i'' -e "s/json\.dumps(\(.*\))\.encode('utf-8')/json.dumps(\1)/g" {} +;
  4. Python3 环境没有默认的 sha, md5 Module.

  5. redis.setex() 的 expire_time 在第二个参数,value 在第三个参数.

  6. redis 读取数据时默认不会 encode(), 读取出的是:b'01234' 这种类型的数据。需要在连接池或其它初始化时加上 decode_responses=True.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注