Esempio n. 1
0
 def get_or_create_quota(self, scope):
     if not self._can_quota_be_created_for_scope(scope):
         raise exceptions.CreationConditionFailedQuotaError(
             'Wrong scope: Cannot create quota "%s" for scope "%s".' %
             (self.name, scope))
     defaults = {
         'limit':
         self.default_limit(scope)
         if six.callable(self.default_limit) else self.default_limit,
         'usage':
         self.default_usage(scope)
         if six.callable(self.default_usage) else self.default_usage,
     }
     return scope.quotas.get_or_create(name=self.name, defaults=defaults)
Esempio n. 2
0
def get_resource_for_object(obj):
    """Return the resource for an object.

    Args:
        obj: The object whose model has a resource associated.

    Returns:
        WebAPIResource:
        The resource associated with the object, or ``None`` if not found.
    """
    from djblets.webapi.resources.base import WebAPIResource

    cls = obj.__class__

    # Deferred models are a subclass of the actual model that we want to look
    # up.
    if getattr(obj, '_deferred', False):
        cls = cls.__bases__[0]

    resource = _model_to_resources.get(cls, None)

    if not isinstance(resource, WebAPIResource) and six.callable(resource):
        resource = resource(obj)

    return resource
Esempio n. 3
0
    def render_data(self, state, obj):
        """Renders the column data to a string. This may contain HTML."""
        id_field = '%s_id' % self.field_name

        # Look for this directly so that we don't end up fetching the
        # data for the object.
        if id_field in obj.__dict__:
            pk = obj.__dict__[id_field]

            if pk in state.data_cache:
                return state.data_cache[pk]
            else:
                value = getattr(obj, self.field_name)
                state.data_cache[pk] = escape(value)
                return value
        else:
            # Follow . separators like in the django template library
            value = obj
            for field_name in self.field_name.split('.'):
                if field_name:
                    value = getattr(value, field_name)

                    if six.callable(value):
                        value = value()

            return escape(value)
Esempio n. 4
0
    def get_fieldsets(self, request, obj=None):
        """
        Customize the fieldsets according to the app settings

        :param request: request
        :param obj: post
        :return: fieldsets configuration
        """
        app_config_default = self._app_config_select(request, obj)
        if app_config_default is None and request.method == 'GET':
            return super(PostAdmin, self).get_fieldsets(request, obj)
        if not obj:
            config = app_config_default
        else:
            config = obj.app_config

        fsets = deepcopy(self._fieldsets)
        if config:
            if config.use_abstract:
                fsets[0][1]['fields'].append('abstract')
            if not config.use_placeholder:
                fsets[0][1]['fields'].append('post_text')
        else:
            if get_setting('USE_ABSTRACT'):
                fsets[0][1]['fields'].append('abstract')
            if not get_setting('USE_PLACEHOLDER'):
                fsets[0][1]['fields'].append('post_text')
        if get_setting('MULTISITE') and not self.has_restricted_sites(request):
            fsets[1][1]['fields'][0].append('sites')
        if request.user.is_superuser:
            fsets[1][1]['fields'][0].append('author')
        filter_function = get_setting('ADMIN_POST_FIELDSET_FILTER')
        if callable(filter_function):
            fsets = filter_function(fsets, request, obj=obj)
        return fsets
Esempio n. 5
0
    def render_cell(self, state, obj, render_context):
        """Renders the table cell containing column data."""
        datagrid = state.datagrid
        rendered_data = self.render_data(state, obj)
        url = ''
        css_class = ''

        if self.link:
            try:
                url = self.link_func(state, obj, rendered_data)
            except AttributeError:
                pass

        if self.css_class:
            if six.callable(self.css_class):
                css_class = self.css_class(obj)
            else:
                css_class = self.css_class

        key = "%s:%s:%s:%s" % (state.last, rendered_data, url, css_class)

        if key not in state.cell_render_cache:
            ctx = Context(render_context)
            ctx.update({
                'column': self,
                'column_state': state,
                'css_class': css_class,
                'url': url,
                'data': mark_safe(rendered_data)
            })

            state.cell_render_cache[key] = \
                mark_safe(datagrid.cell_template_obj.render(ctx))

        return state.cell_render_cache[key]
Esempio n. 6
0
    def get_context_data(self, name, value, attrs=None, bound_field=None):
        ctx = super(CropDusterWidget,
                    self).get_context_data(name, value, attrs, bound_field)
        sizes = self.sizes
        related_object = ctx['instance']
        preview_url = ''
        preview_w = PREVIEW_WIDTH
        preview_h = PREVIEW_HEIGHT
        if related_object:
            preview_url = related_object.get_image_url(size_name='_preview')
            orig_width, orig_height = related_object.width, related_object.height
            if (orig_width and orig_height):
                resize_ratio = min(PREVIEW_WIDTH / float(orig_width),
                                   PREVIEW_HEIGHT / float(orig_height))
                if resize_ratio < 1:
                    preview_w = int(round(orig_width * resize_ratio))
                    preview_h = int(round(orig_height * resize_ratio))

        if six.callable(sizes):
            instance = getattr(getattr(bound_field, 'form', None), 'instance',
                               None)
            try:
                sizes_callable = six.get_method_function(sizes)
            except AttributeError:
                sizes_callable = sizes
            sizes = sizes_callable(instance, related=related_object)
        sizes = [s for s in sizes if not getattr(s, 'is_alias', False)]

        ctx.update({
            'sizes': json.dumps(sizes),
            'preview_url': preview_url,
            'preview_w': preview_w,
            'preview_h': preview_h,
        })
        return ctx
Esempio n. 7
0
def apply_django_settings(siteconfig, settings_map=None):
    """
    Applies all settings from the site configuration to the Django settings
    object.
    """
    if settings_map is None:
        settings_map = get_django_settings_map()

    for key, setting_data in six.iteritems(settings_map):
        if key in siteconfig.settings:
            value = siteconfig.get(key)
            setter = setattr

            if isinstance(setting_data, dict):
                setting_key = setting_data['key']

                if 'setter' in setting_data:
                    setter = setting_data['setter']

                if ('deserialize_func' in setting_data and
                    six.callable(setting_data['deserialize_func'])):
                    value = setting_data['deserialize_func'](value)
            else:
                setting_key = setting_data

            setter(settings, setting_key, value)
Esempio n. 8
0
def apply_django_settings(siteconfig, settings_map=None):
    """
    Applies all settings from the site configuration to the Django settings
    object.
    """
    if settings_map is None:
        settings_map = get_django_settings_map()

    for key, setting_data in six.iteritems(settings_map):
        if key in siteconfig.settings:
            value = siteconfig.get(key)
            setter = setattr

            if isinstance(setting_data, dict):
                setting_key = setting_data['key']

                if 'setter' in setting_data:
                    setter = setting_data['setter']

                if ('deserialize_func' in setting_data
                        and six.callable(setting_data['deserialize_func'])):
                    value = setting_data['deserialize_func'](value)
            else:
                setting_key = setting_data

            setter(settings, setting_key, value)
