microsoft / pylance-release

Documentation and issues for Pylance
Creative Commons Attribution 4.0 International
1.69k stars 768 forks source link

Provide improved support for django #3701

Open rchiodo opened 1 year ago

rchiodo commented 1 year ago

MVP idea:

MVP Python Core?

diego351 commented 1 year ago
  1. Ability to run task of the manage.py utility
  2. Ability to goto definition models referenced by string by'<app_name>.<model_name>'when model sits in '<app_name>.models.<model_name>'
rchiodo commented 1 year ago

Manage.py could

All of these are probably better suited for the core python extension though. Not really language server related. See this documentation: https://code.visualstudio.com/docs/python/tutorial-django#_create-a-debugger-launch-profile

Which could be improved, but probably better to do that in the python extension.

rchiodo commented 1 year ago

Views.py

def index(request):
   pass

becomes

def index(request: HttpRequest) -> HttpResponse:
   pass

automatically (line completions maybe?)

rchiodo commented 1 year ago

Urls.py

rchiodo commented 1 year ago

https://github.com/microsoft/pylance-release/issues/3704

rchiodo commented 1 year ago

Fields with required values should flag an error if those values are missing. Example:

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField()
    votes = models.IntegerField(default=0)

choice_text is missing max_length

rchiodo commented 1 year ago

What @diego351 said in this issue: #3700

Settings.py basically takes a list of modules. It would be nice if they could be treated that way when entering them.

Like by doing

rchiodo commented 1 year ago

Could completions for models be driven by the data in the 'migrations' folder?

diego351 commented 1 year ago

@rchiodo It's actually interesting how Jetbrains inferes that. Might do some tests.

btw, @rchiodo do you get notifications for closed issues?

rchiodo commented 1 year ago

btw, @rchiodo do you get notifications for closed issues?

Only if I had already responded to the item or you mention me by github id.

Is there another item we already closed that's about this topic?

diego351 commented 1 year ago

@rchiodo Not about that topic, but don't know how to contact you another way, didn't wanted to create duplicate ticket https://github.com/microsoft/pylance-release/issues/3678

diego351 commented 1 year ago
  "python.analysis.packageIndexDepths": [
    {
      "name": "django",
      "depth": 3,
      "includeAllSymbols": true
    },
    {
      "name": "rest_framework",
      "depth": 3,
      "includeAllSymbols": true
    }
]

Just this regular django setup hits Workspace indexing has hit its upper limit: 2000 files. In production it's much more needed. We need https://github.com/microsoft/pylance-release/discussions/2608 to make vscode competitive django IDE.

debonte commented 1 year ago

Created an issue to think about whether dataclass_transform can help with Django models: https://github.com/microsoft/pylance-release/issues/3720

rchiodo commented 1 year ago

Some ideas from the work done here: https://youtu.be/Lz4I7rFmFdY?t=1233

Generate type stubs on the fly for django classes

rchiodo commented 1 year ago

At this point in the video you can see the presenter use what @diego351 talked about in #3704

rchiodo commented 1 year ago

Comment here makes it seem like Django functions have data automatically sent to them (like pytest fixtures): https://github.com/microsoft/pylance-release/discussions/3187#discussioncomment-3421854

Type inference would be specific to Django I'd think. Much like pytest fixtures. Needs more investigation to see how this works.

rchiodo commented 1 year ago

https://github.com/microsoft/pylance-release/issues/3704#issuecomment-1335592027

Looking here: https://reinout.vanrees.org/weblog/2015/06/03/05-lookups-transforms-expressions.html

Shows that Django completions for parameter names can include a LOT of stuff. It would be cool to include at least some of these (if not all) in completions for parameters. (much like Pycharm does)

rchiodo commented 1 year ago

An example of why the 'generated' keys are useful.

Suppose we have these two models (from the Django tutorial):

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

Both of these objects have hidden (generated) fields.

Example usage:

q = Question.objects.get(pk=1)
q.choice_set.create(choice_text='Not Much', votes=0)

In this example, pylance would have to know

rchiodo commented 1 year ago

Another idea: Query pattern matching.

Urls might have something like so:

urlpatterns = [
    path("", views.index, name="index"),
    path("<int:question_id>/", views.detail, name='detail'),
    path("<int:question_id>/results", views.results, name='results'),
    path("<int:question_id>/vote", views.vote, name='vote'),
]

See here for more information: https://docs.djangoproject.com/en/4.1/topics/i18n/translation/#translating-url-patterns

It might be possible to have a general regular expression support? Doesn't seem to be asked for, but maybe as a separate extension. Patterned after what regex101.com does.

rchiodo commented 1 year ago

Another obvious example, intellisense in Django templates. This would likely require an entirely different parser.

Yeah definitely. Django's template language is not python.

Example, this is how you concat two strings:

{{ str_1|add:str2 }}
rchiodo commented 1 year ago

There are predefined globals that can be set that have special meaning.

It would be nice if they:

Example - a Urls.py:

from django.urls import path
from . import views

