Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Widgetize #5

Merged
merged 10 commits into from
Feb 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ docs/_build

# System
*.DS_Store
*.idea
*.idea
*.fuse*
2 changes: 1 addition & 1 deletion AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Development Lead
Contributors
------------

None yet. Why not be the first?
* Nathan Shafer <nate@lotech.org>
94 changes: 82 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,120 @@ comma to separate multiple tags in same form field, and resulting in duplicate t
And you probably want auto-complete/auto-suggest feature when user types some characters in tag field. Thanks to selectize.js, we got that covered :)


Features
--------
* Supports Django 1.8.x and Django 1.9.x
* Supports >=Python2.7 and >=Python3.4
* Simple installation, selectize.js 0.12.1 included
* Will use jQuery install included in Django admin, no installation of jQuery needed
* Will use custom jQuery object if it is installed, though
* Themed to match new Django 1.9 flat theme
* Exposes many selectize.js configuration options to your settings.py
* Supports multiple TaggableManagers in a single model


Quickstart
----------

Install taggit-selectize::
Install taggit-selectize:

pip install taggit-selectize


Usage
-----

1. Put `taggit-selectize` in settings:
1. Put `taggit_selectize` in settings:

```
INSTALLED_APPS = (
'django.contrib.admin',
...
...
'taggit',
'taggit_selectize',
)
```

2. Update urls.py.
```
urlpatterns = patterns('',
urlpatterns = [
...

url(r'^taggit/', include('taggit_selectize.urls')),
url(r'^admin/', include(admin.site.urls)),
...
)
]
```

3. Create `admin` dir inside templates folder. Create a template `base_site.html` and [copy paste this](https://github.com/chhantyal/taggit-selectize/blob/master/example_app/templates/admin/base_site.html).
This has to override from project template dirs otherwise django will still load default `base_site.html` from `django.contrib.admin` app.
Also, filesystem loader must be before app dir loader in settings like:
3. Use the `TaggableManager` from taggit_selectize (instead of taggit) in your models.
```
from taggit_selectize.managers import TaggableManager

class MyModel(models.Model):
tags = TaggableManager()
```
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)


Configuration
-------------
In your settings.py (these are defaults):

```
TAGGIT_SELECTIZE = {
'MINIMUM_QUERY_LENGTH': 2,
'RECOMMENDATION_LIMIT': 10,
'CSS_FILENAMES': ("taggit_selectize/css/selectize.django.css",),
'JS_FILENAMES': ("taggit_selectize/js/selectize.js",),
'DIACRITICS': True,
'CREATE': True,
'PERSIST': True,
'OPEN_ON_FOCUS': True,
'HIDE_SELECTED': True,
'CLOSE_AFTER_SELECT': False,
'LOAD_THROTTLE': 300,
'PRELOAD': False,
'ADD_PRECEDENCE': False,
'SELECT_ON_TAB': False,
'REMOVE_BUTTON': False,
'RESTORE_ON_BACKSPACE': False,
'DRAG_DROP': False,
}
```
You can also use outside of admin in same way.

### MINIMUM_QUERY_LENGTH

The minimum number of characters the user needs to type to cause an AJAX request to hit the server for autocompletion. Default: 2

### RECOMMENDATION_LIMIT

The maximum number of results to return to the user for recommendation. Default: 10

### CSS_FILENAMES

A tuple of CSS files to include on any page that has the taggit-selectize widget on it. Default: `("taggit_selectize/css/selectize.django.css",)`

### JS_FILENAMES

A tuple of JS files to include on any page that has the taggit-selectize widget on it. Default: `("taggit_selectize/js/selectize.js",)`

### DIACRITICS, CREATE, PERSIST, OPEN_ON_FOCUS, HIDE_SELECTED, CLOSE_AFTER_SELECT, LOAD_THROTTLE, PRELOAD, ADD_PRECEDENCE, SELECT_ON_TAB

