惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
The GitHub Blog
The GitHub Blog
博客园_首页
T
The Blog of Author Tim Ferriss
H
Hackread – Cybersecurity News, Data Breaches, AI and More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
I
InfoQ
量子位
J
Java Code Geeks
P
Proofpoint News Feed
有赞技术团队
有赞技术团队
Webroot Blog
Webroot Blog
Martin Fowler
Martin Fowler
D
Docker
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
V
Vulnerabilities – Threatpost
罗磊的独立博客
P
Proofpoint News Feed
T
The Exploit Database - CXSecurity.com
Cyberwarzone
Cyberwarzone
P
Privacy & Cybersecurity Law Blog
Last Week in AI
Last Week in AI
爱范儿
爱范儿
The Hacker News
The Hacker News
S
SegmentFault 最新的问题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
V
V2EX
Simon Willison's Weblog
Simon Willison's Weblog
AI
AI
Y
Y Combinator Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
GbyAI
GbyAI
V
Visual Studio Blog
H
Heimdal Security Blog
S
Secure Thoughts
B
Blog RSS Feed
雷峰网
雷峰网
T
Tenable Blog
C
Check Point Blog
G
Google Developers Blog
大猫的无限游戏
大猫的无限游戏
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
About on SuperTechFans
Recent Commits to openclaw:main
Recent Commits to openclaw:main

blag

SQLite prefixes its temp files with `etilqs_` - blag Setsum - order agnostic, additive, subtractive checksum - blag Oldest recorded transaction - blag Replacing a cache service with a database - blag SQLite commits are not durable under default settings - blag PSA: SQLite WAL checksums fail silently and may lose data - blag Rickrolling Turso DB (SQLite rewrite in Rust) - blag Collection of insane and fun facts about SQLite - blag How bloom filters made SQLite 10x faster - blag In search of a faster SQLite - blag Galloping Search - blag Building a distributed log using S3 (under 150 lines of Go) - blag Zero Disk Architecture - blag PSA: Most databases do not do checksums by default - blag PSA: SQLite does not do checksums - blag Disaggregated Storage - a brief introduction - blag Why does SQLite (in production) have such a bad rep? - blag SQLite Slaps - blag Now - blag Learning C - blag Snapshot Testing - blag Win: contribution to libSQL (SQLite) codebase - blag Errata in Hekaton MVCC paper - blag Internet is wholesome: MVCC edition - blag It is becoming difficult for me to be productive in Python - blag MongoDB secondary only index - blag Introducing CaskDB – a project to teach you writing a key-value store - blag Recurse Center: Winter Break - blag Recurse Center Day 24: Hacking Go compiler to add a new keyword - blag Recurse Center Day 19 - blag Recurse Center Day 18 - blag Recurse Center Day 17 - blag Recurse Center Day 16: Open Source - blag Recurse Center Day 15: B Tree Algorithms - blag Recurse Center Day 14: NoSQL Transactions - blag Recurse Center Day 13: Why 'Raft'? - blag Recurse Center Day 12: Isolation Anomalies - blag Recurse Center Day 11: B Tree Insertions - blag Recurse Center Day 10: Learning Distributed Systems - blag Recurse Center Day 9: Papers We Love - blag Recurse Center Day 8: B Tree Fill Factor (Part 2) - blag Recurse Center Day 7: Basics of ncurses - blag Recurse Center Day 6: B Tree Root - blag Recurse Center First Week - blag Recurse Center Day 5: Garbage Collection Algorithms - blag Recurse Center Day 4: B Tree fill factor - blag Recurse Center Day 3: Hammock Driven Development - blag Recurse Center Day 2: BTree Node - blag Recurse Center Day 1: init - blag What I want to do at Recurse Center - blag Accepted to the Recurse Center! - blag Towards Inserting One Billion Rows in SQLite Under A Minute - blag Marshaling Struct with Special Fields to JSON in Golang - blag I ended up adding duplicate records on a unique index in MongoDB - blag Setting up Github Actions for Hugo - blag Moving to Hugo - blag Catching SIGTERM in Python - blag Git/Github fork-pull request-update cycle - blag Using uWSGI with Python 3 - blag When is my Cake Day? - blag Staying Ahead of Amazon, in Amazon Treasure Hunt Contest - blag How I Am Maintaining Multiple Emails For Git On A Same Machine - blag An exploit on Gaana.com gave me access to their entire User Database - blag Flashing Asus-WRT Merlin by XVortex on NetGear NightHawk R7000 - blag Install Windows 8 UEFI on Legacy BIOS with Clover (and Dual boot with Yosemite) - blag Scraping Javascript page using Python - blag Installing Transmission (remote and CLI) client on Raspberry Pi - blag About - blag Projects - blag
Recurse Center Day 20: Django v4 upgrade (from v1) - blag
2021-12-02 · via blag