Esempio n. 9
0
    def render_data(self, state, obj):
        """Renders the column data to a string. This may contain HTML."""
        id_field = '%s_id' % self.field_name

        # Look for this directly so that we don't end up fetching the
        # data for the object.
        if id_field in obj.__dict__:
            pk = obj.__dict__[id_field]

            if pk in state.data_cache:
                return state.data_cache[pk]
            else:
                value = getattr(obj, self.field_name)
                state.data_cache[pk] = escape(value)
                return value
        else:
            # Follow . separators like in the django template library
            value = obj
            for field_name in self.field_name.split('.'):
                if field_name:
                    value = getattr(value, field_name)

                    if six.callable(value):
                        value = value()

            return escape(value)
Esempio n. 10
0
    def get_fieldsets(self, request, obj=None):
        """
        Customize the fieldsets according to the app settings
        :param request: request
        :param obj: post
        :return: fieldsets configuration
        """
        app_config_default = self._app_config_select(request, obj)
        if app_config_default is None and request.method == 'GET':
            return super(PostAdmin, self).get_fieldsets(request, obj)
        if not obj:
            config = app_config_default
        else:
            config = obj.app_config

        fsets = deepcopy(self._fieldsets)
        if config:
            if config.use_abstract:
                fsets[0][1]['fields'].append('abstract')
            if not config.use_placeholder:
                fsets[0][1]['fields'].append('post_text')
        else:
            if get_setting('USE_ABSTRACT'):
                fsets[0][1]['fields'].append('abstract')
            if not get_setting('USE_PLACEHOLDER'):
                fsets[0][1]['fields'].append('post_text')
        if get_setting('MULTISITE'):
            fsets[1][1]['fields'][0].append('sites')
        if request.user.is_superuser:
            fsets[1][1]['fields'][0].append('author')
        filter_function = get_setting('ADMIN_POST_FIELDSET_FILTER')
        if callable(filter_function):
            fsets = filter_function(fsets, request, obj=obj)
        return fsets
Esempio n. 11
0
def get_resource_for_object(obj):
    """Return the resource for an object.

    Args:
        obj: The object whose model has a resource associated.

    Returns:
        WebAPIResource:
        The resource associated with the object, or ``None`` if not found.
    """
    from djblets.webapi.resources.base import WebAPIResource

    cls = obj.__class__

    # Deferred models are a subclass of the actual model that we want to look
    # up.
    if getattr(obj, '_deferred', False):
        cls = cls.__bases__[0]

    resource = _model_to_resources.get(cls, None)

    if not isinstance(resource, WebAPIResource) and six.callable(resource):
        resource = resource(obj)

    return resource
Esempio n. 12
0
    def get_fieldsets(self, request, obj=None):
        app_config_default = self._app_config_select(request, obj)
        if app_config_default is None and request.method == "GET":
            return super(PostAdmin, self).get_fieldsets(request, obj)
        if not obj:
            config = app_config_default
        else:
            config = obj.app_config

        fsets = deepcopy(self._fieldsets)
        if config:
            if config.use_abstract:
                fsets[0][1]["fields"].append("abstract")
            if not config.use_placeholder:
                fsets[0][1]["fields"].append("post_text")
        else:
            if get_setting("USE_ABSTRACT"):
                fsets[0][1]["fields"].append("abstract")
            if not get_setting("USE_PLACEHOLDER"):
                fsets[0][1]["fields"].append("post_text")
        if get_setting("MULTISITE"):
            fsets[1][1]["fields"][0].append("sites")
        if request.user.is_superuser:
            fsets[1][1]["fields"][0].append("author")
        filter_function = get_setting("ADMIN_POST_FIELDSET_FILTER")
        if callable(filter_function):
            fsets = filter_function(fsets, request, obj=obj)
        return fsets
Esempio n. 13
0
    def effective_default(self, field):
        """
        Returns a field's effective database default value
        """
        if field.has_default():
            # 如果有默认值,则使用默认值
            default = field.get_default()
        elif not field.null and field.blank and field.empty_strings_allowed:
            # 如果不允许为空,但是django运行不输入数据(对应的input就不回传服务器), 则使用空字符串
            if field.get_internal_type() == "BinaryField":
                default = six.binary_type()
            else:
                default = six.text_type()
        else:
            default = None

        # If it's a callable, call it
        # default可以为函数(这个需要注意?)
        if six.callable(default):
            default = default()

        # Run it through the field's get_db_prep_save method so we can send it
        # to the database.
        default = field.get_db_prep_save(default, self.connection)
        return default
Esempio n. 14
0
    def effective_default(self, field):
        """
        Returns a field's effective database default value
        """
        if field.has_default():
            # 如果有默认值,则使用默认值
            default = field.get_default()
        elif not field.null and field.blank and field.empty_strings_allowed:
            # 如果不允许为空,但是django运行不输入数据(对应的input就不回传服务器), 则使用空字符串
            if field.get_internal_type() == "BinaryField":
                default = six.binary_type()
            else:
                default = six.text_type()
        else:
            default = None

        # If it's a callable, call it
        # default可以为函数(这个需要注意?)
        if six.callable(default):
            default = default()

        # Run it through the field's get_db_prep_save method so we can send it
        # to the database.
        default = field.get_db_prep_save(default, self.connection)
        return default
Esempio n. 15
0
    def get_link_serializer(self, field):
        """Return the function to use for serializing a link field."""
        serialize_link_func = getattr(self, 'serialize_%s_link' % field, None)

        if not serialize_link_func or not six.callable(serialize_link_func):
            serialize_link_func = self.serialize_link

        return serialize_link_func
Esempio n. 16
0
    def _reinit(self, model_instance):
        """Re-initialize the value in the database from the initializer.

        Args:
            model_instance (django.db.models.Model):
                The model instance containing the field to re-initialize.
        """
        if not (model_instance.pk or self._initializer
                or six.callable(self._initializer)):
            # We don't want to end up defaulting this to 0 if creating a
            # new instance unless an initializer is provided. Instead,
            # we'll want to handle this the next time the object is
            # accessed.
            return

        value = 0

        if self._initializer:
            if isinstance(self._initializer, QueryExpressionType):
                value = self._initializer
            elif six.callable(self._initializer):
                model_instance_id = id(model_instance)
                self._locks[model_instance_id] = 1
                value = self._initializer(model_instance)
                del self._locks[model_instance_id]

        if value is not None:
            is_expr = isinstance(value, QueryExpressionType)

            if is_expr and not model_instance.pk:
                value = 0
                is_expr = False

            if is_expr:
                cls = model_instance.__class__
                cls.objects.filter(pk=model_instance.pk).update(
                    **{
                        self.attname: value,
                    })

                self._reload_model_instance(model_instance, [self.attname])
            else:
                setattr(model_instance, self.attname, value)

                if model_instance.pk:
                    model_instance.save(update_fields=[self.attname])
Esempio n. 17
0
 def scope_default_limit(self, scope, value=None):
     attr_name = '_default_quota_limit_%s' % self.name
     if value is not None:
         setattr(scope, attr_name, value)
     try:
         return getattr(scope, attr_name)
     except AttributeError:
         return self.default_limit(scope) if six.callable(self.default_limit) else self.default_limit
