Beispiel #1
0
def read_source(request, app_name, model_name, user):
    '''
    ' Returns - Dictionary serialized as json:
    '           'data' - paged data from a given model
    '           'page_list' - page buttons html
    '           'errors' - Errors reported to client.
    '
    ' Keyword Args:
    '    app_name     - (string) The application the desired model resides in
    '    model_name   - (string) The model name to get serialized data from
    '    user         - (AuthUser) The authenticated AuthUser object making the request
    '''

    result_info = {}
    get_editable = False
    try:
        jsonData = json.loads(request.GET.get('jsonData'))
    except:
        print "No valid json data found"
    else:
        if 'result_info' in jsonData:
            result_info = jsonData['result_info']
        if 'get_editable' in jsonData:
            get_editable = jsonData['get_editable']

    if 'filter_args' in result_info:
        filter_args = result_info['filter_args']
    else:
        filter_args = None

    kwargs = None
    omni = None
    if filter_args is not None:
        kwargs = {}
        for i in filter_args:
            if i['col'] == 'chucho-omni':
                omni = i['val']
            else:
                cols = i['col'].split('|')
                if len(cols) > 1:
                    keyword = cols[0] + '__' + filter_operators[i['oper']]
                    tmp = {}
                    kwargs[keyword] = tmp

                    for index, c in enumerate(cols[1:], start=1):
                        keyword = c + '__' + filter_operators[i['oper']]
                        if index < len(cols) - 1:
                            tmp[keyword] = {}
                            tmp = tmp[keyword]
                        else:
                            tmp[keyword] = i['val']

                else:
                    keyword = i['col'] + '__' + filter_operators[i['oper']]
                    kwargs[keyword] = i['val']

    cls = apps.get_model(app_name, model_name)

    read_only = False
    try:
        # Only get the objects that can be edited by the user logged in
        if get_editable and cls.objects.can_edit(user):
            objs = cls.objects.get_editable(user, kwargs, omni)
        else:
            objs = cls.objects.get_viewable(user, kwargs, omni)
            read_only = True
    except Exception as e:
        stderr.write('Unknown error occurred in read_source: %s: %s\n' % (type(e), e.message))
        stderr.flush()
        dump = json.dumps({'errors': 'Unknown error occurred in read_source: %s: %s' % (type(e), e.message)}, indent=4)
        return HttpResponse(dump, content_type="application/json")

    extras = {'read_only': read_only}

    # Order the data
    if 'sort_columns' in result_info and result_info['sort_columns'] is not None:
        sign = ""
        sort_arg = result_info['sort_columns']['columnId']
        if not result_info['sort_columns']['sortAsc']:
            sign = "-"

        # Foreign Key relations get ordered normally. They throw an exception otherwise...
        # the update to django 1.10 ment we couldn't use: f, mode, direct, m2m = cls._meta.get_field_by_name(sort_arg)
        # and so instead we now use:
        f = cls._meta.get_field(sort_arg)
        # these are probably unnessisary:
        # model = cls
        # direct = not f.auto_created or f.concrete
        # m2m = f.many_to_many

        if isinstance(f, models.CharField) or isinstance(f, models.TextField):
            objs = objs.extra(select={'lower_'+sort_arg: 'lower('+sort_arg+')'}).order_by(sign+'lower_'+sort_arg)
        else:
            objs = objs.order_by(sign+sort_arg)

    # Break the data into pages
    if 'page' in result_info and 'per_page' in result_info:
        paginator = Paginator(objs, result_info['per_page'])
        try:
            objs = paginator.page(result_info['page'])
        except PageNotAnInteger:
            objs = paginator.page(1)
        except EmptyPage:
            objs = paginator.page(paginator.num_pages)

        # Creat list of pages to render links for
        pages = []
        for i in paginator.page_range:
            if i == objs.number or \
                    i <= 3 or \
                    (i <= objs.number + 2 and i >= objs.number - 2) or \
                    (i <= paginator.num_pages and i >= paginator.num_pages - 2):
                if len(pages) > 0 and i - 1 > pages[-1]:
                    pages.append(-1)
                pages.append(i)

        t_pages = loader.get_template('page_list.html')
        c_pages = Context({'curr_page': objs, 'pages': pages})
        extras['page_list'] = t_pages.render(c_pages)

    return HttpResponse(serialize_model_objs(objs, extras), content_type="application/json")