I have an open source project (check the screenshots here) that used an outdated version of Django. I had made the last commit five years ago. I set out to upgrade Django to the latest version.

The plan

  1. Get it to run.
  2. Upgrade to Django 2, then 3, and then 4
  3. Ignore backward compatibility of the project. It would help me move fast if I redid the migration if needed.

Getting it to run

My current Python version is 3.9.7, Postgres is v14, and my first task was to get Della running under these versions. I tried to install the dependencies from requirements.txt. The first failure was due to psycopg2:

Error: could not determine PostgreSQL version from ‘14.0’

I assumed this was because the 2.6.2 version did not support the latest Postgres. Installing the latest 2.9.2 version fixed the issue. Similarly, I also upgraded pillow, gevent and Django (to 1.11.29 LTS). These changes were enough to get it running.

Upgrading to v2

I read the release note of v2, but I was unsure how would I make changes in my project because I haven’t seen this code in 5 years, and I remember nothing at all. Fortunately, I found this project called django-upgrade which applied upgrades automatically. So, I ran it on my project:

django-upgrade --target-version 2.2 `find . -name "*.py"`
Rewriting ./della/inbox/models.py
Rewriting ./della/inbox/urls.py
Rewriting ./della/gallery/models.py
Rewriting ./della/gallery/urls.py
Rewriting ./della/urls.py
Rewriting ./della/user_manager/models.py
Rewriting ./della/user_manager/urls.py

One more nice thing about the django-upgrade project is that they nicely mentioned all the breaking changes required. Here are the changes it automatically rewrote:

  1. on_delete argument: Starting with Django 1.9, all foreign key and one to one fields need on_delete argument.
# added_by = models.ForeignKey(User)
added_by = models.ForeignKey(User, on_delete=models.CASCADE)
# user = models.OneToOneField(User)
user = models.OneToOneField(User, on_delete=models.CASCADE)
  1. url to path: Django 2.0 simplified the URL routing syntax. The documentation on path explains how to use them.