Esempio n. 18
0
    def _reinit(self, model_instance):
        """Re-initialize the value in the database from the initializer.

        Args:
            model_instance (django.db.models.Model):
                The model instance containing the field to re-initialize.
        """
        if not (model_instance.pk or self._initializer or
                six.callable(self._initializer)):
            # We don't want to end up defaulting this to 0 if creating a
            # new instance unless an initializer is provided. Instead,
            # we'll want to handle this the next time the object is
            # accessed.
            return

        value = 0

        if self._initializer:
            if isinstance(self._initializer, QueryExpressionType):
                value = self._initializer
            elif six.callable(self._initializer):
                model_instance_id = id(model_instance)
                self._locks[model_instance_id] = 1
                value = self._initializer(model_instance)
                del self._locks[model_instance_id]

        if value is not None:
            is_expr = isinstance(value, QueryExpressionType)

            if is_expr and not model_instance.pk:
                value = 0
                is_expr = False

            if is_expr:
                cls = model_instance.__class__
                cls.objects.filter(pk=model_instance.pk).update(**{
                    self.attname: value,
                })

                self._reload_model_instance(model_instance, [self.attname])
            else:
                setattr(model_instance, self.attname, value)

                if model_instance.pk:
                    model_instance.save(update_fields=[self.attname])
Esempio n. 19
0
def get_jpeg_quality(width, height):
    if six.callable(CROPDUSTER_JPEG_QUALITY):
        return CROPDUSTER_JPEG_QUALITY(width, height)
    elif isinstance(CROPDUSTER_JPEG_QUALITY, (int, float)):
        return CROPDUSTER_JPEG_QUALITY
    else:
        raise ImproperlyConfigured(
            "CROPDUSTER_JPEG_QUALITY setting must be either a callable "
            "or a numeric value, got type %s" % (type(CROPDUSTER_JPEG_QUALITY).__name__))
Esempio n. 20
0
    def get_link_serializer(self, field):
        """Return the function to use for serializing a link field."""
        serialize_link_func = getattr(self, 'serialize_%s_link' % field,
                                      None)

        if not serialize_link_func or not six.callable(serialize_link_func):
            serialize_link_func = self.serialize_link

        return serialize_link_func
Esempio n. 21
0
def get_jpeg_quality(width, height):
    if six.callable(CROPDUSTER_JPEG_QUALITY):
        return CROPDUSTER_JPEG_QUALITY(width, height)
    elif isinstance(CROPDUSTER_JPEG_QUALITY, (int, float)):
        return CROPDUSTER_JPEG_QUALITY
    else:
        raise ImproperlyConfigured(
            "CROPDUSTER_JPEG_QUALITY setting must be either a callable "
            "or a numeric value, got type %s" %
            (type(CROPDUSTER_JPEG_QUALITY).__name__))
Esempio n. 22
0
 def database_backwards(self, app_label, schema_editor, from_state, to_state):
     if self.reverse_code is None:
         raise NotImplementedError("You cannot reverse this operation")
     elif six.callable(self.reverse_code):
         self.reverse_code(models=from_state.render(), schema_editor=schema_editor)
     else:
         context = {
             "models": from_state.render(),
             "schema_editor": schema_editor,
         }
         eval(self.reverse_code, context)
Esempio n. 23
0
        def _reinit(model_instance):
            """Re-initializes the value in the database from the initializer."""
            if not (model_instance.pk or self._initializer or
                    six.callable(self._initializer)):
                # We don't want to end up defaulting this to 0 if creating a
                # new instance unless an initializer is provided. Instead,
                # we'll want to handle this the next time the object is
                # accessed.
                return

            if self._initializer and six.callable(self._initializer):
                self._locks[model_instance] = 1
                value = self._initializer(model_instance)
                del self._locks[model_instance]
            else:
                value = 0

            setattr(model_instance, self.attname, value)

            if model_instance.pk:
                model_instance.save()
Esempio n. 24
0
 def get_context_data(self, name, value, attrs=None, bound_field=None):
     ctx = super(CropDusterWidget, self).get_context_data(name, value, attrs, bound_field)
     sizes = self.sizes
     if six.callable(sizes):
         instance = getattr(getattr(bound_field, 'form', None), 'instance', None)
         related_object = ctx['instance']
         sizes_callable = getattr(sizes, 'im_func', sizes)
         sizes = sizes_callable(instance, related=related_object)
     sizes = [s for s in sizes if not getattr(s, 'is_alias', False)]
     ctx.update({
         'sizes': json.dumps(sizes),
     })
     return ctx
Esempio n. 25
0
 def database_forwards(self, app_label, schema_editor, from_state, to_state):
     # We now execute the Python code in a context that contains a 'models'
     # object, representing the versioned models as an AppCache.
     # We could try to override the global cache, but then people will still
     # use direct imports, so we go with a documentation approach instead.
     if six.callable(self.code):
         self.code(models=from_state.render(), schema_editor=schema_editor)
     else:
         context = {
             "models": from_state.render(),
             "schema_editor": schema_editor,
         }
         eval(self.code, context)
Esempio n. 26
0
 def database_backwards(self, app_label, schema_editor, from_state,
                        to_state):
     if self.reverse_code is None:
         raise NotImplementedError("You cannot reverse this operation")
     elif six.callable(self.reverse_code):
         self.reverse_code(models=from_state.render(),
                           schema_editor=schema_editor)
     else:
         context = {
             "models": from_state.render(),
             "schema_editor": schema_editor,
         }
         eval(self.reverse_code, context)
Esempio n. 27
0
 def effective_default(self, field):
     """
     Returns a field's effective database default value
     """
     if field.has_default():
         default = field.get_default()
     elif not field.null and field.blank and field.empty_strings_allowed:
         default = ""
     else:
         default = None
     # If it's a callable, call it
     if callable(default):
         default = default()
     return default
Esempio n. 28
0
 def database_forwards(self, app_label, schema_editor, from_state,
                       to_state):
     # We now execute the Python code in a context that contains a 'models'
     # object, representing the versioned models as an AppCache.
     # We could try to override the global cache, but then people will still
     # use direct imports, so we go with a documentation approach instead.
     if six.callable(self.code):
         self.code(models=from_state.render(), schema_editor=schema_editor)
     else:
         context = {
             "models": from_state.render(),
             "schema_editor": schema_editor,
         }
         eval(self.code, context)
Esempio n. 29
0
 def effective_default(self, field):
     """
     Returns a field's effective database default value
     """
     if field.has_default():
         default = field.get_default()
     elif not field.null and field.blank and field.empty_strings_allowed:
         default = ""
     else:
         default = None
     # If it's a callable, call it
     if callable(default):
         default = default()
     return default
Esempio n. 30
0
def migrate_settings(siteconfig):
    """
    Migrates any settings we want in the database from the settings file.
    """
    # Convert everything in the table.
    for siteconfig_key, setting_data in six.iteritems(migration_table):
        if isinstance(setting_data, dict):
            setting_key = setting_data['key']
            serialize_func = setting_data.get('serialize_func', None)
        else:
            setting_key = setting_data
            serialize_func = None

        default = defaults.get(siteconfig_key, None)
        value = getattr(settings, setting_key, default)

        if serialize_func and six.callable(serialize_func):
            value = serialize_func(value)

        siteconfig.set(siteconfig_key, value)

    # This may be a tuple in a tuple, or it may just be a tuple.
    if type(settings.ADMINS[0]) == tuple:
        admin = settings.ADMINS[0]
    else:
        admin = settings.ADMINS

    siteconfig.set('site_admin_name', admin[0])
    siteconfig.set('site_admin_email', admin[1])

    # Try to transform the authentication backend
    remaining_backends = []
    known_backends = []

    for auth_backend in settings.AUTHENTICATION_BACKENDS:
        if auth_backend in auth_backend_map:
            known_backends.append(auth_backend)
        else:
            remaining_backends.append(auth_backend)

    if remaining_backends or len(known_backends) > 1:
        # The user has some custom backend set. Just set the entire list
        siteconfig.set('auth_backend', 'custom')
        siteconfig.set('auth_custom_backends',
                       settings.AUTHENTICATION_BACKENDS)
    elif len(known_backends) == 1:
        siteconfig.set('auth_backend', auth_backend_map[known_backends[0]])
    else:
        siteconfig.set('auth_backend', 'builtin')
