├── autoload ├── django.vim └── django │ ├── templates.vim │ ├── utils.vim │ ├── commands.vim │ ├── plugins.vim │ ├── apps.vim │ ├── project.vim │ └── completions.vim ├── nerdtree_plugin └── django.vim ├── ftplugin └── python.vim ├── plugin └── django.vim ├── README.markdown └── doc └── vim-django.txt /autoload/django.vim: -------------------------------------------------------------------------------- 1 | function! django#is_active(...) abort 2 | return exists('g:django_project_name') && exists('g:django_project_directory') 3 | endfunction 4 | -------------------------------------------------------------------------------- /autoload/django/templates.vim: -------------------------------------------------------------------------------- 1 | function! django#templates#find(name) 2 | let file_regex = '**/templates/'.a:name 3 | let possible_paths = split(globpath(g:django_project_directory, file_regex)) 4 | return possible_paths 5 | endfunction 6 | -------------------------------------------------------------------------------- /autoload/django/utils.vim: -------------------------------------------------------------------------------- 1 | function! django#utils#vim_open(file, open_as) 2 | if a:open_as is 'tab' 3 | exec 'tabnew '.a:file 4 | elseif a:open_as is 'vsplit' 5 | exec 'vsplit '.a:file 6 | elseif a:open_as is 'split' 7 | exec 'split'.a:file 8 | endif 9 | endfunction 10 | -------------------------------------------------------------------------------- /autoload/django/commands.vim: -------------------------------------------------------------------------------- 1 | function! django#commands#manage(command, ...) 2 | let file_regex = '**/manage.py' 3 | let manage = split(globpath(g:django_project_directory, file_regex))[0] 4 | execute '!python '.manage.' '.a:command 5 | endfunction 6 | 7 | function! django#commands#admin(command, ...) 8 | execute '! django-admin.py '. a:command 9 | endfunction 10 | -------------------------------------------------------------------------------- /nerdtree_plugin/django.vim: -------------------------------------------------------------------------------- 1 | if exists('g:django_nerdtree_plugin_loaded') 2 | finish 3 | endif 4 | let g:django_nerdtree_plugin_loaded = 1 5 | 6 | 7 | call NERDTreeAddMenuSeparator() 8 | 9 | call NERDTreeAddMenuItem({ 10 | \ 'text': 'd(j)ango app', 11 | \ 'shortcut': 'j', 12 | \ 'callback': 'django#plugins#nerdtree_create', 13 | \ 'isActiveCallback': 'django#is_active' }) 14 | -------------------------------------------------------------------------------- /autoload/django/plugins.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_nerd_tree') 2 | function! django#plugins#nerdtree_create() 3 | let curDirNode = g:NERDTreeDirNode.GetSelected() 4 | 5 | let newDjangoName = input("Add a django-app\n". 6 | \ "==========================================================\n". 7 | \ "Enter the django-app name to be created. \n". 8 | \ "==> ") 9 | 10 | exec 'chdir ' . curDirNode.path.str() 11 | call django#commands#manage('startapp '.newDjangoName) 12 | endfunction 13 | endif 14 | -------------------------------------------------------------------------------- /ftplugin/python.vim: -------------------------------------------------------------------------------- 1 | function! s:CreateRelatedMappingsPerFile(filename) 2 | let methods = ['tab', 'vsplit', 'split'] 3 | 4 | for method in methods 5 | execute 'nmap r'.a:filename[:0].method[:0].' :call django#apps#edit("'.a:filename.'", "'.method.'")' 6 | endfor 7 | endfunction 8 | 9 | call s:CreateRelatedMappingsPerFile('models.py') 10 | call s:CreateRelatedMappingsPerFile('views.py') 11 | call s:CreateRelatedMappingsPerFile('urls.py') 12 | call s:CreateRelatedMappingsPerFile('tests.py') 13 | call s:CreateRelatedMappingsPerFile('admin.py') 14 | -------------------------------------------------------------------------------- /plugin/django.vim: -------------------------------------------------------------------------------- 1 | " django.vim - A bangin' interface for ViM and Django 2 | " Maintainer: Colin Wood 3 | " Version: 1.0.0rc 4 | " License: Same as ViM. see http://www.gnu.org/licenses/vim-license.txt 5 | 6 | 7 | if !has('python') 8 | echoerr "This script wont work without Python. Please compile with it." 9 | finish 10 | endif 11 | 12 | if !exists('g:django_projects') 13 | " Where the projects are stored at. Will start from this 14 | " root and search down for all someapp.settings files 15 | let g:django_projects = expand('~/Projects') 16 | else 17 | let g:django_projects = expand(g:django_projects) 18 | endif 19 | 20 | if !isdirectory(g:django_projects) 21 | echoerr "Could not access ".g:django_projects 22 | endif 23 | 24 | if !exists('g:django_project_templates') 25 | let g:django_project_templates = expand('~/.templates/projects') 26 | endif 27 | 28 | if !exists('g:django_app_templates') 29 | let g:django_app_templates = expand('~/.templates/apps') 30 | endif 31 | 32 | command! -nargs=1 -complete=customlist,django#completions#projectscomplete DjangoProjectActivate call django#project#activate() 33 | -------------------------------------------------------------------------------- /autoload/django/apps.vim: -------------------------------------------------------------------------------- 1 | function! django#apps#create_app(app_name, ...) 2 | " Should create a app if a projects_app is specified or 3 | " should take a python path and create it there 4 | let pypath = split(a:app_name , '\.') 5 | let new_app = pypath[-1] 6 | 7 | exec 'chdir ' . g:django_project_directory 8 | for app in pypath 9 | 10 | if app == new_app 11 | call django#commands#manage('startapp '. app) 12 | echo "Created new app at ". join(pypath, '.') 13 | break 14 | endif 15 | 16 | if !isdirectory(app) 17 | call mkdir(app) 18 | silent exec '!touch '.app.'/__init__.py' 19 | endif 20 | 21 | exec 'chdir '.app 22 | endfor 23 | endfunction 24 | 25 | 26 | function! django#apps#edit(file_prefix, open_as) 27 | " BUG: This function will have issues if the file is a model such as custom 28 | " models. Since this can be a __init__ file inside of the models.py. 29 | " Should check both for a file_prefix.py and a folder called file_prefix. 30 | let current_app_directory = fnamemodify(expand('%:p'), ':h') 31 | let python_files = split(globpath(current_app_directory, '*/'.a:file_prefix)) 32 | if len(python_files) == 1 33 | let only_file = python_files[0] 34 | call django#utils#vim_open(only_file, a:open_as) 35 | endif 36 | endfunction 37 | -------------------------------------------------------------------------------- /autoload/django/project.vim: -------------------------------------------------------------------------------- 1 | if !exists('*ActivateProject') 2 | function! ActivateProject(project) 3 | python << EOF 4 | import vim 5 | import sys 6 | import os 7 | import django 8 | 9 | os.environ['DJANGO_SETTINGS_MODULE'] = vim.eval('a:project')+'.settings' 10 | sys.path.append(vim.eval('g:django_project_directory')) 11 | try: 12 | django.setup() 13 | except AttributeError: 14 | pass 15 | EOF 16 | endfunction 17 | endif 18 | 19 | function! django#project#activate(project) 20 | 21 | if !exists('g:django_projects_search_exp') 22 | let g:django_projects_search_exp = '**' " Recursivly look down for all settings 23 | endif 24 | 25 | let search_exp = g:django_projects_search_exp . "/" . a:project . "/settings*" 26 | 27 | if !exists('g:django_projects') 28 | echoerr "No django projects directory set. Please set one" 29 | return 30 | endif 31 | 32 | let settings_found = split(globpath(g:django_projects, search_exp))[0] 33 | 34 | if len(settings_found) == 0 35 | echoerr "No settings file found" 36 | return 37 | endif 38 | 39 | if isdirectory(l:settings_found) 40 | let g:django_project_directory = fnamemodify(l:settings_found, ':h:h') 41 | else 42 | let g:django_project_directory = fnamemodify(l:settings_found, ':p:h:h') 43 | endif 44 | 45 | let g:django_project_name = a:project 46 | 47 | if exists('g:django_activate_virtualenv') && exists('g:virtualenv_loaded') 48 | if g:django_activate_virtualenv == 1 49 | for env in virtualenv#names(a:project) 50 | call virtualenv#activate(env) 51 | break 52 | endfor 53 | else 54 | echoerr 'VirtualEnv not installed. Not activating.' 55 | endif 56 | endif 57 | 58 | if exists('g:django_activate_nerdtree') 59 | if exists('g:loaded_nerd_tree') && g:django_activate_nerdtree == 1 60 | exec ':NERDTree '.g:django_project_directory 61 | else 62 | echoerr "NERDTree not installed. Can not open." 63 | endif 64 | else 65 | exec "cd " . g:django_project_directory 66 | endif 67 | 68 | exec 'set path+='.expand(g:django_project_directory) 69 | call ActivateProject(a:project) 70 | 71 | let template_dirs = split(globpath(g:django_project_directory, '**/templates')) 72 | for template_dir in template_dirs 73 | exec 'set path+='.expand(template_dir) 74 | endfor 75 | 76 | let static_dirs = split(globpath(g:django_project_directory, a:project . '/**/static')) 77 | for static_dir in static_dirs 78 | exec 'set path+='.expand(static_dir) 79 | endfor 80 | 81 | python << EOI 82 | from django.utils.importlib import import_module 83 | from django.template.loaders.app_directories import app_template_dirs 84 | from django.conf import settings 85 | import vim 86 | for template_dir in app_template_dirs: 87 | vim.command("exec 'set path+=%s'" % (template_dir)) 88 | 89 | for app in settings.INSTALLED_APPS: 90 | try: 91 | mod = import_module(app) 92 | except ImportError, e: 93 | raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0])) 94 | static_dir = os.path.join(os.path.dirname(mod.__file__), 'static') 95 | if os.path.isdir(static_dir): 96 | vim.command("exec 'set path+=%s'" % (static_dir)) 97 | EOI 98 | 99 | 100 | 101 | command! -nargs=? -complete=customlist,django#completions#managmentcommands DjangoManage call django#commands#manage() 102 | command! -nargs=? -complete=customlist,django#completions#managmentcommands DjangoAdmin call django#commands#admin() 103 | command! -nargs=? -complete=customlist,django#completions#pypath DjangoCreateApp call django#apps#create_app() 104 | 105 | endfunction 106 | -------------------------------------------------------------------------------- /autoload/django/completions.vim: -------------------------------------------------------------------------------- 1 | function! django#completions#pypath(prefix, ...) 2 | python << EOB 3 | import os 4 | import vim 5 | import sys 6 | 7 | class NoMatchFound(Exception): 8 | pass 9 | 10 | def create_prefix_paths(prefix): 11 | "Should return a list of items to compare aginst" 12 | 13 | if not prefix: 14 | paths = [] 15 | else: 16 | try: 17 | paths = prefix.split('.') 18 | except AttributeError: 19 | paths = [prefix] 20 | return paths 21 | 22 | def create_possible_paths(current_root, current_prefix): 23 | "Should take the prefix list and return a list of possible paths" 24 | 25 | if not isinstance(current_prefix, list): 26 | raise Exception('Prefix is not a list. What we gunna do!') 27 | 28 | full_path = os.path.join(current_root, *current_prefix) 29 | 30 | if not os.path.exists(full_path): 31 | if full_path == current_root: 32 | directories = _get_directories(current_root) 33 | else: 34 | base, head = os.path.split(full_path) 35 | directories = _get_directories(base) 36 | else: 37 | directories = _get_directories(full_path) 38 | 39 | paths = [] 40 | 41 | if not current_prefix: 42 | begining_path = '' 43 | else: 44 | begining_path = '.'.join(current_prefix[:-1]) 45 | matching = current_prefix[-1] 46 | 47 | if begining_path.startswith('.'): 48 | begining_path = begining_path[1:] 49 | 50 | for directory in directories: 51 | 52 | if begining_path and matching: 53 | if directory.startswith(matching): 54 | possible_path = begining_path+'.'+directory+'.' 55 | paths.append(possible_path) 56 | 57 | elif begining_path and not matching: 58 | possible_path = begining_path+'.'+directory+'.' 59 | paths.append(possible_path) 60 | else: 61 | possible_path = directory+'.' 62 | paths.append(possible_path) 63 | 64 | 65 | return paths 66 | 67 | def _get_directories(path): 68 | 69 | directories = [] 70 | for item in os.listdir(path): 71 | if os.path.isdir(os.path.join(path, item)) and not item.startswith('.'): 72 | files = os.listdir(os.path.join(path, item)) 73 | if '__init__.py' in files: 74 | directories.append(item) 75 | 76 | return directories 77 | 78 | prefix = vim.eval('a:prefix') 79 | project_root = vim.eval('g:django_project_directory') 80 | 81 | prefix_path = create_prefix_paths(prefix) 82 | possible_paths = create_possible_paths(project_root, prefix_path) 83 | 84 | vim.command('return '+str(possible_paths)) 85 | EOB 86 | endfunction 87 | 88 | 89 | function! django#completions#managmentcommands(prefix, line, ...) 90 | python << EOB 91 | from django.core import management 92 | from django.conf import settings 93 | 94 | prefix = vim.eval('a:prefix') 95 | commands = list(management.get_commands()) 96 | 97 | if prefix: 98 | commands = [command for command in commands if command.startswith(prefix)] 99 | 100 | vim.command('return '+str(commands)) 101 | EOB 102 | endfunction 103 | 104 | function! django#completions#projectscomplete(prefix, ...) 105 | 106 | if !exists('g:django_projects_search_exp') 107 | let g:django_projects_search_exp = '**' " Recursivly look down for all settings 108 | return 109 | endif 110 | 111 | let search_exp = g:django_projects_search_exp . "/*/settings*" 112 | 113 | if !exists('g:django_projects') 114 | echoerr "No django projects directory set. Please set one" 115 | return 116 | endif 117 | 118 | echo search_exp 119 | 120 | let all_settings_files = split(globpath(g:django_projects, search_exp)) 121 | let all_projects = [] 122 | 123 | for setting_file in all_settings_files 124 | let project = fnamemodify(setting_file, ':h:t') 125 | call add(all_projects, project) 126 | endfor 127 | 128 | if a:prefix == '' 129 | return all_projects 130 | else 131 | let arg_regex = 'v:val =~ "'.a:prefix.'"' 132 | return filter(copy(all_projects), arg_regex) 133 | endif 134 | 135 | endfunction 136 | 137 | function! django#completions#installed_apps(prefix, ...) 138 | python << EOB 139 | import vim 140 | from django.conf import settings 141 | prefix = vim.eval('a:prefix') 142 | 143 | if prefix: 144 | apps = [app for app in settings.INSTALLED_APPS if app.startswith(prefix)] 145 | else: 146 | apps = settings.INSTALLED_APPS 147 | 148 | vim.command('return'+str(apps)) 149 | EOB 150 | endfunction 151 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Vim-Django 2 | =============================================================================== 3 | 4 | Vim-Django is a ViM script that helps manage a django app(s). It has wrapping's 5 | for the ``django-admin.py``, your projects ``manage.py`` and some helper 6 | commands. It also has some quick ways to find templates, edit related files 7 | in a app, create new apps, and help manage django while using ViM. 8 | 9 | Installing 10 | ------------------------------------------------------------------------------- 11 | 12 | I recommend using pathogen or vundle to install this script. Else, you can 13 | put the ``django.vim`` in the plug-ins directory. This script does require 14 | python to be compiled in. 15 | 16 | You can check by doing :version and looking for `+python` 17 | 18 | Example .vimrc 19 | ------------------------------------------------------------------------------ 20 | ```vim 21 | let g:django_projects = '~/Projects' "Sets all projects under project 22 | let g:django_activate_virtualenv = 1 "Try to activate the associated virtualenv 23 | let g:django_activate_nerdtree = 1 "Try to open nerdtree at the project root. 24 | ``` 25 | 26 | 27 | Advanced search for projects 28 | ------------------------------------------------------------------------------- 29 | 30 | If you want more advanced searching for your projects or the default is to slow 31 | for you to use. You can add more advanced filtering. 32 | 33 | For example I use a source directory in each of my projects. So I dont want it to 34 | look through each of my virtualenv directorys, assets, or other project files. 35 | 36 | So what we can do is this 37 | 38 | `g:django_projects_search_exp = '*/source'` this will let us look in the source 39 | folder for each project. You can tweak this to be what you want. This just uses 40 | the vim file path filters. 41 | 42 | 43 | Commands 44 | ------------------------------------------------------------------------------- 45 | 46 | ``DjangoAdmin`` will run any command through the ``django-admin.py`` 47 | command. 48 | 49 | ``DjangoManage`` will run the management command for the project 50 | 51 | ``DjangoProjectActivate`` will activate the project. This will go through 52 | your ``g:django_projects`` and find all the django projects. It will also 53 | set up ``DJANGO_SETTINGS_MODULE`` in your environment and the directory 54 | where the settings file is stored in your ``PYTHONPATH``. 55 | 56 | ``DjangoCreateApp`` will create a new app under your projects base. It will 57 | autocomplete the path. It just needs is a python path such as, 58 | ``colinbits.apps.new_app`` this will be created in the folder colinbits, 59 | apps, then run the ``django-admin.py`` to create the app there. 60 | 61 | 62 | 63 | Mappings 64 | ------------------------------------------------------------------------------- 65 | 66 | There are mappings for easily editing related django files while working on a 67 | app. They all can be changed if you don't like how they are currently mapped. 68 | There are mappings for (v|views), (u|urls), (a|admin), 69 | and (t|tests). If you want to remap these you can call the function 70 | ``django#apps#edit('name_of_file.py', 'split')`` and it will open up 71 | the file it fines in a split. 72 | 73 | 74 | Configuration 75 | ------------------------------------------------------------------------------- 76 | 77 | ``g:django_projects`` is where your django projects are located. 78 | 79 | ``g:django_activate_virtualenv`` when true will activate a virtualenv that 80 | starts with the same name. An example being. colinbits, is the site, and the 81 | virtualenv being colinbits.com. 82 | 83 | 84 | Custom Activation of Projects 85 | ------------------------------------------------------------------------------- 86 | 87 | Since not everyone uses the default settings file vim-django will allow you to 88 | add a custom function to activate any project. In your vimrc you can define a 89 | function called ``ActivateProject`` it needs to accept one argument. From here 90 | you can have it activate the project. 91 | 92 | Working with other Scripts 93 | ------------------------------------------------------------------------------- 94 | 95 | NERDTree: 96 | ``g:django_activate_nerdtree`` when set to 1 will launch nerdtree when 97 | activating the django project. 98 | 99 | VirtualEnv: 100 | ``g:django_activate_virtualenv`` when set to 1 will activate the virtual 101 | env that starts with the same name. 102 | 103 | 104 | 105 | Screen shots 106 | ------------------------------------------------------------------------------- 107 | 108 | ![Mangement Command](http://i.imgur.com/NYd9d.png) 109 | 110 | 111 | FAQ 112 | ------------------------------------------------------------------------------ 113 | 114 | * Working with virtualenv's 115 | * I actully reccomend installing [vim-virtualenv](https://github.com/jmcantrell/vim-virtualenv) 116 | -------------------------------------------------------------------------------- /doc/vim-django.txt: -------------------------------------------------------------------------------- 1 | *vim-django.txt* For Vim version 7.3 Last Change: 2013-06-03 2 | ============================================================================== 3 | 4 | Django - A web framework for perfectionist 5 | A vim script for a better way to work with django. 6 | 7 | ============================================================================== 8 | CONTENTS *django-contents* 9 | 10 | 1. Introduction .......................... |django-introduction| 11 | 2. Configuration ......................... |django-configuration| 12 | 3. Keymappings ........................... |django-keymappings| 13 | 3.1 Editing Related .................... |django-editing-related| 14 | 4. Extensions To Vim ..................... |django-extensions| 15 | 5. Commands .............................. |django-commands| 16 | 6. Custom Setup .......................... |django-custom-setup| 17 | 7. Thanks & Contributing ................. |django-thank-contribute| 18 | 19 | ============================================================================== 20 | Introduction *django-introduction* 21 | 22 | Django VIM is my extension to vim to making working with django projects 23 | easier. This means making creating new apps, working with your projects 24 | management commands inside of ViM, the django-admin.py script, managing 25 | the apps, and various other extensions. 26 | 27 | ============================================================================== 28 | Configuration *django-configruation* 29 | 30 | *django-vim-global-vars* ----------------------------------------------------- 31 | 32 | *g:django_projects* This should be set to where your projects live. 33 | it needs either a absolute path or you can use the |expand()| to include 34 | your home directory. 35 | 36 | Example: 37 | g:django_projects = expand('~/Projects') 38 | 39 | *g:django_activate_nerdtree* when set to 1 it will activate |NERDTree| if you 40 | are using it. This is only done when activating a new django project. 41 | 42 | *g:django_activate_virtualenv* when also set to 1, this will activate a 43 | corresponding virtual environment. The virtual environment must start with 44 | the same name as your project does. An example being: colinbits is my django 45 | project; this will activate the colinbits.com virtualenv. 46 | 47 | *g:django_project_container* this is now depreicated. Please use 48 | |g:django_projects_search_exp| this is a better solution and allows you a more 49 | powerfull search. 50 | 51 | *g:django_projects_search_exp* is used to better filter sub projects. By 52 | default this does "**" so for example. The default search looks like this. 53 | 54 | "**//settings*", this should recursivly look down for a project 55 | directory and a settings directory/file. If there is one there it will be 56 | picked up. So if you have just default django projects this should work fine. 57 | 58 | 59 | ============================================================================== 60 | Keymappings *django-keymappings* 61 | 62 | *django-editing-related* ---------------------------------------------------- 63 | 64 | There are mappings for editing related source for a django app. The mappings 65 | to edit related files all follow the same pattern. That being. (r) for 66 | related, (m) for models.py, and (t) for tab. So this will be edit the related 67 | models.py in a new tab. There is also (s), and (v) for split and vsplit 68 | respectivly. 69 | 70 | ============================================================================== 71 | Extenions to ViM *django-extenions* 72 | 73 | Nothing yet... 74 | 75 | ============================================================================== 76 | Commands *django-commands* 77 | 78 | *DjangoProjectActivate* activates your project inside of ViM. This has 79 | to be run first in order for the other commands and for ViM to take 80 | full advantage of your project and your site-packages that use django. 81 | This also adds your template and static directories so when in views/templates 82 | you can |gf| and open up the new file. 83 | 84 | An example being:: 85 | 86 | from django.views.generic import TemplateView 87 | 88 | 89 | class HomePage(TemplateView): 90 | template_name = 'site/home_page.html' 91 | 92 | If you |gf| over "site/home_page.html" itll open up the first found 93 | site/home_page.html. 94 | 95 | *DjangoManage* this will wrap the manage.py command for your project. It will 96 | try to autocomplete the commands available to your manage.py. This is only 97 | problematic if your project doesn't use the standard django settings or can't 98 | be imported by doing from django.conf import settings. 99 | 100 | *DjangoAdmin* will wrap the django-admin.py for your systems djang-admin.py 101 | script. If you use virtualenv's it should wrap it for your enviroment. This 102 | isn't that different than from |DjangoManage| other than access to the admin 103 | script. 104 | 105 | *DjangoCreateApp* will create a new app based on a python path. If you 106 | give it your app.apps.super_cool_app it will create the app there by using 107 | the django-admin and it will also create corresponding init files and 108 | directories if they are not already created. 109 | 110 | ============================================================================== 111 | Custom Setup *django-custom-setup* 112 | 113 | Incase you dont use the standard setup method or have the ability to use 114 | the settings environment variable from your env. You can create your own 115 | setup function. 116 | 117 | The function has to be named *ActivateProject* it should accept a project name 118 | 119 | you can also access the other global variables such as 120 | |g:django_project_directory|. 121 | 122 | Example: 123 | 124 | 125 | function! ActivateProject(project) 126 | python << EOF 127 | import cbsettings 128 | import sys 129 | sys.path.append(vim.eval('g:django_project_directory')) 130 | cbsettings.configure(vim.eval('a:project')+'.settings.switcher') 131 | EOF 132 | endfunction 133 | 134 | The above example will activate a project that uses django-classbasesettings. 135 | If a custom function is not created it will activate the project by adding 136 | the django_project_directory to sys.path and setting $DJANOG_SETTINGS_MODULE to 137 | project_name.settings. 138 | 139 | ============================================================================== 140 | Thank You & Contributing *django-thank-contribute* 141 | 142 | Thanks for using my little plug-in. I plan on adding more features as I need 143 | them. If there is something you would like to see in this script feel free 144 | to add a issue at the Github project. 145 | 146 | It is located at https://github.com/cwood/vim-django. Also feel free to 147 | fork it and send in a pull request. I love seeing people using my code. 148 | 149 | ============================================================================== 150 | vim:tw=78:sw=4:ts=8:expandtab:ft=help:norl 151 | --------------------------------------------------------------------------------