app_name = 'polls'

urlpatterns = [
    path("", views.index, name="index"),
    path("<int:question_id>/", views.detail, name='detail'),
    path("<int:question_id>/results", views.results, name='results'),
    path("<int:question_id>/vote", views.vote, name='vote'),
]

app_name and urlpatterns are globals that django looks for.

https://docs.djangoproject.com/en/4.1/topics/http/urls/#how-django-processes-a-request

rchiodo commented 1 year ago

Warning in forms that don't use the csrf_token tag

rchiodo commented 1 year ago

@diego351, @luabud pointed this extension out to me:

https://marketplace.visualstudio.com/items?itemName=tonybaloney.python-task-provider

That provides commands for manage.py. Thought that might be useful for you.

diego351 commented 1 year ago

Thanks! How the initial support is going? Please let me know if you need anything django related

rchiodo commented 1 year ago

@diego351 Honestly, we're still in the investigation phase, trying to figure out what to do first. Any more suggestions of things that you'd like to see or any other features you've seen elsewhere would be a big help. Thanks for asking.

rchiodo commented 1 year ago

Another idea: https://github.com/microsoft/pylance-release/issues/3874#issuecomment-1405665334

Supporting other languages inside of strings. Might also how we implement DTL support. Ship a separate language server just for the DTL parts.

dakotahorstman commented 1 year ago

@rchiodo Perhaps off-topic, but intellisense for the django.conf.settings object, which includes user settings.py variables would also be phenomenal.

rchiodo commented 1 year ago
  1. Ability to run task of the manage.py utility
  2. Ability to goto definition models referenced by string by'<app_name>.<model_name>'when model sits in '<app_name>.models.<model_name>'

@dakotahorstman do you mean like option 2 that @diego351 mentioned?

dakotahorstman commented 1 year ago

Albeit, I split my settings.py out into multiple settings/*.py files depending on which mode my server is running in. For example: settings/base.py, settings/dev.py, settings/prod.py, settings/test.py if that makes much of a difference.

dakotahorstman commented 1 year ago

@rchiodo I mean all settings, not just model definitions. Like regular intellisense, if I were to type settings., it would suggest DEBUG, INSTALLED_APPS, DATABASES, etc.

rchiodo commented 1 year ago

@dakotahorstman can you share your source? It would help to have an example.

dakotahorstman commented 1 year ago

@rchiodo Unfortunately, I can't due to it being a closed-source application. The most bare-bones Django project can be used though. Here's a screenshot of my application's structure if it's any benefit: image

settings/local.py and settings/production.py import everything from settings/base.py where all shared settings exist (like INSTALLED_APPS or DATABASES)

All my request is, if I import from django.conf import settings in networking.py, intellisense should suggest all of the module-level variables that exist in these settings/*.py files. For example, if settings/base.py has a FOO="bar" variable, intellisense will suggest FOO when I type settings. in networking.py. Think of the behavior being no different if I were to import from dtautomation.settings import base as settings and did the same thing.

I can try to provide a GIF if that would be more beneficial?

rchiodo commented 1 year ago

If I'm understanding correctly, I'm not sure why those variables are not already visible as completions?

Example:

file: test.py

import test2
test2.b

file test2.py

b = list()

Completions when in test.py do show test2.b

image

rchiodo commented 1 year ago

Oh no wait I see what you mean. You want the 'settings' object from django to dynamically have these other 'settings' on it.

dakotahorstman commented 1 year ago

@rchiodo Exactly, yes! Plus the ones Django already ships with if possible.

rchiodo commented 1 year ago

More Feedback

rchiodo commented 1 year ago

Solution Ideas for previous comment:

Query list completions

Being able to see object tables

Snippets for django related stuff

Django debug toolbar

Show more information about models and other classes

Tables are hard to make in html

Data sent to view is hard to get correct

debonte commented 1 year ago

Related issue where we could provide IntelliSense (similar to pytest extension) where all of the model's attributes are mapped to kwargs -- https://github.com/microsoft/pylance-release/issues/4370

Viicos commented 8 months ago

Mergeable type stubs and generating dynamic fields for models

For anyone interested, I started django-autotyping, which can generate dynamic stubs based on the current application (providing support for foreign field set and get types, and later support for lookup queries, etc).

This article goes into more detail.

ldeluigi commented 7 months ago

Has anyone mentioned support for the auto-generated "id" field?

rchiodo commented 7 months ago

Has anyone mentioned support for the auto-generated "id" field?

I don't believe the 'id' field is mentioned explicitly but it generally follows under this item: https://github.com/microsoft/pylance-release/issues/3704. I believe @Viicos work on autotyping would be relevant too. We're discussing doing something similar to what @Viicos has done but generating the type stubs inside of pylance as you type in your code.

Viicos commented 7 months ago

We're discussing doing something similar to what @Viicos has done but generating the type stubs inside of pylance as you type in your code.

Nice to hear your are also planning on exploring this solution. I did face some challenges though, do not hesitate to let me know if you want to hear more details about it