Geben Sie Anmerkungen für Django-Modelle ein

8

Ich arbeite an einem Django-Projekt. Da dies ein neues Projekt ist, möchte ich, dass es vollständig mit Anmerkungen vom Typ Python 3.6+ kommentiert wird. Ich versuche, Modelle zu kommentieren, aber ich habe Mühe, eine gute Methode dafür zu finden.

Nehmen wir das IntegerFieldals Beispiel. Ich sehe zwei Möglichkeiten, um es zu kommentieren:

# number 1
int_field: int = models.IntegerField()

# number 2
int_field: models.IntegerField = models.IntegerField()

Nummer 1 schlägt in mypy fehl:

Incompatible types in assignment (expression has type "IntegerField[<nothing>, <nothing>]", variable has type "int")

Nummer 2 ist für mypy in Ordnung, aber IDEs wie PyCharm können es nicht lösen und beschweren sich häufig über falsche Typen.

Gibt es Best Practices, um die Modelle korrekt zu kommentieren, die mypy und IDEs erfüllen?

Djent
quelle
3
Da Sie anscheinend viel Zeit in zufriedenstellende Tools investieren, werden Sie überrascht sein zu hören, dass das, was Sie tun, nicht das ist, wofür Typanmerkungen nicht ausgelegt sind: statische Typisierung.
Klaus D.
Suchst du nicht so etwas wie Mypy-Django ?
Pedram Parsian
Es sieht so aus, als ob mypy-django keine Typanmerkungen für Modelle anbietet: github.com/machinalis/mypy-django-example/blob/master/polls/…
Clément Denoix
@KlausD. - Ich bin mir nicht sicher, ob ich verstehe, was Sie sagen. Können Sie das näher erläutern?
Djent
Also, selbst wenn Sie dies für IntegerField () ausarbeiten, was planen Sie für ein Feld mit 50 Zeichen? Es ist schön zu wissen, dass das eine Art Saite ist, aber es ist nicht wirklich so. Ich werde eine naive Frage stellen, aber sie haben bereits Typen. Sie versuchen, sie in grundlegende Typen umzuwandeln, scheint mir. Welches Problem möchten Sie genau lösen? Es ist ein ziemlich schweres Problem ... sehen Sie, wie weit Rust damit gekommen ist.
Tim Richardson

Antworten:

8

Django-Modelle (und andere Komponenten) sind schwer zu kommentieren, da viel Magie dahinter steckt. Eine gute Nachricht ist, dass eine Gruppe cooler Entwickler bereits die harte Arbeit für uns geleistet hat.

django-stubs bietet eine Reihe von Stubs und mypy-Plugins, die statische Typen und Typinferenzen für Django bereitstellen.

Zum Beispiel mit folgendem Modell:

from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()

class Post(models.Model):
    title = models.CharField(max_length=255)
    pubdate = models.DateTimeField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)

mypy würde sich beschweren und sagen:

demo$ mypy .
demo/models.py:9: error: Need type annotation for 'title'
demo/models.py:10: error: Need type annotation for 'pubdate'
demo/models.py:11: error: Need type annotation for 'author'
Found 3 errors in 1 file (checked 5 source files)

Um das Problem zu beheben, reicht es aus, das Paket zu installieren

pip install django-stubs

und erstellen Sie eine setup.cfgDatei mit den folgenden Angaben:

[mypy]
plugins =
    mypy_django_plugin.main

strict_optional = True

[mypy.plugins.django-stubs]
django_settings_module = demo.settings

(Vergessen Sie nicht, django_settings_moduleentsprechend Ihrem Einstellungsmodul zu aktualisieren )

Sobald dies erledigt ist, kann mypy Anmerkungen für Django-Modelle (und andere Komponenten) ableiten und überprüfen.

demo$ mypy .
Success: no issues found in 5 source files

Hier ist ein Beispiel für die Verwendung in einer kleinen Ansicht:

from django.db.models.query import QuerySet
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render

from demo.models import Post

def _get_posts() -> 'QuerySet[Post]':
    return Post.objects.all()

def posts(request: HttpRequest, template: str='posts.html') -> HttpResponse:
    return render(request, template, {'posts': _get_posts()})

Wieder einmal ist mypy mit den bereitgestellten Anmerkungen zufrieden:

demo$ mypy .
Success: no issues found in 7 source files

Aus dem gleichen Grund ist auch ein Paket für Django Rest Framework verfügbar: djangorestframework-stubs .

Fehler
quelle
Ich habe das tatsächlich gefunden, aber ich habe es falsch verwendet. Vielen Dank für die ausführliche Antwort, die mir geholfen hat, weiterzukommen.
Djent