Source

django-extauth / extauth / fieldperms / utils.py

Full commit
import django
from django import forms
from django.forms.fields import EMPTY_VALUES

def map_search_fields_to_query(model_class, search_fields):
    query_fields = {}
    for f in search_fields:
        fname, query_key = expand_search_field(model_class, f)
        query_fields[fname] = query_key
    return query_fields

def expand_search_field(model_class, f):
    if f[0:1] in ['*', '>', '<', '?']:
        fname = f[1:]
        fopt = f[0:1]
    else:
        fname = f
        fopt = None
        
    mf = model_class._meta.get_field_by_name(fname.split('__')[0])
    if mf is not None and isinstance(mf, django.db.models.ForeignKey):
        fname.append('_id')
        
    if fopt == '*':
        query_key = "%s__icontains" % fname
    elif fopt == '>':
        query_key = "%s__gte" % fname
    elif fopt == '<':
        query_key = "%s__lte" % fname
    elif fopt == '?':
        query_key = "%s__isnull" % fname
    else:
        query_key = fname
        
    return (fname, query_key)

def map_search_fields_to_form(search_fields):
    form_fields = {}
    for f in search_fields:
        if f[0:1] in ['*', '>', '<', '?']:
            form_fields[f] = f[1:]
        else:
            form_fields[f] = f
    return form_fields

def get_model_search_fields(model_class, search_fields):
    
    if search_fields is not None:
        return search_fields
    elif hasattr(model_class, 'o9_search_fields'):
        return model_class.o9_search_fields
    else:
        return [[f.name for f in model_class._meta.fields if f.name != "id" and not f.name.endswith("_ptr")][0]]

YES=1
NO=0
ANY=''

def model_has_field(model, field_name):
    if isinstance(model, django.db.models.base.ModelBase):
        model = model()
    fields = field_name.split('__')
    while len(fields) > 0:
        name = fields[0]
        fields = fields[1:]
        try:
            mf = model._meta.get_field(name)
            if mf is not None and isinstance(mf, django.db.models.ForeignKey):
                model = mf.rel.to()
        except:
            return False
    return True

def get_model_value(model, field_name):
    #print "get_model_value(model=%s, field_name=%s)" % (model.__class__.__name__, field_name)
    value = None
    fields = field_name.split('__')
    while len(fields) > 0:
        name = fields[0]
        fields = fields[1:]
        if hasattr(model, name):
            value = getattr(model, name)
            if isinstance(value, django.db.models.Model):
                model = value
    return value

def get_model_value_display(model, field_name):
    #print "get_model_value(model=%s, field_name=%s)" % (model.__class__.__name__, field_name)
    value = None
    fields = field_name.split('__')
    while len(fields) > 0:
        name = fields[0]
        fields = fields[1:]
        if hasattr(model, name):
            value = getattr(model, name)
            if isinstance(value, django.db.models.Model):
                model = value
            elif hasattr(model, 'get_%s_display'%name):
                 value = getattr(model, 'get_%s_display'%name)()
                
    return value

def get_model_field(model, field_name):
    #print "get_model_field(model=%s, field_name=%s)" % (model.__class__.__name__, field_name)
    if isinstance(model, django.db.models.base.ModelBase):
        model = model()
    fields = field_name.split('__')
    while len(fields) > 0:
        name = fields[0]
        fields = fields[1:]
        try:
            mf = model._meta.get_field(name)
            if mf is not None and isinstance(mf, django.db.models.ForeignKey):
                model = mf.rel.to()
        except:
            #print "ERROR: model: %s has not field %s" % (model.__class__.__name__, name)
            pass
    return mf
    