Esempio n. 31
0
def migrate_settings(siteconfig):
    """
    Migrates any settings we want in the database from the settings file.
    """
    # Convert everything in the table.
    for siteconfig_key, setting_data in six.iteritems(migration_table):
        if isinstance(setting_data, dict):
            setting_key = setting_data['key']
            serialize_func = setting_data.get('serialize_func', None)
        else:
            setting_key = setting_data
            serialize_func = None

        default = defaults.get(siteconfig_key, None)
        value = getattr(settings, setting_key, default)

        if serialize_func and six.callable(serialize_func):
            value = serialize_func(value)

        siteconfig.set(siteconfig_key, value)

    # This may be a tuple in a tuple, or it may just be a tuple.
    if type(settings.ADMINS[0]) == tuple:
        admin = settings.ADMINS[0]
    else:
        admin = settings.ADMINS

    siteconfig.set('site_admin_name', admin[0])
    siteconfig.set('site_admin_email', admin[1])

    # Try to transform the authentication backend
    remaining_backends = []
    known_backends = []

    for auth_backend in settings.AUTHENTICATION_BACKENDS:
        if auth_backend in auth_backend_map:
            known_backends.append(auth_backend)
        else:
            remaining_backends.append(auth_backend)

    if remaining_backends or len(known_backends) > 1:
        # The user has some custom backend set. Just set the entire list
        siteconfig.set('auth_backend', 'custom')
        siteconfig.set('auth_custom_backends',
                       settings.AUTHENTICATION_BACKENDS)
    elif len(known_backends) == 1:
        siteconfig.set('auth_backend', auth_backend_map[known_backends[0]])
    else:
        siteconfig.set('auth_backend', 'builtin')
Esempio n. 32
0
    def render_cell(self, state, obj, render_context):
        """Renders the table cell containing column data."""
        datagrid = state.datagrid

        try:
            rendered_data = self.render_data(state, obj)
        except Exception as e:
            logging.error('Error when calling render_data for DataGrid Column'
                          ' %r: %s',
                          self, e, exc_info=1)
            rendered_data = None

        if render_context:
            url = render_context.get('_datagrid_object_url')
        else:
            url = None

        css_class = ''

        if self.link:
            try:
                url = self.link_func(state, obj, rendered_data)
            except AttributeError:
                pass

        if self.css_class:
            if six.callable(self.css_class):
                css_class = self.css_class(obj)
            else:
                css_class = self.css_class

        key = "%s:%s:%s:%s" % (state.last, rendered_data, url, css_class)

        if key not in state.cell_render_cache:
            ctx = Context(render_context)
            ctx.update({
                'column': self,
                'column_state': state,
                'css_class': css_class,
                'url': url,
                'data': mark_safe(rendered_data)
            })

            state.cell_render_cache[key] = \
                mark_safe(datagrid.cell_template_obj.render(ctx))

        return state.cell_render_cache[key]
Esempio n. 33
0
def json_default(obj):
    if six.callable(getattr(obj, '__serialize__', None)):
        dct = obj.__serialize__()
        module = obj.__module__
        if module == '__builtin__':
            module = None
        if isinstance(obj, type):
            name = obj.__name__
        else:
            name = obj.__class__.__name__
        type_name = u'.'.join(filter(None, [module, name]))
        if type_name == 'cropduster.resizing.Size':
            type_name = 'Size'
        dct.update({'__type__': type_name})
        return dct
    raise TypeError("object of type %s is not JSON serializable" %
                    type(obj).__name__)
Esempio n. 34
0
    def render_cell(self, state, obj, render_context):
        """Renders the table cell containing column data."""
        datagrid = state.datagrid

        try:
            rendered_data = self.render_data(state, obj)
        except Exception as e:
            logging.error(
                'Error when calling render_data for DataGrid Column'
                ' %r: %s',
                self,
                e,
                exc_info=1)
            rendered_data = None

        url = ''
        css_class = ''

        if self.link:
            try:
                url = self.link_func(state, obj, rendered_data)
            except AttributeError:
                pass

        if self.css_class:
            if six.callable(self.css_class):
                css_class = self.css_class(obj)
            else:
                css_class = self.css_class

        key = "%s:%s:%s:%s" % (state.last, rendered_data, url, css_class)

        if key not in state.cell_render_cache:
            ctx = Context(render_context)
            ctx.update({
                'column': self,
                'column_state': state,
                'css_class': css_class,
                'url': url,
                'data': mark_safe(rendered_data)
            })

            state.cell_render_cache[key] = \
                mark_safe(datagrid.cell_template_obj.render(ctx))

        return state.cell_render_cache[key]
Esempio n. 35
0
 def effective_default(self, field):
     """
     Returns a field's effective database default value
     """
     if field.has_default():
         default = field.get_default()
     elif not field.null and field.blank and field.empty_strings_allowed:
         default = ""
     else:
         default = None
     # If it's a callable, call it
     if callable(default):
         default = default()
     # Run it through the field's get_db_prep_save method so we can send it
     # to the database.
     default = field.get_db_prep_save(default, self.connection)
     return default
Esempio n. 36
0
File: schema.py Progetto: 912/M-new
 def effective_default(self, field):
     """
     Returns a field's effective database default value
     """
     if field.has_default():
         default = field.get_default()
     elif not field.null and field.blank and field.empty_strings_allowed:
         default = ""
     else:
         default = None
     # If it's a callable, call it
     if callable(default):
         default = default()
     # Run it through the field's get_db_prep_save method so we can send it
     # to the database.
     default = field.get_db_prep_save(default, self.connection)
     return default
Esempio n. 37
0
    def get_fieldsets(self, request, obj=None):
        """
        Customize the fieldsets according to the app settings

        :param request: request
        :param obj: post
        :return: fieldsets configuration
        """
        app_config_default = self._app_config_select(request, obj)
        if app_config_default is None and request.method == 'GET':
            return super(PostAdmin, self).get_fieldsets(request, obj)
        if not obj:
            config = app_config_default
        else:
            config = obj.app_config

        fsets = deepcopy(self._fieldsets)
        if config:
            abstract = bool(config.use_abstract)
            placeholder = bool(config.use_placeholder)
            related = bool(config.use_related)
        else:
            abstract = get_setting('USE_ABSTRACT')
            placeholder = get_setting('USE_PLACEHOLDER')
            related = get_setting('USE_RELATED')
        if abstract:
            fsets[0][1]['fields'].append('abstract')
        if not placeholder:
            fsets[0][1]['fields'].append('post_text')
        if get_setting('MULTISITE') and not self.has_restricted_sites(request):
            fsets[1][1]['fields'][0].append('sites')
        if request.user.is_superuser:
            fsets[1][1]['fields'][0].append('author')
        if apps.is_installed('djangocms_blog.liveblog'):
            fsets[2][1]['fields'][2].append('enable_liveblog')
        filter_function = get_setting('ADMIN_POST_FIELDSET_FILTER')
        if related and Post.objects.namespace(
                config.namespace).active_translations().exists():
            fsets[1][1]['fields'][0].append('related')
        if callable(filter_function):
            fsets = filter_function(fsets, request, obj=obj)
        return fsets
