django-stubs: Django 3.1 JSONField is missing

Bug report

What’s wrong

Django 3.1 adds a generic models.JSONField and fields.JSONField to replace the PostgreSQL-only versions: https://docs.djangoproject.com/en/3.1/releases/3.1/#jsonfield-for-all-supported-database-backends

Attempting to use these new fields results in error: Module has no attribute "JSONField"

How is that should be

Type definitions should exist for the new imports. These can probably just be copied from the existing PostgreSQL versions.

System information

  • OS:
  • python version: 3.8.5
  • django version: 3.1
  • mypy version: 0.770
  • django-stubs version: 1.5.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 33
  • Comments: 25 (15 by maintainers)

Commits related to this issue

Most upvoted comments

@niksubramanian Hello! Me and @sobolevn actually worked out a plan of making it work. We plan to divide stub files into separate repositories, as there is no simple solution to support various Django versions. It’ll be done as soon as I finish my refactor, which lingers in time due to my excess of responsibilities. I’ll get back to this, promise.

One way I have seen it done in other projects with similar constraints is to branch into two versions. 1.x could continue supporting the current versions while 2.x would support Django 3.1, and changes that apply to both can be backported to the 1.x branch.

An approach that is even easier to understand is to release versions that match the Django major and minor versions, with patch versions that follow incrementally from changes in django-stubs.

For example, the first version of django-stubs with Django 3.1 support would be 3.1.0. If any changes are done to it, then release 3.1.1, and so on. If any of those changes apply to previous versions, release them as 3.0.(n+1) and 2.2.(n+1) too.

The nice thing about this project is that most of the changes consist of declarations, which are relatively easy to backport. The main branch in any case should thus reflect the code for the highest supported version of Django, with separate branches supporting the previous versions.

I experienced this bug when upgrading a project from Django 2.2 to Django 3.1 and I want to share my feelings and feedback.

I don’t want to sound harsh but this makes me regret adding django-stubs and mypy to the project I’m working on, I wouldn’t have done it if I had known about this beforehand. It’s a project with several other programmers, with varying degrees of experience with Python, Django and MyPy, so I try to make the development experience as smooth as possible. Now if they use some Django 3.0 or 3.1-specific features such as JSONField they will see MyPy errors (that will need to be addressed as they are part of our pre-commit checks) and scratch their heads wondering where their mistake lies, when it’s not their fault. I think that is an important loss in productivity that should be addressed.

I like @federicobond’s idea of versioning the stubs to match the supported Django version, and backporting changes as necessary. However I recognize that might bee too cumbersome to maintain. In that case I like @kszmigiel’s idea of having two branches:

  • lts or legacy branch to support LTS Django (2.2 currently).
  • master to support latest Django (3.1 currently).

I think the two-branch approach would cover all bases except users not on Django LTS and not on latest Django version. In my opinion those users could just pin django-stubs version to avoid upgrading until they upgrade Django.

Last comment was from October, can someone please give an update on whether this issue will be fixed or not, and if there is something I can do to help it get done?

Thank you for all your work on django-stubs.

Closing because JSONField was added in #467 and some fixes added in #558.

The problem of splitting types between Django versions is still unresolved, unfortunately, but it’s a known problem and I’ve discussed it recently with @sobolevn .

@kszmigiel awesome! Thanks so much for all the hard work you’re putting in the library - it has saved us countless hours of bug hunting, so it’s very much appreciated.

@kszmigiel let’s discuss this tomorrow!

Plugin is not bound to django version. Stubs are. We with @kszmigiel also think that moving our plugin to a separate repo is a good idea.

An approach that is even easier to understand is to release versions that match the Django major and minor versions, with patch versions that follow incrementally from changes in django-stubs.

For example, the first version of django-stubs with Django 3.1 support would be 3.1.0. If any changes are done to it, then release 3.1.1, and so on. If any of those changes apply to previous versions, release them as 3.0.(n+1) and 2.2.(n+1) too.

That’s basically the pattern used by the TypeScript definitions in https://github.com/DefinitelyTyped/DefinitelyTyped, and it works well.

This is not that easy. Because we still don’t know how to support multiple versions of django types in a single codebase. Because versions <3.1 should not have these types.

What would be the impact of having the types available on <3.1? It seems like any code attempting to use the new fields would fail before type checking even came into play. If the types were changing in a backwards incompatible way, then it would be a problem, but I don’t see what would break by making types available for things that just don’t exist in older versions.