Options that are passed directly to selectize.js.
Please see [the selectize.js documentation](https://github.com/selectize/selectize.js/blob/master/docs/usage.md) for explanation

### REMOVE_BUTTON

Adds a remove button to each tag item by including the 'remove_button' plugin.

### RESTORE_ON_BACKSPACE

Adds the 'restore_on_backspace' plugin to selectize.js.

### DRAG_DROP

Adds the 'drag_drop' plugin to selectize.js. WARNING: This requires JQuery UI (Sortable) to be installed. If it's not, then
selectize.js will throw an error in the console and refuse to run.


Demo app
Expand Down
1 change: 0 additions & 1 deletion example_app/__init__.py

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

from django.contrib import admin

from .models import Blog
Expand All @@ -11,4 +9,4 @@ class BlogAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}


admin.site.register(Blog, BlogAdmin)
admin.site.register(Blog, BlogAdmin)
5 changes: 5 additions & 0 deletions example_app/blog/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class BlogConfig(AppConfig):
name = 'blog'
26 changes: 26 additions & 0 deletions example_app/blog/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import taggit_selectize.managers


class Migration(migrations.Migration):

dependencies = [
('taggit', '0002_auto_20150616_2121'),
]

operations = [
migrations.CreateModel(
name='Blog',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(max_length=255)),
('slug', models.SlugField(unique=True, max_length=255)),
('body', models.TextField()),
('date', models.DateTimeField(auto_now_add=True)),
('tags', taggit_selectize.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', help_text='A comma-separated list of tags.', verbose_name='Tags')),
],
),
]
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

from taggit.managers import TaggableManager
from taggit_selectize.managers import TaggableManager


@python_2_unicode_compatible
Expand All @@ -15,4 +13,4 @@ class Blog(models.Model):
tags = TaggableManager()

def __str__(self):
return self.title
return self.title
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

from django.shortcuts import render

# Create your views here.
77 changes: 45 additions & 32 deletions example_app/example_app/settings.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
"""
Django settings for example_app project.

Generated by 'django-admin startproject' using Django 1.8.8.

For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '^_jy=02+8yaj)c2ei0ro+d9*v9qc*d1q-m725_=yjy=uev7$el'
SECRET_KEY = '9o*122uaw#7@*(o9)6b%n=gdlb9ec%+%4!@0-gr8#5h7fz15a4'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = []


# Application definition
Expand All @@ -39,7 +40,8 @@

'taggit',
'taggit_selectize',
'example_app.app',

'blog',
)

MIDDLEWARE_CLASSES = (
Expand All @@ -50,15 +52,32 @@
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'example_app.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

WSGI_APPLICATION = 'example_app.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = {
'default': {
Expand All @@ -67,8 +86,9 @@
}
}


# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

Expand All @@ -80,29 +100,22 @@

USE_TZ = True

TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(BASE_DIR, "templates"),
)

STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#'django.contrib.staticfiles.finders.DefaultStorageFinder',
)


TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
#'django.template.loaders.eggs.Loader',
)

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

# Taggit-Selectize settings
TAGGIT_SELECTIZE = {
'MINIMUM_QUERY_LENGTH': 1,
'RECOMMENDATION_LIMIT': 15,
'PERSIST': False,
'OPEN_ON_FOCUS': False,
'HIDE_SELECTED': True,
'CLOSE_AFTER_SELECT': True,
'LOAD_THROTTLE': 100,
'SELECT_ON_TAB': True,
'REMOVE_BUTTON': True,
}
23 changes: 17 additions & 6 deletions example_app/example_app/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
from django.conf.urls import patterns, include, url
from django.contrib import admin
"""example_app URL Configuration

urlpatterns = patterns('',
# Examples:
# url(r'^$', 'example_app.views.home', name='home'),
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
url(r'^taggit/', include('taggit_selectize.urls')),
url(r'^admin/', include(admin.site.urls)),
)
]
Loading