Esempio n. 38
0
def get_modified_since(request, last_modified):
    """
    Checks if a Last-Modified timestamp is newer than the requested
    HTTP_IF_MODIFIED_SINCE from the browser. This can be used to bail
    early if no updates have been performed since the last access to the
    page.

    This can take a DateField, datetime, HTTP date-formatted string, or
    a function for the last_modified timestamp. If a function is passed,
    it will only be called if the HTTP_IF_MODIFIED_SINCE header is present.
    """
    if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE', None)

    if if_modified_since is not None:
        if six.callable(last_modified):
            last_modified = last_modified()

        return (if_modified_since == http_date(last_modified))

    return False
Esempio n. 39
0
    def _normalize_value_field(self, value_field):
        """Normalize and return a value field.

        If ``value_field`` is a function, the resulting value field from
        calling that function will be returned. Otherwise, ``value_field``
        will be returned directly.

        Args:
            value_field (object):
            A :py:class:`~djblets.conditions.values.BaseConditionValueField`
            or a function returning one.

        Returns:
            djblets.conditions.values.BaseConditionValueField:
            The resulting value field.
        """
        if six.callable(value_field):
            value_field = value_field()

        return value_field
Esempio n. 40
0
def get_modified_since(request, last_modified):
    """
    Checks if a Last-Modified timestamp is newer than the requested
    HTTP_IF_MODIFIED_SINCE from the browser. This can be used to bail
    early if no updates have been performed since the last access to the
    page.

    This can take a DateField, datetime, HTTP date-formatted string, or
    a function for the last_modified timestamp. If a function is passed,
    it will only be called if the HTTP_IF_MODIFIED_SINCE header is present.
    """
    if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE', None)

    if if_modified_since is not None:
        if six.callable(last_modified):
            last_modified = last_modified()

        return (if_modified_since == http_date(last_modified))

    return False
    def get_fieldsets(self, request, obj=None):
        """
        Customize the fieldsets according to the app settings

        :param request: request
        :param obj: post
        :return: fieldsets configuration
        """
        app_config_default = self._app_config_select(request, obj)
        if app_config_default is None and request.method == 'GET':
            return super(PostAdmin, self).get_fieldsets(request, obj)
        if not obj:
            config = app_config_default
        else:
            config = obj.app_config

        fsets = deepcopy(self._fieldsets)
        if config:
            abstract = bool(config.use_abstract)
            placeholder = bool(config.use_placeholder)
            related = bool(config.use_related)
        else:
            abstract = get_setting('USE_ABSTRACT')
            placeholder = get_setting('USE_PLACEHOLDER')
            related = get_setting('USE_RELATED')
        if abstract:
            fsets[0][1]['fields'].append('abstract')
        if not placeholder:
            fsets[0][1]['fields'].append('post_text')
        if get_setting('MULTISITE') and not self.has_restricted_sites(request):
            fsets[1][1]['fields'][0].append('sites')
        if request.user.is_superuser:
            fsets[1][1]['fields'][0].append('author')
        if apps.is_installed('djangocms_blog.liveblog'):
            fsets[2][1]['fields'][2].append('enable_liveblog')
        filter_function = get_setting('ADMIN_POST_FIELDSET_FILTER')
        if related and Post.objects.namespace(config.namespace).active_translations().exists():
            fsets[1][1]['fields'][0].append('related')
        if callable(filter_function):
            fsets = filter_function(fsets, request, obj=obj)
        return fsets
Esempio n. 42
0
def apply_django_settings(siteconfig, settings_map=None):
    """Apply Django settings stored in the site configuration.

    This takes a siteconfiguration storing Django settings and a settings map,
    applying each of the settings to Django. Setting will generally be stored
    in the Django settings object, but some settings will be specially applied
    based on their rules in the settings map.

    Args:
        siteconfig (djblets.siteconfig.models.SiteConfiguration):
            The site configuration containing the Django settings to apply.

        settings_map (dict, optional):
            A map of siteconfig keys to Django settings information. See
            :py:func:`get_django_settings_map` for details.

            If not provided, the result of :py:func:`get_django_settings_map`
            will be used.
    """
    if settings_map is None:
        settings_map = get_django_settings_map()

    for key, setting_data in six.iteritems(settings_map):
        if key in siteconfig.settings:
            value = siteconfig.get(key)
            setter = setattr

            if isinstance(setting_data, dict):
                setting_key = setting_data['key']

                if 'setter' in setting_data:
                    setter = setting_data['setter']

                if ('deserialize_func' in setting_data and
                    six.callable(setting_data['deserialize_func'])):
                    value = setting_data['deserialize_func'](value)
            else:
                setting_key = setting_data

            setter(settings, setting_key, value)
Esempio n. 43
0
def apply_django_settings(siteconfig, settings_map=None):
    """Apply Django settings stored in the site configuration.

    This takes a siteconfiguration storing Django settings and a settings map,
    applying each of the settings to Django. Setting will generally be stored
    in the Django settings object, but some settings will be specially applied
    based on their rules in the settings map.

    Args:
        siteconfig (djblets.siteconfig.models.SiteConfiguration):
            The site configuration containing the Django settings to apply.

        settings_map (dict, optional):
            A map of siteconfig keys to Django settings information. See
            :py:func:`get_django_settings_map` for details.

            If not provided, the result of :py:func:`get_django_settings_map`
            will be used.
    """
    if settings_map is None:
        settings_map = get_django_settings_map()

    for key, setting_data in six.iteritems(settings_map):
        if key in siteconfig.settings:
            value = siteconfig.get(key)
            setter = setattr

            if isinstance(setting_data, dict):
                setting_key = setting_data['key']

                if 'setter' in setting_data:
                    setter = setting_data['setter']

                if ('deserialize_func' in setting_data
                        and six.callable(setting_data['deserialize_func'])):
                    value = setting_data['deserialize_func'](value)
            else:
                setting_key = setting_data

            setter(settings, setting_key, value)
