Non-Django issues during a Django upgrade
Upgrading from Django 3.0.9 to 3.1 was a breeze.
To be fair upgrading Django is usually a breeze. The exhausive release notes written every time a new version is rolled out is a defining factor here.
What do I mean when I say “a breeze”? I compare Django “upgrades” to something like upgrading a Python 2 codebase to Python 3 😬
So, upgrades being a breeze, why write a post about this topic?
Because a Django application usually does not comprise only of the Django package.
How I upgraded
This section basically is about “how I usually upgrade”.
Made specific for this
requirements.txtfile. I.e. changed entry from
pip install -r requirements.txtwith the updated
requirementsfile. Among the command’s output I spotted:
Installing collected packages: Django Found existing installation: Django 3.0.9 Uninstalling Django-3.0.9: Successfully uninstalled Django-3.0.9 Successfully installed Django-3.1
This yielded several warnings of the type:
$ ./manage.py check System check identified some issues: WARNINGS: app_name.Model.field_name: (fields.W904) django.contrib.postgres.fields.JSONField is deprecated. Support for it (except in historical migrations) will be removed in Django 4.0. HINT: Use django.db.models.JSONField instead. ... System check identified 3 issues (0 silenced).
Hence I search/replaced any instances of
from django.contrib.postgres.fields import JSONField
from django.db.models import JSONField
./manage.py checkagain. Got this output:
System check identified no issues (0 silenced)
- In order to keep the Django models code and database state in sync, I ran
./manage.py makemigrations appname -n move_to_django_jsonfield
Done this for each app containing a
This resulted in
AlterField statements for the models/fields whose
JSONField type was updated:
migrations.AlterField( model_name='mymodel', name='myfield', field=models.JSONField(), ),
- Ran tests.
Oh noes! An external Python packages I use only when running tests,
django_bakery, does not like Django
3.1. I got this exception:
TypeError: <class 'django.db.models.fields.json.JSONField'> is not supported by baker.
Non-Django issue and what I did about it
The Django application itself works without error. Unit tests that rely on the Django 3.1
JSONField fail. Because the model_bakery package does not support the newly added
First thought: Am I running the latest package?
The below command didn’t install a new version.
pip install model_bakery -U
So I have the latest.
Second thought: So is this an opportunity for me to write a PR? Finally make a decent contribution to a package I really like? To an opensource project which has given me so much?
Not so fast 😊
I navigated to the pacakge’s github repo and looked for the text
JSONField within the closed PRs. And indeed:
So the question now is: How do I get to use the package with this commit in my project?
Pinning a github project to a specific commit
This StackOverflow answer presents various ways of achieving this.
model_bakery requirements file entry I had looked like:
whereas now I have:
I ran into an error when trying to install the package above while rolling out a Docker container for local Django development:
Collecting git+ssh://****@github.com/model-bakers/model_bakery.git@2dada1f51a3d08bbec7cd8be9da0b103581dc392 (from -r requirements/local.txt (line 9)) Cloning ssh://****@github.com/model-bakers/model_bakery.git (to revision 2dada1f51a3d08bbec7cd8be9da0b103581dc392) to /tmp/pip-req-build-zi5byz4k Running command git clone -q 'ssh://****@github.com/model-bakers/model_bakery.git' /tmp/pip-req-build-zi5byz4k Host key verification failed. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. ERROR: Command errored out with exit status 128: git clone -q 'ssh://****@github.com/model-bakers/model_bakery.git' /tmp/pip-req-build-zi5byz4k Check the logs for full command output.
Why this error? Because on the Docker container I do not have git set up and configured with a Github user account.
To resolve this I changed the way the repo commit is pinned. The format I’m using does not need
pip to rely on
git. In fact it relies only on
I.e. the format now is:
This works across all environments, i.e.:
- when installing the package on its own using
pip install [https path to package zip]
pip install -r requirements.txtin my local terminal
pip install -r requirements.txtinside the Docker container
How to get that zip file URL?
Navigate to the commit’s URL on github. In this case it’s:
Code button, and copy the link address for the
Download ZIP option:
What I did is not best practice. Far from it. But I only use
model_bakery package when running unit tests. I’m OK with taking that sort of risk with a package that does not “run” in production. I’m willing to accept that risk.
I find Django a very stable framework. But no open source project can guarantee “zero hiccups” for the whole ecosystem around it.
The approach I’ve taken above is a compromise between:
- the stability of a mature framework like Django, and
- utilising the rich ecosystem around it
Any thoughts? Should I have done it another way? Did I ignore any risks?