Skip to content

Commit de037d6

Browse files
author
A.J. May
committed
contrib ready
1 parent 41449f1 commit de037d6

25 files changed

+365
-10
lines changed

CONTRIBUTING.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Want to contribute? Submit a pull request.
2+
3+
### Getting Started
4+
5+
1. Fork the repo.
6+
7+
2. run `$ script/bootstrap` from within a [virtual enviromnent](https://virtualenv.pypa.io/en/latest/).
8+
9+
3. Make changes, add a feature, or fix a bug.
10+
11+
4. Run the tests. I _only_ take pull requests with passing tests: `$ script/test`
12+
13+
5. Add a test for your change. Only refactoring and documentation changes
14+
require no new tests. If you are adding functionality or fixing a bug, I need
15+
a test! Not sure? ask.
16+
17+
6. Make the test pass.
18+
19+
7. Push to your fork and submit a pull request.
20+
21+
22+
At this point you're waiting on me. I like to at least comment on, if not
23+
accept, pull requests within three business days (and, typically, one business
24+
day). I may suggest some changes or improvements or alternatives.

LICENSE.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
__Copyright (c) 2014 A.J. May__
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
recursive-include django_bootstrap_typeahead/static *
2+
include README.md

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Django Bootstrap Typeahead
2+
3+
## Convert django model choice fields into typeahead fields.
4+
5+
Typeahead inputs built ontop of [Django](https://www.djangoproject.com/) and [Bootstrap](http://getbootstrap.com/).
6+
7+
![Example](http://thegoods.aj7may.com/content/images/2014/Feb/Screen_Shot_2014_02_05_at_5_27_56_PM.png)
8+
9+
### Install:
10+
`> pip install django-bootstrap-typeahead`
11+
12+
### Usage:
13+
14+
* Add `django-bootstrap-typeahead` to the installed apps of your Django Project
15+
* create a form and use `TypeaheadField` instead of `ModelChoiceField`
16+
or `MultipleTypeaheadField` instead of `ModelMultipleChoiceField`
17+
* Be sure to include the form's required media in the template. _ie._ `{{ form.media }}`
18+
* Also be sure to include [Twitter Bootstrap](http://getbootstrap.com/)
19+
20+
### Example:
21+
22+
_forms.py_
23+
24+
from django import forms
25+
from django_bootstrap_typeahead.fields import *
26+
from .models import Thing
27+
28+
29+
def build_thing(value):
30+
thing, created = Thing.objects.get_or_create(name=value)
31+
return thing
32+
33+
34+
class TestForm(forms.Form):
35+
typeahead = TypeaheadField(
36+
queryset=Thing.objects.all(),
37+
builder=build_thing
38+
)
39+
multi_typeahead = MultipleTypeaheadField(
40+
queryset=Thing.objects.all(),
41+
builder=build_thing
42+
)

django_bootstrap_typeahead/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def __init__(self, queryset, builder=False, required=True, label=None,
1313
queryset, required=required,
1414
widget=TypeaheadInput(queryset=queryset, builder=builder),
1515
label=label, initial=initial, help_text=help_text,
16-
limit_choices_to=limit_choices_to, *args, **kwargs
16+
limit_choices_to=limit_choices_to, empty_label='', *args, **kwargs
1717
)
1818

1919

requirements.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-e git+https://github.com/django/django.git@95cf17244c086cb31eef86bdb0db57a0b5d05e38#egg=Django-dev
2+
coverage==3.7.1
3+
-e git://github.com/kennethreitz/dj-static.git@e79582483a976c76511244b3f236f7c68991e1ae#egg=dj_static-master
4+
pep8==1.5.6
5+
py==1.4.20
6+
pystache==0.5.4
7+
pytest==2.5.2
8+
static==1.0.2
9+
static3==0.5
10+
wsgiref==0.1.2

script/adduser

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
(cd test_project; python manage.py createsuperuser)

script/bootstrap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
pip install -r requirements.txt
4+
5+
(cd test_project; python manage.py syncdb --noinput)

script/runserver

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
(cd test_project; python manage.py runserver)

script/test

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
pep8 --ignore=E128 .
4+
coverage run --source=django_bootstrap_markdown -m py.test
5+
coverage report

setup.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,13 @@
22

33
setup(
44
name="django-bootstrap-typeahead",
5-
version="1.1.3",
5+
version="1.1.4",
66
packages=find_packages(),
77
author="A.J. May",
88
author_email="[email protected]",
9-
description="""A typeahead django form input which
10-
accepts a queryset to populate the typeahead options.""",
9+
description="Convert django model choice fields into typeahead fields.",
1110
license="MIT License",
1211
keywords="django bootstrap typeahead form widget input",
1312
url="http://thegoods.aj7may.com/django-bootstrap-typeahead",
1413
zip_safe=False,
15-
package_data={
16-
'django_bootstrap_typeahead': [
17-
'static/js/*',
18-
'static/css/*',
19-
],
20-
},
2114
)

test_project/db.sqlite3

132 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../django_bootstrap_typeahead/

test_project/manage.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python
2+
import os
3+
import sys
4+
5+
if __name__ == "__main__":
6+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")
7+
8+
from django.core.management import execute_from_command_line
9+
10+
execute_from_command_line(sys.argv)

test_project/test_app/__init__.py

Whitespace-only changes.

test_project/test_app/admin.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from django.contrib import admin
2+
from .models import Thing
3+
4+
admin.site.register(Thing)

test_project/test_app/forms.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from django import forms
2+
from django_bootstrap_typeahead.fields import *
3+
from .models import Thing
4+
5+
6+
def build_thing(value):
7+
thing, created = Thing.objects.get_or_create(name=value)
8+
return thing
9+
10+
11+
class TestForm(forms.Form):
12+
typeahead = TypeaheadField(
13+
queryset=Thing.objects.all(),
14+
builder=build_thing,
15+
required=False
16+
)
17+
multi_typeahead = MultipleTypeaheadField(
18+
queryset=Thing.objects.all(),
19+
builder=build_thing,
20+
required=False
21+
)

test_project/test_app/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.db import models
2+
3+
4+
class Thing(models.Model):
5+
name = models.CharField(max_length=100)
6+
7+
def __unicode__(self):
8+
return self.name
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
7+
<title>Django Bootstrap Markdown Test Application</title>
8+
9+
<!-- Bootstrap -->
10+
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
11+
12+
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
13+
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
14+
<!--[if lt IE 9]>
15+
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"></script>
16+
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
17+
<![endif]-->
18+
</head>
19+
<body>
20+
<nav class="navbar navbar-default navbar-static-top" role="navigation">
21+
<div class="container">
22+
<div class="navbar-header">
23+
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navigation">
24+
<span class="sr-only">Toggle navigation</span>
25+
<span class="icon-bar"></span>
26+
<span class="icon-bar"></span>
27+
<span class="icon-bar"></span>
28+
</button>
29+
<a class="navbar-brand" href="#">Django Bootstrap Markdown</a>
30+
</div>
31+
32+
<!-- Collect the nav links, forms, and other content for toggling -->
33+
<div class="collapse navbar-collapse" id="navigation">
34+
<ul class="nav navbar-nav">
35+
<li><a href="#">Home</a></li>
36+
</ul>
37+
</div>
38+
</div>
39+
</nav>
40+
41+
<div class="container" style="margin-bottom: 20px;">
42+
{% for message in messages %}
43+
<div class="alert alert-{% if message.tags == 'error' %}danger{% else %}{{ message.tags }}{% endif %} alert-dismissable">
44+
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
45+
{{ message }}
46+
</div>
47+
{% endfor %}
48+
49+
<form method="POST">{% csrf_token %}
50+
<div class="form-group">
51+
<label for="{{ form.typeahead.id_for_label }}">Typeahead Field</label>
52+
{{ form.typeahead }}
53+
{{ form.typeahead.errors }}
54+
</div>
55+
56+
<div class="form-group">
57+
<label for="{{ form.typeahead.id_for_label }}">Multiple Typeahead Field</label>
58+
{{ form.multi_typeahead }}
59+
{{ form.multi_typeahead.errors }}
60+
</div>
61+
62+
<button type="submit" class="btn btn-primary">Submit</button>
63+
</form>
64+
</div>
65+
66+
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
67+
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/js/bootstrap.min.js"></script>
68+
{{ form.media }}
69+
</body>
70+
</html>

test_project/test_app/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

test_project/test_app/views.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from django.shortcuts import render
2+
from django.contrib import messages
3+
from .forms import TestForm
4+
5+
6+
def test_view(request):
7+
if request.method == 'POST':
8+
form = TestForm(request.POST)
9+
if form.is_valid():
10+
if form.cleaned_data['typeahead']:
11+
messages.success(
12+
request,
13+
'Typeahead: %s' % form.cleaned_data['typeahead']
14+
)
15+
if form.cleaned_data['multi_typeahead']:
16+
messages.success(
17+
request,
18+
'MultipleTypeahead: %s' % form.cleaned_data['multi_typeahead']
19+
)
20+
else:
21+
form = TestForm()
22+
23+
return render(request, 'test.html', {
24+
'form': form,
25+
})

test_project/test_project/__init__.py

Whitespace-only changes.

test_project/test_project/settings.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""
2+
Django settings for test_project project.
3+
4+
For more information on this file, see
5+
https://docs.djangoproject.com/en/1.6/topics/settings/
6+
7+
For the full list of settings and their values, see
8+
https://docs.djangoproject.com/en/1.6/ref/settings/
9+
"""
10+
11+
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
12+
import os
13+
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
14+
15+
16+
# Quick-start development settings - unsuitable for production
17+
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
18+
19+
# SECURITY WARNING: keep the secret key used in production secret!
20+
SECRET_KEY = '%5e9q4k6ef_zkn5x350iq2!0db5op7@#kkk(jeja4!glbwpy-k'
21+
22+
# SECURITY WARNING: don't run with debug turned on in production!
23+
DEBUG = True
24+
TEMPLATE_DEBUG = True
25+
26+
ALLOWED_HOSTS = []
27+
28+
29+
# Application definition
30+
INSTALLED_APPS = (
31+
'django.contrib.admin',
32+
'django.contrib.auth',
33+
'django.contrib.contenttypes',
34+
'django.contrib.sessions',
35+
'django.contrib.messages',
36+
'django.contrib.staticfiles',
37+
'django_bootstrap_typeahead',
38+
'test_app',
39+
)
40+
41+
MIDDLEWARE_CLASSES = (
42+
'django.contrib.sessions.middleware.SessionMiddleware',
43+
'django.middleware.locale.LocaleMiddleware',
44+
'django.middleware.common.CommonMiddleware',
45+
'django.middleware.csrf.CsrfViewMiddleware',
46+
'django.contrib.auth.middleware.AuthenticationMiddleware',
47+
'django.contrib.messages.middleware.MessageMiddleware',
48+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
49+
)
50+
51+
ROOT_URLCONF = 'test_project.urls'
52+
53+
WSGI_APPLICATION = 'test_project.wsgi.application'
54+
55+
# Database
56+
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases
57+
58+
DATABASES = {
59+
'default': {
60+
'ENGINE': 'django.db.backends.sqlite3',
61+
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
62+
}
63+
}
64+
65+
# Internationalization
66+
# https://docs.djangoproject.com/en/1.6/topics/i18n/
67+
68+
LANGUAGE_CODE = 'en-US'
69+
70+
TIME_ZONE = 'UTC'
71+
72+
USE_I18N = True
73+
74+
USE_L10N = True
75+
76+
USE_TZ = True
77+
78+
79+
# Static files (CSS, JavaScript, Images)
80+
# https://docs.djangoproject.com/en/1.6/howto/static-files/
81+
STATIC_ROOT = 'static'
82+
STATIC_URL = '/static/'

0 commit comments

Comments
 (0)