Acces to db made easy

- Prev: Advanced configuration
- Next: ModelProxy

# Fields

Mask and Tables display a collection of data that may belong to the database or not. Each of the data represented in the GUI that needs to partecipate to any updating/saving process should have it’s own handler that is a Field.

A Field is an entity that knows how to handle a piece of data, be it on the database (a field_name) or just in the GUI. It’s a layer that allows gui widget to be simpler and easier to interchange. As an example, both varchars and integers are normally displayed by a gtk.Entry: the entry.get_text() will retrieve in both cases a string, it’s the Field (IntegerField) that knows how to turn that string into an integer using the `Field.clean_value()` method. In more complex cases `clean_value` can return data computed from related records.

cthe field knows:

> - if it belongs to the database (attribute `persistent` is True) and in case how it is defined ( i.e.: sqlalchemy property/column)
> - if it is nullable/editable
> - which widget must be used to represent it (see below, not requested)
> - how to produce a formatted representation of the field.

It provides functions to

> - set/get value
> - get default value (but will not cope with server_side defaults)
> - tell if it changed from the default
> - clean value according to it’s logic: i.e. return a value of the correct type
> - validate values (possibly according to other criteria)

The association between a database field and a Field is dome by FieldChooser, but you can force a particular Field when defining the model class setting the key `field` of the column’s `info` dictionary:

    class MyClass(Base):
        ...
        foo = Column(..., info={'field' : MyField})

A last method is to use on_pre_layout hook that allows to set `sqlkit.Fields` even on non persisted fields.

## Relation with the master sqlwidget

Currently there are a number of operation that require that the field know wich is the sqlwidget it is acting for. I’d like to loosen this connection in future but at present it’s used in the following situations:

- to keep updated the list of field_widgets
- to get default values (that can be local to a sqlwidget)
- for validation purposes: to issue master.run_hooks and NonNullableException
- FKey: to handle addition of related_obj when cascading policy requires it

In the meanwhile I add master to the Field via set_master() and add a widget to the Field via set_widget()

## Db attributes

The costructor can be passed a dict of field_attributes

> - field_name: the name of the field

> - nullable: True if field is nullable or False. The related widget will get a background color that

>     reflects the fact that it is required (currently yellow). This can be set at any time.

> - editable: True if field is editable or False. The related widget will be set unsensitive. This can

>     be set at any time.

> - length: the desired length in chars

> - default: a possible default option

> - type: the python type

> - mapper: defined as None for field that are mapped

> - table: the SA Table object

> - column: the SA Column object

> - property: the SA Property - if any

> - fkey: the SA ForeignKey or None

> - pkey: True is field is a PRIMARY KEY or False

## Other attributes

> - widget: the widget used to represent it. May be sqlkit.widgets.mask.miniwidget or similar
> - format: the format used to represent the field (numeric or date/time)
> - locale: the locale to use to represent the field (numeric or date/time)
> - DecimalFields also have precision/scale
> - Varchar/TextFields also have blank=True/False (default: False). It determines if an empty string is a valid value. Empty strings are differerent from NULL values

## future

> This should provide a way to set the possible observers

> validation based on the type should live here

> possibly more validation may live here

## formatting/locale

> see decimal to have an intro on formatting numbers

### FieldChooser

This class implements a way to determine which Field should be associated to each field_name in a mapper (used in setup_field_validation so that it can be easily overwritten). It’s important to understand that it already receives a gtkwidget from layoutgenerator; that widget has been set by introspection of the layout description and of the field in the database.

You can overwrite the decision of the field redefining the gui_field on a derived sqlwidget or passing it as argument (see code snippet 34):

    class Movie(SqlMask):
        gui_field_mapping = {'date_release' : VarcharField}

    t = Movie(table='movie', dbproxy=db, layout=lay)

It’s up to the field defined in this way to be able to handle the type of data. This setting can be used to add field constraints (eg: mail address validation) or to completely change the widget that represent data.

### Widgets

A Field does not create a gtk widget to represent data. Layout definition is normally enought to create the correct GTK widget. If a gtk widget exists that represent a field, it is handled by a proxy called Miniwidget that offers a common interface to possbly different gtk widgets. If a MiniWidget exists the Field will instantiate it and set values thought it.

A notable exception to this rule is represented by any m2m/o2m relation, that in the layout is only present as a gtk.Alignment widget to which a children is added by mask.Widget.

Miniwidgets for all main types are provided.

### Global variables

Varchar fields will try to cast an empty value to None unless blank_ok is set in the field:

    t.gui_field.field_name.blank_ok = True

or globally:

> from sqlkit.widgets.common import fields fields.BLANK_OK = True

Default value for BLANK_OK is False.

This is only enforced for NEW records, for already persisted records the default behaviour is to let it as-is, to prevent a very annoying flood of dialog “do you want to save?” when you just need to browse some data.

### Available Fields

