Gõ chú thích cho các mô hình Django


8

Tôi đang làm việc trong một dự án Django. Vì đây là một dự án mới, tôi muốn nó được chú thích đầy đủ với các chú thích kiểu python 3.6+. Tôi đang cố gắng chú thích các mô hình, nhưng tôi đấu tranh để tìm ra một phương pháp tốt cho điều đó.

Hãy lấy IntegerFieldmột ví dụ. Tôi thấy hai lựa chọn để chú thích nó:

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

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

Số 1 thất bại trong mypy:

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

Số 2 là ổn đối với mypy, nhưng IDE là PyCharm không thể giải quyết nó và thường phàn nàn về các loại sai được sử dụng.

Có cách thực hành tốt nhất nào để chú thích chính xác các mô hình, điều này sẽ thỏa mãn mypy và IDE không?


3
Vì bạn dường như đầu tư nhiều thời gian vào các công cụ thỏa mãn, bạn có thể ngạc nhiên khi biết rằng những gì bạn làm, không phải là chú thích kiểu nào không được thiết kế cho: gõ tĩnh.
Klaus D.

Không phải bạn đang tìm kiếm một cái gì đó như mypy-django ?
Pedram Parsian

Có vẻ như mypy-django không cung cấp chú thích loại cho các mô hình: github.com/machinalis/mypy-django-example/blob/master/polls/iêu
Clément Denoix

@KlausD. - Tôi không chắc là tôi có hiểu bạn nói gì không, bạn có thể nói rõ hơn không?
Djent

Vì vậy, ngay cả khi bạn làm việc này cho IntegerField (), bạn có kế hoạch gì cho trường 50 char? Thật tuyệt khi biết đó là một chuỗi, nhưng thực sự không phải vậy. Tôi sẽ hỏi một câu hỏi ngây thơ, nhưng họ đã có loại. Bạn đang cố gắng chuyển chúng thành các loại cơ bản, có vẻ như với tôi .. chính xác thì bạn muốn giải quyết vấn đề gì? Đây là một vấn đề khá khó khăn ... hãy xem Rust đã đi được bao xa.
Tim Richardson

Câu trả lời:


8

Các mô hình Django (và các thành phần khác) rất khó để chú thích vì có rất nhiều phép thuật đằng sau chúng, tin tốt là một nhóm các nhà phát triển tuyệt vời đã thực hiện công việc khó khăn cho chúng tôi.

django-stub cung cấp một tập hợp các sơ khai và plugin mypy cung cấp các kiểu tĩnh và suy luận kiểu cho Django.

Ví dụ: có mô hình sau:

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 sẽ phàn nàn rằng:

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)

Để khắc phục, nó đủ để cài đặt gói

pip install django-stubs

và tạo một setup.cfgtệp với các mục sau:

[mypy]
plugins =
    mypy_django_plugin.main

strict_optional = True

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

(Đừng quên cập nhật django_settings_moduletheo mô-đun cài đặt của bạn)

Một khi điều này được thực hiện, mypy sẽ có thể suy luận và kiểm tra các chú thích cho các mô hình Django (và các thành phần khác).

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

Dưới đây là một ví dụ về việc sử dụng trong một chế độ xem nhỏ:

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()})

Một lần nữa, mypy hài lòng với các chú thích được cung cấp:

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

Cùng một lưu ý, một gói cho Django Rest Framework cũng có sẵn: djangorestframework-stub .


Tôi thực sự đã tìm thấy điều này, nhưng tôi đã sử dụng nó sai. Cảm ơn bạn đã trả lời chi tiết giúp tôi tiến về phía trước.
Djent
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.