def get_model_search_form_fields(model_class, search_fields):
    from o9.forms import SearchField
    fields = django.utils.datastructures.SortedDict()
    model = model_class()
    for f in search_fields:
        
        # If this is an instance of SearchField, use it's properties
        if isinstance(f, SearchField):
            field_name = f.field_name
            field_id = f.field_id
            if f.form_field is not None:
                field = f.form_field
            else:
                field = get_model_field(model, field_name).formfield()
                if f.form_widget is not None:
                    field.widget = f.form_widget
                if f.default is not None:
                    field.initial = f.default
                if f.label is not None:
                    field.label = f.label
            field.html_name = field_id
        elif isinstance(f, (list, tuple)): 
            if len(f) == 4:
                field_name, default, query_key, field_id = f
            elif len(f) == 3:
                field_name, default, query_key = f
                field_id = field_name
            else:
                field_name, default = f
                field_name, query_key = expand_search_field(model_class, field_name)
                field_id = field_name
            
            if f[0].startswith('?'):
                field = forms.fields.ChoiceField(choices=((ANY, '---------'), (YES, u'Yes'), (NO, u'No')), label=get_model_field(model, field_name).verbose_name)
                default = boolean_to_choice(default)
                #field = forms.fields.BooleanField(label=model._meta.get_field_by_name(field_name)[0].verbose_name)
            else:
                field = get_model_field(model, field_name).formfield()
                if field is None:
                    raise Exception("%s.%s has no formfield"%(model.__class__, field_name))
                field.empty = False
            field.initial = default
            field_id = field_name
            
        elif isinstance(f, (str, unicode)):
            field_name, query_key = expand_search_field(model_class, f)
            if f.startswith('?'):
                field = forms.fields.ChoiceField(choices=((ANY, '---------'), (YES, u'Yes'), (NO, u'No')), label=get_model_field(model, field_name).verbose_name)
                default = boolean_to_choice(default)
                #field = forms.fields.BooleanField(label=model._meta.get_field_by_name(field_name)[0].verbose_name)
            else:
                field = get_model_field(model, field_name).formfield()
                if field is None:
                    raise Exception("%s.%s has no formfield"%(model.__class__, field_name))
                if get_model_field(model, field_name).default != django.db.models.fields.NOT_PROVIDED:
                    default = get_model_field(model, field_name).default
                else:
                    default = None
                field.empty = False
            field.initial = default
            field_id = field_name
    
        field.widget.attrs['class'] = field.__class__.__name__
        field.required = False
        
        field.help_text = None
        fields[field_id] = field
    return fields

def boolean_to_choice(b):
    if b not in EMPTY_VALUES:
        if b:
            return YES
        else:
            return NO

def get_model_search_query(model_class, search_fields, form, request):
    from o9.forms import SearchField

    if form.is_valid():
        search = {}
        for f in search_fields:
            
            if isinstance(f, SearchField):
                field_name = f.field_name
                field_id = f.field_id
                query_key = f.query_key
            
            elif isinstance(f, (list, tuple)):
                if len(f) == 4:
                    field_name, default, query_key, field_id = f
                elif len(f) == 3:
                    field_name, default, query_key = f
                    field_id = field_name
                else:
                    field_name, default = f
                    field_name, query_key = expand_search_field(model_class, field_name)
                    field_id = field_name
            elif isinstance(f, (str, unicode)):
                field_name, query_key = expand_search_field(model_class, f)
                field_id = field_name
                
            if form.cleaned_data[field_id] not in EMPTY_VALUES:
                if query_key.endswith('__isnull'):
                    if int(form.cleaned_data[field_id]) in (YES, NO):
                        search[query_key] = int(form.cleaned_data[field_id]) == NO
                else:
                    search[query_key] = form.cleaned_data[field_id]
                
        if len(search) > 0:
            return model_class.objects.filter(**search)
        else:
            return model_class.objects.all()
    else:
        return model_class.objects.none()
    
def get_model_search_values(model_class, search_fields, request):
    from o9.forms import SearchField
    search = {}
    for f in search_fields:
        if isinstance(f, SearchField):
            field_name = f.field_name
            field_id = f.field_id
            default = f.default or ''
            query_key = f.query_key

        elif isinstance(f, (list, tuple)):
            if len(f) == 4:
                field_name, default, query_key, field_id = f
            elif len(f) == 3:
                field_name, default, query_key = f
                field_id = field_name
            else:
                field_name, default = f
                field_name, query_key = expand_search_field(model_class, field_name)
                field_id = field_name

        elif isinstance(f, (str, unicode)):
            field_name, query_key = expand_search_field(model_class, f)
            field_id = field_name
            default = ''
        else:
            raise Exception("Unknown field type: %s (%s)" % (type(f), repr(f)))

        if query_key is not None and query_key.endswith('__isnull'):
            default = boolean_to_choice(default)
            
        if request.has_key(field_id):
            search[field_id] = request.get(field_id, '')
        else:
            search[field_id] = default
    return search
    