Beispiel #2
0
def update(request, app_name, model_name, user, id=None):
    '''
    ' Modifies a model object with the given data, saves it to the db and
    ' returns it as serialized json.
    '
    ' Keyword Args:
    '    model_name  - The name of the model object to modify.
    '    data - The data to modify the object with.
    '
    ' Returns:
    '    The modified object serialized as json.
    '''

    try:
        data = json.loads(request.body)
    except:
        transaction.rollback()
        dump = json.dumps({'errors': 'Error loading json'}, indent=4)
        return HttpResponse(dump, content_type="application/json")

    cls = apps.get_model(app_name, model_name)
    if id is None:
        if not cls.objects.can_edit(user):
            transaction.rollback()
            dump = json.dumps({'errors': 'User %s does not have permission to add to this table.' % str(user)}, indent=4)
            return HttpResponse(dump, content_type="application/json")
        obj = cls()
    else:
        try:
            obj = cls.objects.get_editable_by_pk(user, pk=id)
            if obj is None:
                transaction.rollback()
                dump = json.dumps({'errors': 'User %s does not have permission to edit this object' % str(user)}, indent=4)
                return HttpResponse(dump, content_type="application/json")
        except Exception as e:
            transaction.rollback()
            dump = json.dumps({'errors': 'Cannot load object to save: Exception: ' + e.message}, indent=4)
            return HttpResponse(dump, content_type="application/json")

    try:
        fields = gen_columns(obj)
    except Exception as e:
        transaction.rollback()
        dump = json.dumps({'errors': 'Error generating columns: ' + e.message}, indent=4)
        return HttpResponse(dump, content_type="application/json")

    m2m = []
    try:
        for field in fields:
            if field['_editable']:

                # save inportant m2m stuff for after object save
                if field['_type'] == 'm2m':
                    m2m.append({
                        'field': field['field'],
                        'model_name': field['model_name'],
                        'app': field['app']
                    })
                    continue

                # Handle empy data
                elif data[field['field']] in [None, ''] and field['_type'] != 'password':
                    if field['_type'] in ['text', 'char', 'color']:
                        setattr(obj, field['field'], '')
                    else:
                        setattr(obj, field['field'], None)

                elif field['_type'] == 'foreignkey':
                    rel_cls = apps.get_model(field['app'], field['model_name'])
                    if data[field['field']]['pk'] is None:
                        rel_obj = None
                    else:
                        rel_obj = rel_cls.objects.get(pk=data[field['field']]['pk'])

                    if rel_obj is None or rel_obj.can_view(user):
                        setattr(obj, field['field'], rel_obj)
                    else:
                        transaction.rollback()
                        error = 'Error: You do not have permission to assign this object: %s' % rel_obj
                        return HttpResponse(json.dumps({'errors': error}, indent=4), content_type="application/json")

                elif field['_type'] == 'datetime':
                    dt_obj = None
                    if settings.USE_TZ and data[field['field']] not in (None, u""):
                        dt_obj = make_aware(datetime.utcfromtimestamp(float(data[field['field']])), utc)
                    elif not settings.USE_TZ and data[field['field']] not in (None, u""):
                        aware_dt_obj = make_aware(datetime.utcfromtimestamp(float(data[field['field']])), utc)
                        dt_obj = make_naive(aware_dt_obj, get_current_timezone())

                    setattr(obj, field['field'], dt_obj)

                elif field['_type'] == 'date':
                    dt_obj = datetime.strptime(data[field['field']], settings.D_FORMAT)
                    setattr(obj, field['field'], dt_obj.date())

                elif field['_type'] == 'password':
                    if data[field['field']] not in [None, '']:
                        obj.set_password(data[field['field']])

                else:
                    setattr(obj, field['field'], data[field['field']])
        obj.save()

        try:
            # Get all respective objects for many to many fields and add them in.
            for m in m2m:
                cls = apps.get_model(m['app'], m['model_name'])
                m2m_objs = []
                for m2m_obj in data[m['field']]:
                    rel_obj = cls.objects.get(pk=m2m_obj['pk'])
                    if rel_obj.can_view(user):
                        m2m_objs.append(rel_obj)
                    else:
                        transaction.rollback()
                        error = 'Error: You do not have permission to assign this object: %s' % rel_obj
                        return HttpResponse(json.dumps({'errors': error}, indent=4), content_type="application/json")

                setattr(obj, m['field'], m2m_objs)

        except Exception as e:
            transaction.rollback()
            error = 'Error setting ManyToMany fields: %s: %s' % (type(e), e.message)
            stderr.write(error)
            stderr.flush()
            transaction.rollback()
            return HttpResponse(json.dumps({'errors': error}, indent=4), content_type="application/json")

    except Exception as e:
        transaction.rollback()
        error = 'In ajax update exception: %s: %s\n' % (type(e), e.message)
        stderr.write(error)
        stderr.flush()
        return HttpResponse(json.dumps({'errors': error}, indent=4), content_type="application/json")

    # Run validations
    try:
        obj.full_clean()
    except ValidationError as e:
        transaction.rollback()
        errors = 'ValiationError '
        for field_name, error_messages in e.message_dict.items():
            errors += ' ::Field: %s: Errors: %s ' % (field_name, ','.join(error_messages))

        return HttpResponse(json.dumps({'errors': errors}, indent=4), content_type="application/json")

    try:
        serialized_model = serialize_model_objs([obj.__class__.objects.get(pk=obj.pk)], {'read_only': True})
    except Exception as e:
        transaction.rollback()
        error = 'In ajax update exception: %s: %s\n' % (type(e), e.message)
        stderr.write(error)
        stderr.flush()
        return HttpResponse(json.dumps({'errors': error}, indent=4), content_type="application/json")

    transaction.commit()
    response = HttpResponse(serialized_model, content_type="application/json")
    response.status_code = 201
    return response