django-bursar / bursar /

Full commit
from django.contrib import admin
from django.db import models
from django.db.models.query import QuerySet
from django.http import HttpResponse, HttpResponseNotFound
from django.utils.encoding import smart_str
from django.utils.translation import ugettext_lazy as _
from bursar.models import Authorization, CreditCardDetail, PaymentFailure, \
                        PaymentNote, PaymentPending, Purchase, LineItem, \

class AutocompleteAdmin(admin.ModelAdmin):
    """Admin class for models using the autocomplete feature.

    There are two additional fields:
       - related_search_fields: defines fields of managed model that
         have to be represented by autocomplete input, together with
         a list of target model fields that have to be searched for
         input string,
       - related_string_functions: contains optional functions which
         take target model instance as only argument and return string
         representation. By default __unicode__() method of target
         object is used.

    related_search_fields = {}
    related_string_functions = {}

    def __call__(self, request, url):
        # This is deprecated interface and will be dropped in Django 1.3.
        # Since the version 1.1, Django uses get_urls() method below.
        if url is None:
        elif url == 'search':
        return super(AutocompleteAdmin, self).__call__(request, url)

    def get_urls(self):
        from django.conf.urls.defaults import url
        patterns = super(AutocompleteAdmin, self).get_urls()
        info =, self.model._meta.app_label, self.model._meta.module_name
                -1,     # insert just before (.+) rule (see django.contrib.admin.options.ModelAdmin.get_urls)
                    name='%sadmin_%s_%s_search' % info
        return patterns

    def search(self, request):
        Searches in the fields of the given related model and returns the
        result as a simple string to be used by the jQuery Autocomplete plugin
        query = request.GET.get('q', None)
        app_label = request.GET.get('app_label', None)
        model_name = request.GET.get('model_name', None)
        search_fields = request.GET.get('search_fields', None)
            to_string_function = self.related_string_functions[model_name]
        except KeyError:
            to_string_function = lambda x: x.__unicode__()

        if search_fields and app_label and model_name and query:
            def construct_search(field_name):
                # use different lookup methods depending on the notation
                if field_name.startswith('^'):
                    return "%s__istartswith" % field_name[1:]
                elif field_name.startswith('='):
                    return "%s__iexact" % field_name[1:]
                elif field_name.startswith('@'):
                    return "%s__search" % field_name[1:]
                    return "%s__icontains" % field_name

            model = models.get_model(app_label, model_name)
            qs = model._default_manager.all()
            for bit in query.split():
                or_queries = [models.Q(**{construct_search(
                    smart_str(field_name)): smart_str(bit)})
                        for field_name in search_fields.split(',')]
                other_qs = QuerySet(model)
                other_qs = other_qs.filter(reduce(operator.or_, or_queries))
                qs = qs & other_qs
            data = ''.join([u'%s|%s\n' % (to_string_function(f), for f in qs])
            return HttpResponse(data)
        return HttpResponseNotFound()

    def formfield_for_dbfield(self, db_field, **kwargs):
        Overrides the default widget for Foreignkey fields if they are
        specified in the related_search_fields class attribute.
        if isinstance(db_field, models.ForeignKey) and \
       in self.related_search_fields:
            kwargs['widget'] = ForeignKeySearchInput(
        field = super(AutocompleteAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        return field

class Authorization_Inline(admin.TabularInline):
    model = Authorization
    extra = 0

class CreditCardDetail_Inline(admin.TabularInline):
    model = CreditCardDetail
    extra = 0

class LineItem_Inline(admin.TabularInline):
    model = LineItem
    extra = 1

class Payment_Inline(admin.TabularInline):
    model = Payment
    extra = 1

class PaymentNote_Inline(admin.TabularInline):
    model = PaymentNote
    extra = 1

class PaymentFailure_Inline(admin.TabularInline):
    model = PaymentFailure
    extra = 0

class PaymentPending_Inline(admin.TabularInline):
    model = PaymentPending
    extra = 0

class PurchaseOptions(admin.ModelAdmin):
    fieldsets = (
        (None, {'fields': ('site', 'orderno')}),
        (_('Purchaser'), {'fields': ('first_name', 'last_name', 'email', 'phone', )}), 
        (_('Shipping Address'), 
            {'classes': ('collapse',), 
             'fields': ('ship_street1', 'ship_street2', 'ship_city', 'ship_state', 'ship_postal_code', 'ship_country')}),
        (_('Billing Address'), 
            {'classes': ('collapse',),
             'fields': ('bill_street1', 'bill_street2', 'bill_city', 'bill_state', 'bill_postal_code', 'bill_country')}),
            {'fields': ('sub_total', 'shipping', 'tax', 'total', 'time_stamp')})
    list_display = ('id', 'first_name', 'last_name', 'time_stamp', 'total', 'authorized_remaining', 'remaining')
    list_filter = ['time_stamp', 'last_name']
    date_hierarchy = 'time_stamp' 
    list_filter = ['time_stamp'] 
    inlines = [Payment_Inline, PaymentPending_Inline,  PaymentFailure_Inline, LineItem_Inline] #, RecurringLineItem_Inline]

class PaymentOptions(AutocompleteAdmin):
    list_filter = ['method']
    list_display = ['id', 'transaction_id', 'success', 'method', 'amount', 'time_stamp']
    fieldsets = (
        (None, {'fields': ('purchase','success', 'method', 'amount',  'transaction_id', 'reason_code', 'time_stamp', 'details')}), )
    raw_id_fields = ['purchase']
    inlines = [CreditCardDetail_Inline, PaymentNote_Inline], PurchaseOptions), PaymentOptions)