Skip to content

Commit

Permalink
Merge branch 'release/1.3.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
crucialfelix committed Apr 6, 2015
2 parents dbab068 + b12a3fe commit cfbc6db
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 104 deletions.
82 changes: 41 additions & 41 deletions README.md
Expand Up @@ -32,7 +32,7 @@ Features
+ Customize HTML, CSS and JS
+ JQuery triggers allow you to customize interface behavior to respond when items are added or removed
+ Default (but customizable) security prevents griefers from pilfering your data via JSON requests

+ Django 1.6+


Quick Installation
Expand Down Expand Up @@ -65,7 +65,7 @@ In settings.py :

In your urls.py:

from django.conf.urls import *
from django.conf.urls import patterns, include

from django.contrib import admin
from ajax_select import urls as ajax_select_urls
Expand All @@ -78,24 +78,23 @@ In your urls.py:
(r'^admin/', include(admin.site.urls)),
)

For Django 1.3 or earlier replace the first line by `from django.conf.urls.defaults import *`.

In your admin.py:

from django.contrib import admin
from ajax_select import make_ajax_form
from ajax_select.admin import AjaxSelectAdmin
from example.models import *
from example.models import Person, Label

class PersonAdmin(admin.ModelAdmin):
pass
admin.site.register(Person,PersonAdmin)
admin.site.register(Person, PersonAdmin)

class SongAdmin(AjaxSelectAdmin):
class LabelAdmin(AjaxSelectAdmin):
# create an ajax form class using the factory function
# model,fieldlist, [form superclass]
form = make_ajax_form(Label,{'owner':'person'})
admin.site.register(Label,LabelAdmin)
form = make_ajax_form(Label, {'owner': 'person'})
admin.site.register(Label, LabelAdmin)

example/lookups.py:

Expand All @@ -105,7 +104,7 @@ example/lookups.py:

model = Song

def get_query(self,q,request):
def get_query(self, q, request):
return Song.objects.filter(title__icontains=q).order_by('title')


Expand Down Expand Up @@ -159,18 +158,18 @@ settings.py

Defines the available lookup channels.

+ channel_name : {'model': 'app.modelname', 'search_field': 'name_of_field_to_search' }
+ channel_name : {'model': 'app.modelname', 'search_field': 'name_of_field_to_search'}
> This will create a channel automatically
channel_name : ( 'app.lookups', 'YourLookup' )
This points to a custom Lookup channel name YourLookup in app/lookups.py

AJAX_LOOKUP_CHANNELS = {
# channel : dict with settings to create a channel
'person' : {'model':'example.person', 'search_field':'name'},
'person': {'model': 'example.person', 'search_field': 'name'},

# channel: ( module.where_lookup_is, ClassNameOfLookup )
'song' : ('example.lookups', 'SongLookup'),
'song': ('example.lookups', 'SongLookup'),
}

#### AJAX_SELECT_BOOTSTRAP
Expand Down Expand Up @@ -203,7 +202,7 @@ urls.py

Simply include the ajax_select urls in your site's urlpatterns:

from django.conf.urls.defaults import *
from django.conf.urls.defaults import patterns, include

from django.contrib import admin
from ajax_select import urls as ajax_select_urls
Expand All @@ -229,26 +228,26 @@ Those old lookup channels will still work and the previous methods will be used.
from ajax_select import LookupChannel
from django.utils.html import escape
from django.db.models import Q
from example.models import *
from example.models import Person

class PersonLookup(LookupChannel):

model = Person

def get_query(self,q,request):
def get_query(self, q, request):
return Person.objects.filter(Q(name__icontains=q) | Q(email__istartswith=q)).order_by('name')

def get_result(self,obj):
def get_result(self, obj):
u""" result is the simple text that is the completion of what the person typed """
return obj.name

def format_match(self,obj):
def format_match(self, obj):
""" (HTML) formatted item for display in the dropdown """
return self.format_item_display(obj)

