From 5334a80c9b1e3c90852b1c66a7a2eae7536983dc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 1 Aug 2022 18:39:14 -0500 Subject: [PATCH] docs(README): Fix indentation in list and examples (#1083) Run examples through black for uniformity, link `HttpModel` --- README.md | 67 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index a392f80..290aa80 100644 --- a/README.md +++ b/README.md @@ -100,37 +100,40 @@ This happens because these Django classes do not support [`__class_getitem__`](h 1. You can go with our [`django_stubs_ext`](https://github.com/typeddjango/django-stubs/tree/master/django_stubs_ext) helper, that patches all the types we use as Generic in django. -Install it: + Install it: -```bash -pip install django-stubs-ext # as a production dependency -``` + ```bash + pip install django-stubs-ext # as a production dependency + ``` -And then place in your top-level settings: + And then place in your top-level settings: -```python -import django_stubs_ext + ```python + import django_stubs_ext + + django_stubs_ext.monkeypatch() + ``` -django_stubs_ext.monkeypatch() -``` - -Note: This monkey patching approach will only work when using Python 3.7 and higher, when the `__class_getitem__` magic method was introduced. + Note: This monkey patching approach will only work when using Python 3.7 and higher, when the `__class_getitem__` magic method was introduced. 2. You can use strings instead: `'QuerySet[MyModel]'` and `'Manager[MyModel]'`, this way it will work as a type for `mypy` and as a regular `str` in runtime. ### How can I create a HttpRequest that's guaranteed to have an authenticated user? -Django's built in `HttpRequest` has the attribute `user` that resolves to the type +Django's built in [`HttpRequest`](https://docs.djangoproject.com/en/4.0/ref/request-response/#django.http.HttpRequest) has the attribute `user` that resolves to the type + ```python Union[User, AnonymousUser] ``` where `User` is the user model specified by the `AUTH_USER_MODEL` setting. If you want a `HttpRequest` that you can type-annotate with where you know that the user is authenticated you can subclass the normal `HttpRequest` class like so: + ```python from django.http import HttpRequest from my_user_app.models import MyUser + class AuthenticatedHttpRequest(HttpRequest): user: MyUser ``` @@ -150,15 +153,17 @@ Example: from django.db import models class MyModelQuerySet(models.QuerySet): - pass + pass + class MyModel(models.Model): - bar = models.IntegerField() - objects = MyModelQuerySet.as_manager() + bar = models.IntegerField() + objects = MyModelQuerySet.as_manager() + def use_my_model(): - foo = MyModel.objects.get(id=1) # This is `Any` but it should be `MyModel` - return foo.xyz # No error, but there should be + foo = MyModel.objects.get(id=1) # This is `Any` but it should be `MyModel` + return foo.xyz # No error, but there should be ``` There is a workaround: use `Manager.from_queryset` instead. @@ -168,18 +173,22 @@ Example: ```python from django.db import models + class MyModelQuerySet(models.QuerySet): - pass + pass + MyModelManager = models.Manager.from_queryset(MyModelQuerySet) + class MyModel(models.Model): - bar = models.IntegerField() - objects = MyModelManager() + bar = models.IntegerField() + objects = MyModelManager() + def use_my_model(): - foo = MyModel.objects.get(id=1) - return foo.xyz # Gives an error + foo = MyModel.objects.get(id=1) + return foo.xyz # Gives an error ``` ### How do I annotate cases where I called QuerySet.annotate? @@ -203,23 +212,29 @@ from django_stubs_ext import WithAnnotations from django.db import models from django.db.models.expressions import Value + class MyModel(models.Model): username = models.CharField(max_length=100) def func(m: WithAnnotations[MyModel]) -> str: - return m.asdf # OK, since the model is annotated as allowing any attribute + return m.asdf # OK, since the model is annotated as allowing any attribute + func(MyModel.objects.annotate(foo=Value("")).get(id=1)) # OK -func(MyModel.objects.get(id=1)) # Error, since this model will not allow access to any attribute +func( + MyModel.objects.get(id=1) +) # Error, since this model will not allow access to any attribute class MyTypedDict(TypedDict): foo: str + def func2(m: WithAnnotations[MyModel, MyTypedDict]) -> str: - print(m.bar) # Error, since field "bar" is not in MyModel or MyTypedDict. - return m.foo # OK, since we said field "foo" was allowed + print(m.bar) # Error, since field "bar" is not in MyModel or MyTypedDict. + return m.foo # OK, since we said field "foo" was allowed + func(MyModel.objects.annotate(foo=Value("")).get(id=1)) # OK func(MyModel.objects.annotate(bar=Value("")).get(id=1)) # Error