Esempio n. 44
0
    def serialize_object(self, obj, *args, **kwargs):
        """Serializes the object, transforming text fields.

        This is a specialization of serialize_object that transforms any
        text fields that support text types. It also handles attaching
        the raw text to the payload, on request.
        """
        data = super(MarkdownFieldsMixin, self).serialize_object(
            obj, *args, **kwargs)

        request = kwargs.get('request')

        if not request:
            force_text_type = None
        elif request.method == 'GET':
            force_text_type = request.GET.get('force-text-type')
        else:
            force_text_type = request.POST.get('force_text_type')

        if force_text_type not in self.TEXT_TYPES:
            force_text_type = None

        extra_text_type_fields = dict(
            (extra_text_type, {})
            for extra_text_type in self._get_extra_text_types(obj, **kwargs)
        )

        for field, field_info in six.iteritems(self.fields):
            if not field_info.get('supports_text_types'):
                continue

            get_func = getattr(self, 'get_is_%s_rich_text' % field, None)

            if six.callable(get_func):
                getter = lambda obj, *args: get_func(obj)
            else:
                getter = lambda obj, data, rich_text_field, text_type_field: \
                    getattr(obj, rich_text_field, None)

            self._serialize_text_info(obj, data, extra_text_type_fields,
                                      field, force_text_type, getter)

        if 'extra_data' in data:
            extra_data = data['extra_data']
            all_text_types_extra_data = {}

            if obj.extra_data is None:
                obj.extra_data = {}

            # Work on a copy of extra_data, in case we change it.
            for field, value in six.iteritems(obj.extra_data.copy()):
                if not self.get_extra_data_field_supports_markdown(obj, field):
                    continue

                # If all_text_types_extra_data is empty that implies we have
                # encountered the first field in extra_data which supports
                # markdown. In this case we must initialize the dictionary
                # with the extra text types that should be included in the
                # payload.
                if not all_text_types_extra_data:
                    all_text_types_extra_data = dict(
                        (k, {}) for k in six.iterkeys(extra_text_type_fields)
                    )

                # Note that we assume all custom fields are in Markdown by
                # default. This is to preserve compatibility with older
                # fields. New fields will always have the text_type flag
                # set to the proper value.
                self._serialize_text_info(
                    obj, extra_data, all_text_types_extra_data, field,
                    force_text_type, self._extra_data_rich_text_getter)

            for key, values in six.iteritems(all_text_types_extra_data):
                extra_text_type_fields[key]['extra_data'] = values

        for key, values in six.iteritems(extra_text_type_fields):
            data[key + '_text_fields'] = values

        return data
Esempio n. 45
0
    def __call__(self, request, api_format=None, *args, **kwargs):
        """Invokes the correct HTTP handler based on the type of request."""
        if not hasattr(request, '_djblets_webapi_object_cache'):
            request._djblets_webapi_object_cache = {}

        auth_result = check_login(request)

        if isinstance(auth_result, tuple):
            auth_success, auth_message, auth_headers = auth_result

            if not auth_success:
                err = LOGIN_FAILED

                if auth_message:
                    err = err.with_message(auth_message)

                return WebAPIResponseError(
                    request,
                    err=err,
                    headers=auth_headers or {},
                    api_format=api_format,
                    mimetype=self._build_error_mimetype(request))

        method = request.method

        if method == 'POST':
            # Not all clients can do anything other than GET or POST.
            # So, in the case of POST, we allow overriding the method
            # used.
            method = request.POST.get('_method', kwargs.get('_method', method))
        elif method == 'PUT':
            # Normalize the PUT data so we can get to it.
            # This is due to Django's treatment of PUT vs. POST. They claim
            # that PUT, unlike POST, is not necessarily represented as form
            # data, so they do not parse it. However, that gives us no clean
            # way of accessing the data. So we pretend it's POST for a second
            # in order to parse.
            #
            # This must be done only for legitimate PUT requests, not faked
            # ones using ?method=PUT.
            try:
                request.method = 'POST'
                request._load_post_and_files()
                request.method = 'PUT'
            except AttributeError:
                request.META['REQUEST_METHOD'] = 'POST'
                request._load_post_and_files()
                request.META['REQUEST_METHOD'] = 'PUT'

        request._djblets_webapi_method = method
        request._djblets_webapi_kwargs = kwargs
        request.PUT = request.POST

        if method in self.allowed_methods:
            if (method == "GET" and not self.singleton
                    and (self.uri_object_key is None
                         or self.uri_object_key not in kwargs)):
                view = self.get_list
            else:
                view = getattr(self, self.method_mapping.get(method, None))
        else:
            view = None

        if view and six.callable(view):
            result = self.call_method_view(request,
                                           method,
                                           view,
                                           api_format=api_format,
                                           *args,
                                           **kwargs)

            if isinstance(result, WebAPIResponse):
                return result
            elif isinstance(result, WebAPIError):
                return WebAPIResponseError(
                    request,
                    err=result,
                    api_format=api_format,
                    mimetype=self._build_error_mimetype(request))
            elif isinstance(result, tuple):
                headers = {}

                if method == 'GET':
                    request_params = request.GET
                else:
                    request_params = request.POST

                if len(result) == 3:
                    headers = result[2]

                if 'Location' in headers:
                    extra_querystr = '&'.join([
                        '%s=%s' % (param, request_params[param])
                        for param in SPECIAL_PARAMS if param in request_params
                    ])

                    if extra_querystr:
                        if '?' in headers['Location']:
                            headers['Location'] += '&' + extra_querystr
                        else:
                            headers['Location'] += '?' + extra_querystr

                if isinstance(result[0], WebAPIError):
                    return WebAPIResponseError(
                        request,
                        err=result[0],
                        headers=headers,
                        extra_params=result[1],
                        api_format=api_format,
                        mimetype=self._build_error_mimetype(request))
                else:
                    response_args = self.build_response_args(request)
                    headers.update(response_args.pop('headers', {}))
                    return WebAPIResponse(request,
                                          status=result[0],
                                          obj=result[1],
                                          headers=headers,
                                          api_format=api_format,
                                          encoder_kwargs=dict(
                                              {
                                                  'calling_resource': self,
                                              }, **kwargs),
                                          **response_args)
            elif isinstance(result, HttpResponse):
                return result
            else:
                raise AssertionError(result)
        else:
            return HttpResponseNotAllowed(self.allowed_methods)