def format_item_display(self,obj):
def format_item_display(self, obj):
""" (HTML) formatted item for displaying item in the selected deck area """
return u"%s<div><i>%s</i></div>" % (escape(obj.name),escape(obj.email))
return u"%s<div><i>%s</i></div>" % (escape(obj.name), escape(obj.email))

Note that raw strings should always be escaped with the escape() function

Expand Down Expand Up @@ -405,6 +404,7 @@ A factory function to makes an ajax field + widget. The helper ensures things a

class Meta:
model = Release
exclude = []

group = make_ajax_field(Release, 'group', 'group', help_text=None)

Expand Down Expand Up @@ -435,7 +435,7 @@ There is possibly a better way to do this, but here is an initial example:
from django.forms.models import BaseModelFormSet
from ajax_select.fields import AutoCompleteSelectMultipleField, AutoCompleteSelectField

from models import *
from models import Task

# create a superclass
class BaseTaskFormSet(BaseModelFormSet):
Expand All @@ -446,7 +446,7 @@ There is possibly a better way to do this, but here is an initial example:
form.fields["project"] = AutoCompleteSelectField('project', required=False)

# pass in the base formset class to the factory
TaskFormSet = modelformset_factory(Task, fields=('name', 'project', 'area'),extra=0, formset=BaseTaskFormSet)
TaskFormSet = modelformset_factory(Task, fields=('name', 'project', 'area'), extra=0, formset=BaseTaskFormSet)



Expand All @@ -459,9 +459,9 @@ Each form field widget is rendered using a template. You may write a custom tem
{% block help %}{% endblock %}

<table>
<tr><th>form Field</th><th>tries this first</th><th>default template</th></tr>
<tr><td>AutoCompleteField</td><td>templates/autocomplete_{{CHANNELNAME}}.html</td><td>templates/autocomplete.html</td></tr> <tr><td>AutoCompleteSelectField</td><td>templates/autocompleteselect_{{CHANNELNAME}}.html</td><td>templates/autocompleteselect.html</td></tr>
<tr><td>AutoCompleteSelectMultipleField</td><td>templates/autocompleteselectmultiple_{{CHANNELNAME}}.html</td><td>templates/autocompleteselectmultiple.html</td></tr>
<tr><th>form Field</th><th>tries this first</th><th>default template</th></tr>
<tr><td>AutoCompleteField</td><td>templates/autocomplete_{{CHANNELNAME}}.html</td><td>templates/autocomplete.html</td></tr> <tr><td>AutoCompleteSelectField</td><td>templates/autocompleteselect_{{CHANNELNAME}}.html</td><td>templates/autocompleteselect.html</td></tr>
<tr><td>AutoCompleteSelectMultipleField</td><td>templates/autocompleteselectmultiple_{{CHANNELNAME}}.html</td><td>templates/autocompleteselectmultiple.html</td></tr>
</table>

See ajax_select/static/js/ajax_select.js below for the use of jQuery trigger events
Expand Down Expand Up @@ -501,35 +501,35 @@ Extend the template, implement the extra_script block and bind functions that wi
##### multi select:

