Acces to db made easy

- Prev: Advanced configuration
- Next: ModelProxy

# Fields

Mask/Tables are 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 knows:

> - if it belongs to the database (attribute `persisted` 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)

## 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 decide 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, that’s -rarely- done by sqlkit.widgets.mask.miniwiget.Widget. More tipically it is done by the layout procedure and the Fields/Widget just takes its control and adds completion capabilities.

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

### 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 alreadu 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)

  `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)

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

    Parameter: | 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`.

    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.``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)