Raise error on read of a browse object with bad id

# Problem

Browse objects can be returned for an arbitrary number of ids.
The lazy read properties of the browse object makes it so it doesn't write any SQL with the function `browse()`. This causes the ability to create things such as :

```
In : self.pool.get'res.partner').browse(cr, uid, 0)
Out: browse_record(res.partner, 0)
```

The problem arises when attempts to fetch a field are made:

```
In [7]: session.registry('res.partner').browse(session.cr, session.uid, 0).name
2014-11-14 18:53:39,541 21965 DEBUG test openerp.sql_db: query: SELECT res_partner."comment",res_partner."ean13",res_partner."color",res_partner."zip_id",res_partner."railway_company",res_partner."use_parent_address",res_partner."active",res_partner."street",res_partner."supplier",res_partner."observer_state",res_partner."city",res_partner."user_id",res_partner."firstname",res_partner."zip",res_partner."title",res_partner."country_id",res_partner."company_id",res_partner."iata_code",res_partner."parent_id",res_partner."notification_email_send",res_partner."railway_station",res_partner."employee",res_partner."birth_name",res_partner."type",res_partner."email",res_partner."vat",res_partner."airline",res_partner."function",res_partner."lang",res_partner."fax",res_partner."member_states",res_partner."lastname",res_partner."street2",res_partner."phone",res_partner."date",res_partner."tz",res_partner."customer",res_partner."credit_limit",res_partner."name",res_partner."extension",res_partner."mobile",res_partner."ref",res_partner."website",res_partner."birthdate",res_partner."airport",res_partner."is_company",res_partner."state_id",res_partner.id FROM "res_partner" WHERE res_partner.id IN (0) ORDER BY name
2014-11-14 18:53:39,542 21965 DEBUG test openerp.sql_db: query: SELECT id FROM res_partner WHERE id IN (0)
2014-11-14 18:53:39,543 21965 WARNING test openerp.osv.orm: No field_values found for ids [0] in browse_record(res.partner, 0)

  File "openerp/osv/osv.py", line 132, in wrapper
    return f(self, dbname, *args, **kwargs)
  File "openerp/osv/osv.py", line 199, in execute
    res = self.execute_cr(cr, uid, obj, method, *args, **kw)
  File "openerp/osv/osv.py", line 187, in execute_cr
    return getattr(object, method)(cr, uid, *args, **kw)
  File "openerp/addons/oif_account_voucher/account_voucher.py", line 183, in write
    if 'name' not in vals and not voucher.name:
  File "openerp/osv/orm.py", line 505, in __getattr__
    raise AttributeError(e)
```

# Solution

**This is no longer true, was the solution with 4e999da**

Check if id is valid by searching objects for id yields no fields
If no id is in the table raise BrowseRecordError with proper message to user
Maintain lazy sql properties of object by only checking when things go wrong

The result is now


```
In : self.pool.get'res.partner').browse(cr, uid, 0)
Out: browse_record(res.partner, 0)
```

No calls to the database

```
In: session.registry('res.partner').browse(session.cr, session.uid, 0).name
2014-11-14 18:53:39,541 21965 DEBUG oif openerp.sql_db: query: SELECT res_partner."comment",res_partner."ean13",res_partner."color",res_partner."zip_id",res_partner."railway_company",res_partner."use_parent_address",res_partner."active",res_partner."street",res_partner."supplier",res_partner."observer_state",res_partner."city",res_partner."user_id",res_partner."firstname",res_partner."zip",res_partner."title",res_partner."country_id",res_partner."company_id",res_partner."iata_code",res_partner."parent_id",res_partner."notification_email_send",res_partner."railway_station",res_partner."employee",res_partner."birth_name",res_partner."type",res_partner."email",res_partner."vat",res_partner."airline",res_partner."function",res_partner."lang",res_partner."fax",res_partner."member_states",res_partner."lastname",res_partner."street2",res_partner."phone",res_partner."date",res_partner."tz",res_partner."customer",res_partner."credit_limit",res_partner."name",res_partner."extension",res_partner."mobile",res_partner."ref",res_partner."website",res_partner."birthdate",res_partner."airport",res_partner."is_company",res_partner."state_id",res_partner.id FROM "res_partner" WHERE res_partner.id IN (0) ORDER BY name
2014-11-14 18:53:39,542 21965 DEBUG oif openerp.sql_db: query: SELECT id FROM res_partner WHERE id IN (0)
2014-11-14 18:53:39,543 21965 WARNING oif openerp.osv.orm: No field_values found for ids [0] in browse_record(res.partner, 0)
2014-11-14 18:53:39,545 21965 DEBUG oif openerp.sql_db: query: SELECT "res_partner".id FROM "res_partner" WHERE (("res_partner"."active" = 'True')  AND  (FALSE OR "res_partner"."id" IS NULL)) ORDER BY "res_partner"."name"   limit 1

BrowseRecordError: Object res.partner with IDs [0] don't exist

  File "openerp/osv/osv.py", line 132, in wrapper
    return f(self, dbname, *args, **kwargs)
  File "openerp/osv/osv.py", line 199, in execute
    res = self.execute_cr(cr, uid, obj, method, *args, **kw)
  File "openerp/osv/osv.py", line 187, in execute_cr
    return getattr(object, method)(cr, uid, *args, **kw)
  File "openerp/addons/oif_account_voucher/account_voucher.py", line 183, in write
    if 'name' not in vals and not voucher.name:
  File "openerp/osv/orm.py", line 505, in __getattr__
     return self[name]
  File "openerp/osv/orm.py", line 434, in __getitem__
    raise BrowseRecordError("Object %s with IDs %s don't exist" % (self._model._name, ids))
```

Signed-off-by: Sandy Carter <sandy.carter@savoirfairelinux.com>
This could be a good improvement, but it's really a NTH (as opposed to a  bugfix) so it can only go to master, especially as you are changing an exception type, not just improving a message.
BTW `BrowseRecordError` is not used anywhere, not sure it's a good idea to start using it. I think it's been dropped in 8.0 anyway so you won't have it in master. What about ValueError (as the provided ID isn't valid)?
Also I do not think it is possible to hit this branch of the code when a record rule prohibits access to a record. You'd get a different exception instead. So while we're improving the error message, let's make sure it is as accurate as possible, and preserve the name of the attribute being looked up. Something like this perhaps:
> Cannot fetch field %(field)s for %(model)s record with ID %(id)s,
> that record does not exist or has been deleted

You could also drop the unnecessary `else:` after the first `raise`.

Sorry if that all sounds like nitpicking but you're touching a core part of the framework there... ;-)

Thanks!