{% block extra_script %}
$("#{{html_id}}_on_deck").bind('added',function() {
id = $("#{{html_id}}").val();
alert('added id:' + id );
$("#{{html_id}}_on_deck").bind('added', function() {
id = $("#{{html_id}}").val();
alert('added id:' + id );
});
$("#{{html_id}}_on_deck").bind('killed',function() {
current = $("#{{html_id}}").val()
alert('removed, current is:' + current);
$("#{{html_id}}_on_deck").bind('killed', function() {
current = $("#{{html_id}}").val()
alert('removed, current is:' + current);
});
{% endblock %}

##### select:

{% block extra_script %}
$("#{{html_id}}_on_deck").bind('added',function() {
id = $("#{{html_id}}").val();
alert('added id:' + id );
});
$("#{{html_id}}_on_deck").bind('killed',function() {
alert('removed');
});
$("#{{html_id}}_on_deck").bind('added', function() {
id = $("#{{html_id}}").val();
alert('added id:' + id );
});
$("#{{html_id}}_on_deck").bind('killed', function() {
alert('removed');
});
{% endblock %}

##### auto-complete text field:

{% block extra_script %}
$('#{{ html_id }}').bind('added',function() {
entered = $('#{{ html_id }}').val();
alert( entered );
});
$('#{{ html_id }}').bind('added', function() {
entered = $('#{{ html_id }}').val();
alert(entered);
});
{% endblock %}

There is no remove as there is no kill/delete button in a simple auto-complete.
Expand Down
54 changes: 54 additions & 0 deletions Release-notes.md
@@ -0,0 +1,54 @@

Version 1.3.6
=============

Support for Django 1.8

Version 1.3.5
=============

Support for Django 1.7
Support for non-integer primary keys

Version 1.3.4
=============

Fix protocols removing http/https in bootstrap

Version 1.3.2
=============

Fixed issues with bootstrap.js correctly detecting the presence of jQuery.ui.autocomplete


Version 1.3
===========

+ Support for Django 1.5 and 1.6
+ Assets moved so that staticfiles works correctly
+ Media classes for widgets added so that Form and Admin media work correctly
+ Spinner image is now served locally, no from github (since staticfiles works now)
+ Improved bootstrap.js that locates or CDN loads a jQuery and a jQuery-ui as needed
+ XSS vulnerability patched in the default lookup

+ Inline scripts moved out of html.
Form fields are activated after the body is loaded with plugin settings stored in the field's data-plugin-options.
This means that javascript including jquery can be at the bottom of the page.
Also less html, more resuable javascript.

+ max-width hack removed
This set the max-width of the dropdown menu for autocomplete fields (simple text) to the size of the text field.
Dropdowns are now the min-width of the text field and max width of 60% of parent div.
This works well in Django admin, in pop ups and in narrow pages.


Breaking changes
----------------

The widget templates no longer have any javascript in them. If you have custom templates you can simplify them now.

The extra_script block is retained in case you are extending a template (to add custom triggers) but it is no longer inside a `jQuery.ready(function() { })` block, so if you are using it then you will need to wrap your code in one.

The bootstrap script uses Django staticfiles

AJAX_SELECT_BOOTSTRAP defaults to True now
13 changes: 7 additions & 6 deletions ajax_select/__init__.py
@@ -1,5 +1,5 @@
"""JQuery-Ajax Autocomplete fields for Django Forms"""
__version__ = "1.3.5"
__version__ = "1.3.6"
__author__ = "crucialfelix"
__contact__ = "crucialfelix@gmail.com"
__homepage__ = "https://github.com/crucialfelix/django-ajax-selects/"
Expand Down Expand Up @@ -92,7 +92,8 @@ class YourModelAdmin(Admin):
class TheForm(superclass):

class Meta:
pass
exclude = []

setattr(Meta, 'model', model)
if hasattr(superclass, 'Meta'):
if hasattr(superclass.Meta, 'fields'):
Expand Down Expand Up @@ -133,12 +134,12 @@ def make_ajax_field(model, model_fieldname, channel, show_help_text=False, **kwa
AutoCompleteSelectField

field = model._meta.get_field(model_fieldname)
if not 'label' in kwargs:
if 'label' not in kwargs:
kwargs['label'] = _(capfirst(force_text(field.verbose_name)))

if not 'help_text' in kwargs and field.help_text:
if ('help_text' not in kwargs) and field.help_text:
kwargs['help_text'] = field.help_text
if not 'required' in kwargs:
if 'required' not in kwargs:
kwargs['required'] = not field.blank

kwargs['show_help_text'] = show_help_text
Expand All @@ -160,7 +161,7 @@ def make_ajax_field(model, model_fieldname, channel, show_help_text=False, **kwa
return f


#################### private ##################################################
# ----------------------- private --------------------------------------------- #

def get_lookup(channel):
""" find the lookup class for the named channel. this is used internally """
Expand Down

0 comments on commit cfbc6db

Please sign in to comment.