class `sqlkit.fields.``Field`(field_name, field_attrs=None)
  `set_widget`(gtkwidget=None, def_str=None, widget=None)

    Parameters:

    - def_str – the definition string in the layout that determined the gtk.Widget (eg.: c=married, e=first_name)
    - widget – the miniwidget to be used. Defaults to class-defined self.Widget the widget can be a string of a Widget derived from `miniwidget.Widget`
    - gtkwidget – the gtk widget to be used (already created by Layout)

  `set_value`(value, initial=True, shown=False, obj=None, update_widget=True)

    Set the value

    Parameters:

    - value – the value to be set. It will be cleaned.
    - initial – if True the `self.initial_value` is set as. `self.initial_value` is used to know if a field has changed
    - obj – if passed the attribute is set on the object when the field is set
    - update_widget – if True (default) the widget that renders the field is set as well.

  `get_value`(shown=False)
    Return the current value. Look for it in the widget and returns a cleaned value
  `clear_value`()
    sets a value that clears the corresponding widget, can be None or []
  `format_value`(value, format=None)

    return a string representation of the value according to current locale value is a”cleaned” value

    Parameter: | value – the value to be formatted (must already be casted to correct type)

  `clean_value`(value, obj=None)

    return a value of the correct type, if needed parse it with locale parsers (numbers, date...)

    Parameters:

    - value – the value to be cleaned (i.e. casted to correct type). It’s the attribute of a persisten object or the object itself for non persisted fields. I.e.: if you create a custom field to count how many movies has directed each director, the Director instance will be passed as `value`.
    - obj – the object to which the field belongs. It’s normally disreguarded but it can be used by special fields (as image fields) to create customized property (e.g.: the save path)

    This function is used while sorting a column

  `has_changed`(verbose=False)
    return True if field has changed after last set
  `get_default`()
    return the default value for this object
  `validate`(value, clean=False)
    check if the current value is accepted and call on_field__validation on the master’s hook.
  `get_human_value`(value, format=None)
    return the value or a translation in human readable for foreign key

All other field inherit from Field

class `sqlkit.fields.``VarcharField`(*args, **kw)

  The field to represent Strings

  `blank_ok`
    The widget return an epty string on empty values. This variable determines if that value will be set NULL or left empty. Regardless of this value the value is left untouched if it already exists.

class `sqlkit.fields.``IntegerField`(*args, **kw)

  The fields to handle interegers

  `format`
    How to represent integers. Default: ‘#,###’

class `sqlkit.fields.``FloatField`(*args, **kw)

  The fields to handle floats

  `format`
    How to represent integers. Default: None

class `sqlkit.fields.``DecimalField`(*args, **kw)

  The fields to handle Numeric Fields

  `format`
    How to represent integers. Default: ‘#,###.00’ (The number of 0 determined by `scale`

class `sqlkit.fields.``TextField`(*args, **kw)

class `sqlkit.fields.``DateField`(*args, **kw)

  The fields to handle datets

  `format`
    The format used to represent dates. Default: `short`

class `sqlkit.fields.``TimeField`(*args, **kw)
  The fields to handle times w/o timezone

class `sqlkit.fields.``TimeTZField`(*args, **kwargs)
  The fields to handle times with timezone

class `sqlkit.fields.``IntervalField`(field_name, field_attrs=None)
  The fields to handle times with interval

class `sqlkit.fields.``DateTimeField`(*args, **kwargs)
  The fields to handle datetimes w/o timezone

class `sqlkit.fields.``DateTimeTZField`(*args, **kwargs)
  The fields to handle datetimes with timezone

class `sqlkit.fields.``BooleanField`(field_name, field_attrs=None)
  A field to handle booleans that does not allow NULL

class `sqlkit.fields.``BooleanNullField`(field_name, field_attrs=None)
  A field to handle booleans that allows NULL

class `sqlkit.fields.``EnumField`(*args, **kw)

  A field to handle a set of allowed values. You set `values` in the `info` column dict or setting `values`. Setting info column’s key `render` to ‘enum’ triggers this field and a widget based on ComboBox. It doesn’t currently use Sqlalchemy Enum type as it’s not yet supported in sqlalchemy 0.5.

  `keys`
    A list of allowe values in the orederd set by the programmer. Used to set the order of the Combo Box
  `values`
    A dict: keys are the allowed values, values are te corresponding descriptions. It’s up to the programmer to set this list appropriately.
  `lookup_value`(value)
    Return the value to be shown