Esempio n. 46
0
    def serialize_object(self, obj, *args, **kwargs):
        """Serializes the object into a Python dictionary."""
        request = kwargs.get('request', None)

        if request:
            if not hasattr(request, '_djblets_webapi_serialize_cache'):
                request._djblets_webapi_serialize_cache = {}

            if obj in request._djblets_webapi_serialize_cache:
                return self._clone_serialized_object(
                    request._djblets_webapi_serialize_cache[obj])

        only_fields = self.get_only_fields(request)
        only_links = self.get_only_links(request)

        data = {}
        links = {}

        if only_links != []:
            links = self.get_links(self.item_child_resources, obj, *args,
                                   **kwargs)

        if hasattr(request, '_djblets_webapi_expanded_resources'):
            expanded_resources = request._djblets_webapi_expanded_resources
        else:
            expand = request.GET.get('expand', request.POST.get('expand', ''))
            expanded_resources = expand.split(',')
            request._djblets_webapi_expanded_resources = expanded_resources

        # Make a copy of the list of expanded resources. We'll be temporarily
        # removing items as we recurse down into any nested objects, to
        # prevent infinite loops. We'll want to make sure we don't
        # permanently remove these entries, or subsequent list items will
        # be affected.
        orig_expanded_resources = list(expanded_resources)

        for field in six.iterkeys(self.fields):
            can_include_field = only_fields is None or field in only_fields
            expand_field = field in expanded_resources

            # If we're limiting fields and this one isn't explicitly included,
            # then we're only going to want to process it if there's a chance
            # it'll be linked (as opposed to being expanded).
            if not can_include_field and expand_field:
                continue

            serialize_func = getattr(self, "serialize_%s_field" % field, None)

            if serialize_func and six.callable(serialize_func):
                value = serialize_func(obj, request=request)
            else:
                value = getattr(obj, field)

                if isinstance(value, models.Manager):
                    if not can_include_field:
                        # This field isn't a single Model, so it can't be
                        # linked below. We can safely bail now before talking
                        # to the database.
                        continue

                    value = value.all()
                elif isinstance(value, models.ForeignKey):
                    value = value.get()

            # Make sure that any given field expansion only applies once. This
            # prevents infinite recursion in the case where there's a loop in
            # the object graph.
            #
            # We'll be restoring these values once we're done serializing
            # objects.
            if expand_field:
                request._djblets_webapi_expanded_resources.remove(field)

            if isinstance(value, models.Model) and not expand_field:
                serialize_link_func = self.get_link_serializer(field)

                links[field] = serialize_link_func(value, *args, **kwargs)
            elif can_include_field:
                if isinstance(value, QuerySet) and not expand_field:
                    serialize_link_func = self.get_link_serializer(field)

                    data[field] = [
                        serialize_link_func(o, *args, **kwargs) for o in value
                    ]
                elif isinstance(value, QuerySet):
                    objects = list(value)

                    if objects:
                        resource = self.get_serializer_for_object(objects[0])
                        data[field] = [
                            resource.serialize_object(o, *args, **kwargs)
                            for o in objects
                        ]
                    else:
                        data[field] = []
                elif isinstance(value, models.Model):
                    resource = self.get_serializer_for_object(value)
                    data[field] = resource.serialize_object(
                        value, *args, **kwargs)
                else:
                    data[field] = value

        for resource_name in expanded_resources:
            if (resource_name not in links
                    or (only_fields is not None
                        and resource_name not in only_fields)):
                continue

            # Try to find the resource from the child list.
            found = False

            for resource in self.item_child_resources:
                if resource_name in [resource.name, resource.name_plural]:
                    found = True
                    break

            if not found or not resource.model:
                continue

            del links[resource_name]

            extra_kwargs = {
                self.uri_object_key: getattr(obj, self.model_object_key),
            }
            extra_kwargs.update(**kwargs)
            extra_kwargs.update(self.get_href_parent_ids(obj, **kwargs))

            data[resource_name] = [
                resource.serialize_object(o, *args, **kwargs) for o in
                resource._get_queryset(is_list=True, *args, **extra_kwargs)
            ]

        if only_links is None:
            data['links'] = links
        elif only_links != []:
            data['links'] = dict([
                (link_name, link_info)
                for link_name, link_info in six.iteritems(links)
                if link_name in only_links
            ])

        # Now that we're done serializing, restore the list of expanded
        # resource for the next call.
        request._djblets_webapi_expanded_resources = orig_expanded_resources

        if request:
            request._djblets_webapi_serialize_cache[obj] = \
                self._clone_serialized_object(data)

        return data
Esempio n. 47
0
    def serialize_object(self, obj, *args, **kwargs):
        """Serializes the object into a Python dictionary."""
        request = kwargs.get('request', None)

        if request:
            if not hasattr(request, '_djblets_webapi_serialize_cache'):
                request._djblets_webapi_serialize_cache = {}

            if obj in request._djblets_webapi_serialize_cache:
                return self._clone_serialized_object(
                    request._djblets_webapi_serialize_cache[obj])

        only_fields = self.get_only_fields(request)
        only_links = self.get_only_links(request)

        data = {}
        links = {}

        if only_links != []:
            links = self.get_links(self.item_child_resources, obj,
                                   *args, **kwargs)

        if hasattr(request, '_djblets_webapi_expanded_resources'):
            expanded_resources = request._djblets_webapi_expanded_resources
        else:
            expand = request.GET.get('expand', request.POST.get('expand', ''))
            expanded_resources = expand.split(',')
            request._djblets_webapi_expanded_resources = expanded_resources

        # Make a copy of the list of expanded resources. We'll be temporarily
        # removing items as we recurse down into any nested objects, to
        # prevent infinite loops. We'll want to make sure we don't
        # permanently remove these entries, or subsequent list items will
        # be affected.
        orig_expanded_resources = list(expanded_resources)

        for field in six.iterkeys(self.fields):
            can_include_field = only_fields is None or field in only_fields
            expand_field = field in expanded_resources

            # If we're limiting fields and this one isn't explicitly included,
            # then we're only going to want to process it if there's a chance
            # it'll be linked (as opposed to being expanded).
            if not can_include_field and expand_field:
                continue

            serialize_func = getattr(self, "serialize_%s_field" % field, None)

            if serialize_func and six.callable(serialize_func):
                value = serialize_func(obj, request=request)
            else:
                value = getattr(obj, field)

                if isinstance(value, models.Manager):
                    if not can_include_field:
                        # This field isn't a single Model, so it can't be
                        # linked below. We can safely bail now before talking
                        # to the database.
                        continue

                    value = value.all()
                elif isinstance(value, models.ForeignKey):
                    value = value.get()

            # Make sure that any given field expansion only applies once. This
            # prevents infinite recursion in the case where there's a loop in
            # the object graph.
            #
            # We'll be restoring these values once we're done serializing
            # objects.
            if expand_field:
                request._djblets_webapi_expanded_resources.remove(field)

            if isinstance(value, models.Model) and not expand_field:
                serialize_link_func = self.get_link_serializer(field)

                links[field] = serialize_link_func(value, *args, **kwargs)
            elif can_include_field:
                if isinstance(value, QuerySet) and not expand_field:
                    serialize_link_func = self.get_link_serializer(field)

                    data[field] = [
                        serialize_link_func(o, *args, **kwargs)
                        for o in value
                    ]
                elif isinstance(value, QuerySet):
                    objects = list(value)

                    if objects:
                        resource = self.get_serializer_for_object(objects[0])
                        data[field] = [
                            resource.serialize_object(o, *args, **kwargs)
                            for o in objects
                        ]
                    else:
                        data[field] = []
                elif isinstance(value, models.Model):
                    resource = self.get_serializer_for_object(value)
                    data[field] = resource.serialize_object(
                        value, *args, **kwargs)
                else:
                    data[field] = value

        for resource_name in expanded_resources:
            if (resource_name not in links or
                (only_fields is not None and
                 resource_name not in only_fields)):
                continue

            # Try to find the resource from the child list.
            found = False

            for resource in self.item_child_resources:
                if resource_name in [resource.name, resource.name_plural]:
                    found = True
                    break

            if not found or not resource.model:
                continue

            del links[resource_name]

            extra_kwargs = {
                self.uri_object_key: getattr(obj, self.model_object_key),
            }
            extra_kwargs.update(**kwargs)
            extra_kwargs.update(self.get_href_parent_ids(obj, **kwargs))

            data[resource_name] = [
                resource.serialize_object(o, *args, **kwargs)
                for o in resource._get_queryset(
                    is_list=True, *args, **extra_kwargs)
            ]

        if only_links is None:
            data['links'] = links
        elif only_links != []:
            data['links'] = dict([
                (link_name, link_info)
                for link_name, link_info in six.iteritems(links)
                if link_name in only_links
            ])

        # Now that we're done serializing, restore the list of expanded
        # resource for the next call.
        request._djblets_webapi_expanded_resources = orig_expanded_resources

        if request:
            request._djblets_webapi_serialize_cache[obj] = \
                self._clone_serialized_object(data)

        return data