def get_model_search_params(model_class, search_fields, form, request):
    from o9.forms import SearchField
    search = {}
    if form.is_valid():
        for f in search_fields:
            if isinstance(f, SearchField):
                field_name = f.field_name
                field_id = f.field_id
                default = f.default or ''
                query_key = f.query_key

            elif isinstance(f, (list, tuple)):
                field_name, default = f
                if len(f) == 4:
                    field_name, default, query_key, field_id = f
                elif len(f) == 3:
                    field_name, default, query_key = f
                    field_id = field_name
                else:
                    field_name, default = f
                    field_name, query_key = expand_search_field(model_class, field_name)
                    field_id = field_name

            elif isinstance(f, (str, unicode)):
                field_name, query_key = expand_search_field(model_class, f)
                if get_model_field(model_class, field_name).default != django.db.models.fields.NOT_PROVIDED:
                    default = get_model_field(model_class, field_name).default
                else:
                    default = ''
                field_id = field_name
            
            if query_key is not None and query_key.endswith('__isnull'):
                default = boolean_to_choice(default)
            
            if request.has_key(field_id):
                search[field_id] = request.get(field_id, '')
            else:
                search[field_id] = default
    return search
    

def get_model_result_fields(model_class, result_fields):
    
    if result_fields is not None:
        return result_fields
    elif hasattr(model_class, 'o9_result_fields'):
        return model_class.o9_result_fields
    else:
        return [f.name for f in model_class._meta.fields if f.name != "id" and not f.name.endswith("_ptr")]

def get_model_export_fields(model_class, export_fields):
    
    if export_fields is not None:
        return export_fields
    elif hasattr(model_class, 'o9_export_fields'):
        return model_class.o9_export_fields
    else:
        return [f.name for f in model_class._meta.fields if not f.name.endswith("_ptr") ]

def get_model_display_fields(model_class, display_fields=None):
    
    if display_fields is not None:
        return display_fields
    elif hasattr(model_class, 'o9_display_fields') and model_class.o9_display_fields is not None:
        return model_class.o9_display_fields
    else:
        return [f.name for f in model_class._meta.fields + model_class._meta.many_to_many if f.name != "id" and not f.name.endswith("_ptr")]

def corefilter_to_data(model):
    filters = model.core_filters
    data = {}
    #print "Getting data from %s core_filters" % model
    
    for (filter, value) in filters.items():
        #print "%s Filter: %s: %s" % (model, filter, value)
        fields = filter.split('__')
        field_name = fields[0]
        #print "Field_name: %s" % field_name
        while len(fields) > 0:
            name = fields[0]
            fields = fields[1:]
            #print "Name: %s" % name
            try:
                if model.__class__.__name__ == 'ManyRelatedManager' or model.__class__.__name__ == 'RelatedManager':
                    mf = model.model._meta.get_field(name)
                else:
                    mf = model._meta.get_field(name)
                    
                if mf is not None and isinstance(mf, django.db.models.ForeignKey):
                    #print "%s is a ForeignKey, traversing..." % name
                    model = mf.rel.to()
            except:
                #print "ERROR: model: %s has not field %s" % (model.__class__.__name__, name)
                pass
        
        #print "Model is %s" % model.__class__.__name__
        if model.__class__.__name__ == 'ManyRelatedManager' or model.__class__.__name__ == 'RelatedManager':
            #print "Model is a RelatedManager"
            for f in model.model._meta.fields:
                #print "Checking field %s" % f.name
                if f.column == name:
                    #print "Matched column %s" % f.column
                    data[field_name] = value
        elif isinstance(model, django.db.models.Model):
            #print "Model is a Model"
            for f in model._meta.fields:
                #print "Checking field %s" % f.name
                if f.column == name:
                    #print "Matched column %s" % f.column
                    data[field_name] = value
        else:
            data[field_name] = value
    return data