class `sqlkit.fields.``ImageField`(*args, **kw)

  Imge field suitable for VarcharField that hold an image path and should be rendered as image (icon in tables). It’s never used when autoloading the database schema (no info on the database tells that a string represent an image path), it can be forced setting info values on the Column:

      render:         image
      base_dir:       a directory
      thumbnail_size: tuple (width, height)
      default_size:   tuple (width height)

  as in:

      image = Column(String(100), info={'render' : 'image', 'base_dir' : '/path/to/images'}

  Image field that can create a thumbnail and resize an image into jpeg/png format using gtk.gdk.pixbuf* functions

  `base_dir`
    base directory under which all files will be saved. Default is `os.getcwd()` unless is set at Schema time as shown above. `get_save_path()` will use this to create a complete path. This can be set when defining the Column as shown above.
  `thumbnail_size`
    size of the thumbnail used to render in treeview. Default 50,50. Can be set in Column.info as explained above.
  `default_size`
    If set it must be a tuple (width, height) and all files uploaded will be default to these dimentions if bigger.
  `get_value`(shown=False, complete_path=False)

    Return the path to the image

    Parameters:

    - shown – boolean: not meaningful for this field
    - complete_path – boolean: compose it with base path

  `set_value`(value, initial=True, shown=False, obj=None, update_widget=True, new_name=None)

    Set the value and -if needed- copy the image file inside `base_dir` possibly resizing it to `default_size`. When resizing the only possible format is jpeg and the name is changed accordingly.

    Parameters:

    - value – the value to be set. It will be cleaned.
    - initial – if True the `self.initial_value` is set as. `self.initial_value` is used to know if a field has changed
    - obj – if passed the attribute is set on the object when the field is set
    - update_widget – if True (default) the widget that renders the field is set as well.

  `clean_value`(value, obj=None)
    strip self.base_dir from the file if present
  `get_save_path`(name=None, obj=None)

    Return a standard save path. You may want to customize it.

    Parameters:

    - name – the name of the file as picked up from the filesystem or the desired new name for the file
    - obj – the object. This may be used to work out the path. It’s not used by default.

  `scale_pixbuf`(pixbuf, width=None, height=None)

    scale pixbuf image with the same ratio so that it fits into self.w/self.h

    Parameters:

    - pixbuf – the pixbuf to scale
    - width – the desider width
    - height – the desider height

  `scale_file`(image_path, dst_path, width, height)
    Scale input file into output file. Keep width/height ratio :param image_path: path of the image to resize :param dst_path: new name of the image :param width: the desired width :param height: the desired height
  `create_thumbnail`(filename, thumbnail_path=None)

    Create a thumbnail that will be used when rendering images in tables. Uses attribute `thumbnail_size`

    Parameter: | filename – the filename to create a thumbnail for

  `get_thumbnail`(path=None, complete_path=False)

    Return a thumbnail path and create the thumbnail image, if it doesn’t already exists

    Parameters:

    - path – the path of the image file. If missing it’s found using `get_value()`
    - complete_path – return a complete path. Default is to return the path stripped from the `base_dir`

  `get_thumbnail_path_with_size`(filename)

    Return the thumbnail name for filename using default size. Place the thumbnail in a subdir of image dir ‘.thumbnail’ used by `get_thumbnail()` and `create_thumbnail()`. The name contains the `thumbail_size` used to generate it.

    Parameter: | filename – the complete filename of the image

class `sqlkit.fields.``ForeignKeyField`(*args, **kwargs)

  A field to handle foreign keys

  `lookup_value`(field_value)
    retrieve the value in a lookup table in case of foreign_key. It means: “given the foreign key return a value describing at the best the referenced record”. This implies some guessing of the best representation of the record or using information given to site-wide database configuration via _sqlkit_table. The details of such mechanism are described in Completion and Table Description. Since field_value may be incorrectly casted (it is used in completion) errors are catched and None is returned (rather than raising an Error)
  `add_related_object`(prop, key)

    Add an object to fullfill the constraint on delete-orphan

    This is not meant to be used directly, it is used by `set_value()` If you have a relation with a delete-orphan constraint that would complain that is not attached to anybody configure the Column adding in the info keyword the `attach_instance` key pointing to the property of the relation to be added.

    In the demo you can find this example:

        class Movie(Base):
            __tablename__  = 'movie'
            ...
            director_id    = Column(Integer, ForeignKey('director.id'), nullable=False,
                                    info={'attach_instance': 'director'})

        class Director(Base):
            __tablename__ = 'director'
            ...
            movies      = relation('Movie', backref='director', cascade='all, delete-orphan',)

    Attaching a director_id via completion, requires that you attach a director instance as well.

class `sqlkit.fields.``CollectionField`(*args, **kwargs)
  A field that manages a collection of objects Used in OneToMany or ManyToMany db fields. it’s default widget is a collectionWidget that uses a SqlTable

`sqlkit.fields.``std_cleanup`(fn)

  A decorator that will handle standard cases: value is None, is a string or is already cleaned.

  This is handy when building new Fields as it allows to keep the `.clean_value` method as simple as possible, i.e. no need to check for standard cases:

      class CountMovies(fields.IntegerField):
          '''
          A field that counts the movies
          '''
          @fields.std_cleanup
          def clean_value(self, value):
              ## missing a field_name attribute on obj the object itselt is passed
              return len(value.movies)