Esempio n. 48
0
 def sizes(self):
     if six.callable(self.field.db_field.sizes):
         return self.field.db_field.sizes(self.instance, related=self.related_object)
     else:
         return self.field.db_field.sizes
Esempio n. 49
0
    def __call__(self, request, api_format=None, *args, **kwargs):
        """Invokes the correct HTTP handler based on the type of request."""
        if not hasattr(request, '_djblets_webapi_object_cache'):
            request._djblets_webapi_object_cache = {}

        auth_result = check_login(request)

        if isinstance(auth_result, tuple):
            auth_success, auth_message, auth_headers = auth_result

            if not auth_success:
                err = LOGIN_FAILED

                if auth_message:
                    err = err.with_message(auth_message)

                return WebAPIResponseError(
                    request,
                    err=err,
                    headers=auth_headers or {},
                    api_format=api_format,
                    mimetype=self._build_error_mimetype(request))

        method = request.method

        if method == 'POST':
            # Not all clients can do anything other than GET or POST.
            # So, in the case of POST, we allow overriding the method
            # used.
            method = request.POST.get('_method', kwargs.get('_method', method))
        elif method == 'PUT':
            # Normalize the PUT data so we can get to it.
            # This is due to Django's treatment of PUT vs. POST. They claim
            # that PUT, unlike POST, is not necessarily represented as form
            # data, so they do not parse it. However, that gives us no clean
            # way of accessing the data. So we pretend it's POST for a second
            # in order to parse.
            #
            # This must be done only for legitimate PUT requests, not faked
            # ones using ?method=PUT.
            try:
                request.method = 'POST'
                request._load_post_and_files()
                request.method = 'PUT'
            except AttributeError:
                request.META['REQUEST_METHOD'] = 'POST'
                request._load_post_and_files()
                request.META['REQUEST_METHOD'] = 'PUT'

        request._djblets_webapi_method = method
        request._djblets_webapi_kwargs = kwargs
        request.PUT = request.POST

        if method in self.allowed_methods:
            if (method == "GET" and
                not self.singleton and
                (self.uri_object_key is None or
                 self.uri_object_key not in kwargs)):
                view = self.get_list
            else:
                view = getattr(self, self.method_mapping.get(method, None))
        else:
            view = None

        if view and six.callable(view):
            result = self.call_method_view(
                request, method, view, api_format=api_format, *args, **kwargs)

            if isinstance(result, WebAPIResponse):
                return result
            elif isinstance(result, WebAPIError):
                return WebAPIResponseError(
                    request,
                    err=result,
                    api_format=api_format,
                    mimetype=self._build_error_mimetype(request))
            elif isinstance(result, tuple):
                headers = {}

                if method == 'GET':
                    request_params = request.GET
                else:
                    request_params = request.POST

                if len(result) == 3:
                    headers = result[2]

                if 'Location' in headers:
                    extra_querystr = '&'.join([
                        '%s=%s' % (param, request_params[param])
                        for param in SPECIAL_PARAMS
                        if param in request_params
                    ])

                    if extra_querystr:
                        if '?' in headers['Location']:
                            headers['Location'] += '&' + extra_querystr
                        else:
                            headers['Location'] += '?' + extra_querystr

                if isinstance(result[0], WebAPIError):
                    return WebAPIResponseError(
                        request,
                        err=result[0],
                        headers=headers,
                        extra_params=result[1],
                        api_format=api_format,
                        mimetype=self._build_error_mimetype(request))
                else:
                    response_args = self.build_response_args(request)
                    headers.update(response_args.pop('headers', {}))
                    return WebAPIResponse(
                        request,
                        status=result[0],
                        obj=result[1],
                        headers=headers,
                        api_format=api_format,
                        encoder_kwargs=dict({
                            'calling_resource': self,
                        }, **kwargs),
                        **response_args)
            elif isinstance(result, HttpResponse):
                return result
            else:
                raise AssertionError(result)
        else:
            return HttpResponseNotAllowed(self.allowed_methods)
Esempio n. 50
0
import hashlib
Esempio n. 51
0
 def sizes(self):
     if six.callable(self.field.db_field.sizes):
         return self.field.db_field.sizes(self.instance,
                                          related=self.related_object)
     else:
         return self.field.db_field.sizes
Esempio n. 52
0
    def serialize_object(self, obj, *args, **kwargs):
        """Serializes the object, transforming text fields.

        This is a specialization of serialize_object that transforms any
        text fields that support text types. It also handles attaching
        the raw text to the payload, on request.
        """
        data = super(MarkdownFieldsMixin, self).serialize_object(
            obj, *args, **kwargs)

        request = kwargs.get('request')

        if not request:
            force_text_type = None
        elif request.method == 'GET':
            force_text_type = request.GET.get('force-text-type')
        else:
            force_text_type = request.POST.get('force_text_type')

        if force_text_type not in self.TEXT_TYPES:
            force_text_type = None

        extra_text_type_fields = dict(
            (extra_text_type, {})
            for extra_text_type in self._get_extra_text_types(obj, **kwargs)
        )

        for field, field_info in six.iteritems(self.fields):
            if not field_info.get('supports_text_types'):
                continue

            get_func = getattr(self, 'get_is_%s_rich_text' % field, None)

            if six.callable(get_func):
                getter = lambda obj, *args: get_func(obj)
            else:
                getter = lambda obj, data, rich_text_field, text_type_field: \
                    getattr(obj, rich_text_field, None)

            self._serialize_text_info(obj, data, extra_text_type_fields,
                                      field, force_text_type, getter)

        if 'extra_data' in data:
            extra_data = data['extra_data']
            all_text_types_extra_data = {}

            # Work on a copy of extra_data, in case we change it.
            for field, value in six.iteritems(obj.extra_data.copy()):
                if not self.get_extra_data_field_supports_markdown(obj, field):
                    continue

                # If all_text_types_extra_data is empty that implies we have
                # encountered the first field in extra_data which supports
                # markdown. In this case we must initialize the dictionary
                # with the extra text types that should be included in the
                # payload.
                if not all_text_types_extra_data:
                    all_text_types_extra_data = dict(
                        (k, {}) for k in six.iterkeys(extra_text_type_fields)
                    )

                # Note that we assume all custom fields are in Markdown by
                # default. This is to preserve compatibility with older
                # fields. New fields will always have the text_type flag
                # set to the proper value.
                self._serialize_text_info(
                    obj, extra_data, all_text_types_extra_data, field,
                    force_text_type, self._extra_data_rich_text_getter)

            for key, values in six.iteritems(all_text_types_extra_data):
                extra_text_type_fields[key]['extra_data'] = values

        for key, values in six.iteritems(extra_text_type_fields):
            data[key + '_text_fields'] = values

        return data
Esempio n. 53
0
 def target_models(self):
     if not hasattr(self, '_target_models'):
         self._target_models = (self._raw_target_models() if six.callable(
             self._raw_target_models) else self._raw_target_models)
     return self._target_models