Index: django/contrib/gis/db/models/fields/__init__.py
===================================================================
--- django/contrib/gis/db/models/fields/__init__.py	(revision 5178)
+++ django/contrib/gis/db/models/fields/__init__.py	(working copy)
@@ -4,10 +4,12 @@
 from django.contrib.gis.oldforms import WKTField
 from django.utils.functional import curry
 
+from django.contrib.gis.db.models.proxy import GeometryProxy
+
 #TODO: add db.quotename.
 
 # Creates the SQL to add the model to the database. 
-def _add_geom(geom, srid, style, model, field, dim=2):
+def _add_geom(geom, srid, null_ok, style, model, field, dim=2):
     # Constructing the AddGeometryColumn(...) command -- the style
     # object is passed in from the management module and is used
     # to syntax highlight the command for 'sqlall'
@@ -19,6 +21,14 @@
           style.SQL_COLTYPE(geom) + "', " + \
           style.SQL_KEYWORD(str(dim)) + \
           ');'
+    if not null_ok:
+        # Add a NOT NULL constraint to the field
+        sql += '\n' + \
+            style.SQL_KEYWORD('ALTER TABLE ') + \
+            style.SQL_TABLE('"' + model + '"') + \
+            style.SQL_KEYWORD(' ALTER ') + \
+            style.SQL_FIELD('"' + field + '"') + \
+            style.SQL_KEYWORD(' SET NOT NULL') + ';'
     return sql
 
 # Creates an index for the given geometry.
@@ -52,6 +62,10 @@
         # The SRID for the geometry, defaults to 4326.
         self._srid = srid
 
+        # blank values are bad. We'd prefer NULLs for geometry fields
+        if 'blank' in kwargs:
+            kwargs['null'] = kwargs['blank'] or kwargs.get('null',False)
+
         # Calling the Field initialization function first
         super(GeometryField, self).__init__(**kwargs)
 
@@ -59,6 +73,10 @@
     def contribute_to_class(self, cls, name):
         super(GeometryField, self).contribute_to_class(cls, name)
 
+        # setup for lazy-instantiated GEOSGeometry objects 
+        setattr(cls, self.attname, GeometryProxy(self))
+
+        # TODO: These are deprecated now, and issue warnings as such
         # Adding the WKT accessor function for geometry
         setattr(cls, 'get_%s_geos' % self.name, curry(cls._get_GEOM_geos, field=self))
         setattr(cls, 'get_%s_wkt' % self.name, curry(cls._get_GEOM_wkt, field=self))
@@ -76,24 +94,24 @@
 
         # Getting the AddGeometryColumn() SQL necessary to create a PostGIS
         # geometry field.
-        post_sql = _add_geom(self._geom, self._srid, *args, **kwargs)
+        post_sql = _add_geom(self._geom, self._srid, self.null, *args, **kwargs)
 
         # If the user wants to index this data, then get the indexing SQL as well.
         if self._index:
             return '%s\n%s' % (post_sql, _geom_index(self._geom, *args, **kwargs))
         else:
             return post_sql
-
+            
     def get_db_prep_lookup(self, lookup_type, value):
         """Returns field's value prepared for database lookup; the SRID of the geometry is
         included by default in these queries."""
         if lookup_type in POSTGIS_TERMS:
-            return ['SRID=%d;%s' % (self._srid, value)]
+            return [value and ("SRID=%d;%s" % (self.srid,value.wkt)) or None]
         raise TypeError("Field has invalid lookup: %s" % lookup_type)
 
     def get_db_prep_save(self, value):
         "Making sure the SRID is included before saving."
-        return 'SRID=%d;%s' % (self._srid, value)
+        return value and ("SRID=%d;%s" % (value.srid,value.wkt)) or None
 
     def get_manipulator_field_objs(self):
         "Using the WKTField (defined above) to be our manipulator."
Index: django/contrib/gis/db/models/GeoMixin.py
===================================================================
--- django/contrib/gis/db/models/GeoMixin.py	(revision 5178)
+++ django/contrib/gis/db/models/GeoMixin.py	(working copy)
@@ -10,21 +10,25 @@
     # routines are present for instantiations of the models.
     def _get_GEOM_geos(self, field):
         "Gets a GEOS Python object for the geometry."
-        return GEOSGeometry(getattr(self, field.attname), 'hex')
+        import warnings
+        warnings.warn("use model.geometry_field", DeprecationWarning)
+        return getattr(self, field.attname)
 
     def _get_GEOM_wkt(self, field):
         "Gets the WKT of the geometry."
-        hex = getattr(self, field.attname)
-        return hex_to_wkt(hex)
+        import warnings
+        warnings.warn("use model.geometry_field.wkt", DeprecationWarning)
+        return getattr(self, field.attname).wkt
 
     def _get_GEOM_centroid(self, field):
         "Gets the centroid of the geometry, in WKT."
-        hex = getattr(self, field.attname)
-        return centroid(hex)
+        import warnings
+        warnings.warn("use model.geometry_field.centroid.wkt", DeprecationWarning)
+        return getattr(self, field.attname).centroid.wkt
     
     def _get_GEOM_area(self, field):
         "Gets the area of the geometry, in projected units."
-        hex = getattr(self, field.attname)
-        return area(hex)
-
-
+        import warnings
+        warnings.warn("use model.geometry_field.area", DeprecationWarning)
+        return getattr(self, field.attname).area
+        
Index: django/contrib/gis/db/models/proxy.py
===================================================================
--- django/contrib/gis/db/models/proxy.py	(revision 0)
+++ django/contrib/gis/db/models/proxy.py	(revision 0)
@@ -0,0 +1,30 @@
+# GEOS Routines
+from django.contrib.gis.geos import GEOSGeometry, GEOSException
+
+class GeometryProxy(object):
+    def __init__(self, field):
+        self._field = field
+    
+    def __get__(self, obj, type=None):
+        geom_value = obj.__dict__[self._field.attname]
+        if (geom_value is None) or (isinstance(geom_value, GEOSGeometry)):
+            geom = geom_value
+        else:
+            # TODO: can we improve this somehow? 
+            # first case is what happens on DB extract
+            try:
+                geom = GEOSGeometry(geom_value, "hex")
+            except GEOSException:
+                geom = GEOSGeometry(geom_value, "wkt")
+
+            setattr(obj, self._field.attname, geom)
+
+        if geom and ((geom.srid is None) and (self._field._srid is not None)):
+            geom.set_srid(self._field._srid)
+
+        return geom
+    
+    def __set__(self, obj, value):
+        obj.__dict__[self._field.attname] = value
+        return value
+    
\ No newline at end of file
Index: django/contrib/gis/geos/GEOSGeometry.py
===================================================================
--- django/contrib/gis/geos/GEOSGeometry.py	(revision 5178)
+++ django/contrib/gis/geos/GEOSGeometry.py	(working copy)
@@ -127,7 +127,11 @@
             g = lgeos.GEOSGeomFromWKT(buf)
         elif geom_type == 'hex':
             # If the geometry is in HEX form.
-            sz = c_size_t(len(input))
+            try:
+                # we do this to catch numbers (eg. 5) being passed in
+                sz = c_size_t(len(input))
+            except TypeError:
+                raise GEOSException, 'Invalid hex given!'
             buf = create_string_buffer(input)
             g = lgeos.GEOSGeomFromHEX_buf(buf, sz)
         elif geom_type == 'geos':