url(r'^upload/$', ImageUploadView.as_view(), name='upload'),
url(r'^(?P<pk>\d+)/$', ImageDetailView.as_view(), name='image-detail'),
url(r'^$', ImageListView.as_view(), name='image-list')
url(r'^@(?P<recipient>[a-zA-Z0-9_]+)/$', ThreadDetailView.as_view()

simplified to:

path('upload/', ImageUploadView.as_view(), name='upload'),
path('<int:pk>/', ImageDetailView.as_view(), name='image-detail'),
path('', ImageListView.as_view(), name='image-list')
re_path(r'^@(?P<recipient>[a-zA-Z0-9_]+)/$', ThreadDetailView.as_view()

However, when I tried to migrate, I ran into the following error:

File "/Users/avi/code/della/della/urls.py", line 21, in <module>
    from .views import HomePageView
  File "/Users/avi/code/della/della/views.py", line 3, in <module>
    from della.user_manager.forms import SignupForm
  File "/Users/avi/code/della/della/user_manager/forms.py", line 7, in <module>
    from crispy_forms.helper import FormHelper
  File "/Users/avi/.virtualenvs/della/lib/python3.9/site-packages/crispy_forms/helper.py", line 4, in <module>
    from django.core.urlresolvers import reverse, NoReverseMatch
ModuleNotFoundError: No module named 'django.core.urlresolvers'

I fixed by upgrading django-crispy-forms. The next error was:

File "/Users/avi/code/della/della/urls.py", line 24, in <module>
    path('gallery/', include(
  File "/Users/avi/.virtualenvs/della/lib/python3.9/site-packages/django/urls/conf.py", line 38, in include
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.

It seems it needed application name in the urlconfs. So I added app_name variable to each of the URLconf module. The next error was:

File "/Users/avi/code/della/della/inbox/urls.py", line 3, in <module>
    from .views import (MessageCreateView, ThreadDetailView, ThreadListView,
  File "/Users/avi/code/della/della/inbox/views.py", line 14, in <module>
    from . import tasks
  File "/Users/avi/code/della/della/inbox/tasks.py", line 4, in <module>
    from django.core.urlresolvers import reverse
ModuleNotFoundError: No module named 'django.core.urlresolvers'

Seems they moved reverse and reverse_lazy to django.urls from django.core.urlresolvers. I simply renamed the import statements to fix this. Next error was:

  File "/Users/avi/code/della/della/user_manager/urls.py", line 11, in <module>
    path('login/', auth_views.login, name='login',
AttributeError: module 'django.contrib.auth.views' has no attribute 'login'

In Django 2.2, contrib.auth.views started using class based views. Following changes fixed this error:

urlpatterns = [
    path('login/', auth_views.login, name='login',
        kwargs={'template_name': 'user_manager/login.html'}),
    path('logout/', auth_views.logout, name='logout',
        kwargs={'next_page': '/'}),
    ]

changed to:

urlpatterns = [
    path('login/', auth_views.LoginView.as_view(template_name="user_manager/login.html"), name='login',
        ),
    path('logout/', auth_views.LogoutView, name='logout',
        kwargs={'next_page': '/'}),
    ]

The following error was:

File "/Users/avi/code/della/della/views.py", line 13, in get_context_data
    if self.request.user.is_authenticated():
TypeError: 'bool' object is not callable

Seems User.is_authenticated() was changed to a property in Django 1.10, but django-upgrade did not account for this change. The fix was simple, and now my project started working for Django 2.2.

Upgrading to v3

django-upgrade did not make changes, so I made all changes manually. The first error was:

  File "/Users/avi/.virtualenvs/della/lib/python3.9/site-packages/django/apps/config.py", line 246, in create
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Cannot import 'user_manager'. Check that 'della.user_manager.apps.UserManagerConfig.name' is correct.

It seems Django 3.2 introduced auto discovery of apps, which requires some changes for the app names. I tried changing the config as per docs; it didn’t work. However, I learned that Django made this config optional, so I removed all of them. The following error was:

File "/Users/avi/.virtualenvs/della/lib/python3.9/site-packages/django/template/defaulttags.py", line 1036, in find_library
    raise TemplateSyntaxError(
django.template.exceptions.TemplateSyntaxError: 'staticfiles' is not a registered tag library. Must be one of:
admin_list
admin_modify
admin_urls
cache
crispy_forms_field
crispy_forms_filters
crispy_forms_tags
crispy_forms_utils
i18n
l10n
log
static
tz

The fix was pretty simple, I just renamed staticfiles to static. Now my app started working with Django 3.

Upgrading to v4

At the time of this writing, Django 4.0 RC1 is out, but Django 4.0 will be out in just four days.

Only change required was using the CBV with as_view:

path('logout/', auth_views.LogoutView.as_view(), name='logout')

Update 7/Dec/2021: Django v4 is out and I upgraded from RC1 to 4.0 final. No changes were required.

What’s next?

Della used a significantly older version of django-background-tasks which seems to be unmaintained now. I am looking at alternatives and replacing them.