A simpler way to view django projects
able to parse for project name
10 files changed, +274 -11
+22-0sample/manage.py
| @@ -0,0 +1,22 @@ | ||
| 1 | +#!/usr/bin/env python | |
| 2 | +"""Django's command-line utility for administrative tasks.""" | |
| 3 | +import os | |
| 4 | +import sys | |
| 5 | + | |
| 6 | + | |
| 7 | +def main(): | |
| 8 | + """Run administrative tasks.""" | |
| 9 | + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sample.settings') | |
| 10 | + try: | |
| 11 | + from django.core.management import execute_from_command_line | |
| 12 | + except ImportError as exc: | |
| 13 | + raise ImportError( | |
| 14 | + "Couldn't import Django. Are you sure it's installed and " | |
| 15 | + "available on your PYTHONPATH environment variable? Did you " | |
| 16 | + "forget to activate a virtual environment?" | |
| 17 | + ) from exc | |
| 18 | + execute_from_command_line(sys.argv) | |
| 19 | + | |
| 20 | + | |
| 21 | +if __name__ == '__main__': | |
| 22 | + main() |
+0-0sample/sample/__init__.py
No content changes (mode or rename only).
+16-0sample/sample/asgi.py
| @@ -0,0 +1,16 @@ | ||
| 1 | +""" | |
| 2 | +ASGI config for sample project. | |
| 3 | + | |
| 4 | +It exposes the ASGI callable as a module-level variable named ``application``. | |
| 5 | + | |
| 6 | +For more information on this file, see | |
| 7 | +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ | |
| 8 | +""" | |
| 9 | + | |
| 10 | +import os | |
| 11 | + | |
| 12 | +from django.core.asgi import get_asgi_application | |
| 13 | + | |
| 14 | +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sample.settings') | |
| 15 | + | |
| 16 | +application = get_asgi_application() |
+123-0sample/sample/settings.py
| @@ -0,0 +1,123 @@ | ||
| 1 | +""" | |
| 2 | +Django settings for sample project. | |
| 3 | + | |
| 4 | +Generated by 'django-admin startproject' using Django 5.0.6. | |
| 5 | + | |
| 6 | +For more information on this file, see | |
| 7 | +https://docs.djangoproject.com/en/5.0/topics/settings/ | |
| 8 | + | |
| 9 | +For the full list of settings and their values, see | |
| 10 | +https://docs.djangoproject.com/en/5.0/ref/settings/ | |
| 11 | +""" | |
| 12 | + | |
| 13 | +from pathlib import Path | |
| 14 | + | |
| 15 | +# Build paths inside the project like this: BASE_DIR / 'subdir'. | |
| 16 | +BASE_DIR = Path(__file__).resolve().parent.parent | |
| 17 | + | |
| 18 | + | |
| 19 | +# Quick-start development settings - unsuitable for production | |
| 20 | +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ | |
| 21 | + | |
| 22 | +# SECURITY WARNING: keep the secret key used in production secret! | |
| 23 | +SECRET_KEY = 'django-insecure-t7siujt+q594x254t!3cqw)5z_z6^k!6k6qi3)i-v@4ib(-j89' | |
| 24 | + | |
| 25 | +# SECURITY WARNING: don't run with debug turned on in production! | |
| 26 | +DEBUG = True | |
| 27 | + | |
| 28 | +ALLOWED_HOSTS = [] | |
| 29 | + | |
| 30 | + | |
| 31 | +# Application definition | |
| 32 | + | |
| 33 | +INSTALLED_APPS = [ | |
| 34 | + 'django.contrib.admin', | |
| 35 | + 'django.contrib.auth', | |
| 36 | + 'django.contrib.contenttypes', | |
| 37 | + 'django.contrib.sessions', | |
| 38 | + 'django.contrib.messages', | |
| 39 | + 'django.contrib.staticfiles', | |
| 40 | +] | |
| 41 | + | |
| 42 | +MIDDLEWARE = [ | |
| 43 | + 'django.middleware.security.SecurityMiddleware', | |
| 44 | + 'django.contrib.sessions.middleware.SessionMiddleware', | |
| 45 | + 'django.middleware.common.CommonMiddleware', | |
| 46 | + 'django.middleware.csrf.CsrfViewMiddleware', | |
| 47 | + 'django.contrib.auth.middleware.AuthenticationMiddleware', | |
| 48 | + 'django.contrib.messages.middleware.MessageMiddleware', | |
| 49 | + 'django.middleware.clickjacking.XFrameOptionsMiddleware', | |
| 50 | +] | |
| 51 | + | |
| 52 | +ROOT_URLCONF = 'sample.urls' | |
| 53 | + | |
| 54 | +TEMPLATES = [ | |
| 55 | + { | |
| 56 | + 'BACKEND': 'django.template.backends.django.DjangoTemplates', | |
| 57 | + 'DIRS': [], | |
| 58 | + 'APP_DIRS': True, | |
| 59 | + 'OPTIONS': { | |
| 60 | + 'context_processors': [ | |
| 61 | + 'django.template.context_processors.debug', | |
| 62 | + 'django.template.context_processors.request', | |
| 63 | + 'django.contrib.auth.context_processors.auth', | |
| 64 | + 'django.contrib.messages.context_processors.messages', | |
| 65 | + ], | |
| 66 | + }, | |
| 67 | + }, | |
| 68 | +] | |
| 69 | + | |
| 70 | +WSGI_APPLICATION = 'sample.wsgi.application' | |
| 71 | + | |
| 72 | + | |
| 73 | +# Database | |
| 74 | +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases | |
| 75 | + | |
| 76 | +DATABASES = { | |
| 77 | + 'default': { | |
| 78 | + 'ENGINE': 'django.db.backends.sqlite3', | |
| 79 | + 'NAME': BASE_DIR / 'db.sqlite3', | |
| 80 | + } | |
| 81 | +} | |
| 82 | + | |
| 83 | + | |
| 84 | +# Password validation | |
| 85 | +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators | |
| 86 | + | |
| 87 | +AUTH_PASSWORD_VALIDATORS = [ | |
| 88 | + { | |
| 89 | + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | |
| 90 | + }, | |
| 91 | + { | |
| 92 | + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | |
| 93 | + }, | |
| 94 | + { | |
| 95 | + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | |
| 96 | + }, | |
| 97 | + { | |
| 98 | + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | |
| 99 | + }, | |
| 100 | +] | |
| 101 | + | |
| 102 | + | |
| 103 | +# Internationalization | |
| 104 | +# https://docs.djangoproject.com/en/5.0/topics/i18n/ | |
| 105 | + | |
| 106 | +LANGUAGE_CODE = 'en-us' | |
| 107 | + | |
| 108 | +TIME_ZONE = 'UTC' | |
| 109 | + | |
| 110 | +USE_I18N = True | |
| 111 | + | |
| 112 | +USE_TZ = True | |
| 113 | + | |
| 114 | + | |
| 115 | +# Static files (CSS, JavaScript, Images) | |
| 116 | +# https://docs.djangoproject.com/en/5.0/howto/static-files/ | |
| 117 | + | |
| 118 | +STATIC_URL = 'static/' | |
| 119 | + | |
| 120 | +# Default primary key field type | |
| 121 | +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field | |
| 122 | + | |
| 123 | +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' |
+22-0sample/sample/urls.py
| @@ -0,0 +1,22 @@ | ||
| 1 | +""" | |
| 2 | +URL configuration for sample project. | |
| 3 | + | |
| 4 | +The `urlpatterns` list routes URLs to views. For more information please see: | |
| 5 | + https://docs.djangoproject.com/en/5.0/topics/http/urls/ | |
| 6 | +Examples: | |
| 7 | +Function views | |
| 8 | + 1. Add an import: from my_app import views | |
| 9 | + 2. Add a URL to urlpatterns: path('', views.home, name='home') | |
| 10 | +Class-based views | |
| 11 | + 1. Add an import: from other_app.views import Home | |
| 12 | + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') | |
| 13 | +Including another URLconf | |
| 14 | + 1. Import the include() function: from django.urls import include, path | |
| 15 | + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) | |
| 16 | +""" | |
| 17 | +from django.contrib import admin | |
| 18 | +from django.urls import path | |
| 19 | + | |
| 20 | +urlpatterns = [ | |
| 21 | + path('admin/', admin.site.urls), | |
| 22 | +] |
+16-0sample/sample/wsgi.py
| @@ -0,0 +1,16 @@ | ||
| 1 | +""" | |
| 2 | +WSGI config for sample project. | |
| 3 | + | |
| 4 | +It exposes the WSGI callable as a module-level variable named ``application``. | |
| 5 | + | |
| 6 | +For more information on this file, see | |
| 7 | +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ | |
| 8 | +""" | |
| 9 | + | |
| 10 | +import os | |
| 11 | + | |
| 12 | +from django.core.wsgi import get_wsgi_application | |
| 13 | + | |
| 14 | +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sample.settings') | |
| 15 | + | |
| 16 | +application = get_wsgi_application() |
+6-3src/context.ts
| @@ -4,6 +4,9 @@ import * as fs from "fs"; | ||
| 4 | 4 | |
| 5 | 5 | export const setDjangoContext = async () => { |
| 6 | 6 | const workspaceFolders = vscode.workspace.workspaceFolders; |
| 7 | + if (vscode.workspace.getConfiguration("django-overview").get("projectDir")) { | |
| 8 | + return; | |
| 9 | + } | |
| 7 | 10 | if (workspaceFolders) { |
| 8 | 11 | for (const folder of workspaceFolders) { |
| 9 | 12 | const dir = folder.uri.fsPath; |
| @@ -45,10 +48,10 @@ const isInDjangoProject = async (dir: string): Promise<boolean> => { | ||
| 45 | 48 | return isInDjangoProject(parentDir); |
| 46 | 49 | }; |
| 47 | 50 | |
| 48 | -export const getDjangoProjectDir = () => { | |
| 51 | +export const getDjangoProjectDir = (): string | undefined => { | |
| 49 | 52 | return vscode.workspace.getConfiguration("django-overview").get("projectDir"); |
| 50 | 53 | }; |
| 51 | 54 | |
| 52 | -export const settingsFiles = () => { | |
| 53 | - const projectDir = getDjangoProjectDir(); | |
| 55 | +export const getSkipDirs = () => { | |
| 56 | + return vscode.workspace.getConfiguration("django-overview").get("skipDirs"); | |
| 54 | 57 | }; |
+55-0src/project.ts
| @@ -0,0 +1,55 @@ | ||
| 1 | +import * as childProcess from "child_process"; | |
| 2 | +import { getDjangoProjectDir } from "./context"; | |
| 3 | +import * as fs from "fs"; | |
| 4 | +import { promisify } from "util"; | |
| 5 | +import regex from "./regex"; | |
| 6 | + | |
| 7 | +type Field = { | |
| 8 | + name: string; | |
| 9 | + type: string; | |
| 10 | + required: boolean; | |
| 11 | + unique: boolean; | |
| 12 | + default: string; | |
| 13 | + max_length: number; | |
| 14 | + choices: [string]; | |
| 15 | +}; | |
| 16 | + | |
| 17 | +type Model = { | |
| 18 | + name: string; | |
| 19 | + fields: [Field]; | |
| 20 | +}; | |
| 21 | + | |
| 22 | +type App = { | |
| 23 | + name: string; | |
| 24 | + // path: string; | |
| 25 | + // urls: [string]; | |
| 26 | + // models: [{string: Model}]; | |
| 27 | +}; | |
| 28 | + | |
| 29 | +type Project = { | |
| 30 | + name: string; | |
| 31 | +}; | |
| 32 | + | |
| 33 | +const readFile = promisify(fs.readFile); | |
| 34 | + | |
| 35 | +export default class DjangoProject { | |
| 36 | + projectDir?: string; | |
| 37 | + name?: string; | |
| 38 | + | |
| 39 | + constructor(rootDir: string) { | |
| 40 | + this.projectDir = rootDir; | |
| 41 | + } | |
| 42 | + | |
| 43 | + async parseManagePy() { | |
| 44 | + const managePyPath = `${this.projectDir}/manage.py`; | |
| 45 | + const text = await readFile(managePyPath, "utf-8"); | |
| 46 | + const match = text.match(regex.projectName); | |
| 47 | + this.name = match ? match[1] : undefined; | |
| 48 | + } | |
| 49 | +} | |
| 50 | + | |
| 51 | +export const getProject = async () => {}; | |
| 52 | + | |
| 53 | +export const getAvailableApps = async () => { | |
| 54 | + const projectDir = getDjangoProjectDir(); | |
| 55 | +}; |
+3-0src/regex.ts
| @@ -0,0 +1,3 @@ | ||
| 1 | +export default { | |
| 2 | + projectName: /([^']+?)\.settings/, | |
| 3 | +}; |
+11-8src/test/extension.test.ts
| @@ -1,15 +1,18 @@ | ||
| 1 | -import * as assert from 'assert'; | |
| 1 | +import * as assert from "assert"; | |
| 2 | 2 | |
| 3 | 3 | // You can import and use all API from the 'vscode' module |
| 4 | 4 | // as well as import your extension to test it |
| 5 | -import * as vscode from 'vscode'; | |
| 5 | +import * as vscode from "vscode"; | |
| 6 | +import DjangoProject from "../project"; | |
| 6 | 7 | // import * as myExtension from '../../extension'; |
| 7 | 8 | |
| 8 | -suite('Extension Test Suite', () => { | |
| 9 | - vscode.window.showInformationMessage('Start all tests.'); | |
| 9 | +suite("Extension Test Suite", () => { | |
| 10 | + vscode.window.showInformationMessage("Start all tests."); | |
| 10 | 11 | |
| 11 | - test('Sample test', () => { | |
| 12 | - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); | |
| 13 | - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); | |
| 14 | - }); | |
| 12 | + test("Get project.", async () => { | |
| 13 | + console.log("HELLO"); | |
| 14 | + const project = new DjangoProject("sample"); | |
| 15 | + await project.parseManagePy(); | |
| 16 | + console.log(project); | |
| 17 | + }); | |
| 15 | 18 | }); |