Index: django/db/models/base.py
===================================================================
--- django/db/models/base.py	(revision 7996)
+++ django/db/models/base.py	(working copy)
@@ -170,7 +170,6 @@
 
     def __init__(self, *args, **kwargs):
         dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs)
-
         # There is a rather weird disparity here; if kwargs, it's set, then args
         # overrides it. It should be one or the other; don't duplicate the work
         # The reason for the kwargs check is that standard iterator passes in by
@@ -187,6 +186,8 @@
             # is *not* consumed. We rely on this, so don't change the order
             # without changing the logic.
             for val, field in izip(args, fields_iter):
+                if field.get_internal_type() in ['BlobField', 'BinaryField']:
+                    val = buffer(val)
                 setattr(self, field.attname, val)
         else:
             # Slower, kwargs-ready version.
Index: django/db/models/fields/__init__.py
===================================================================
--- django/db/models/fields/__init__.py	(revision 7996)
+++ django/db/models/fields/__init__.py	(working copy)
@@ -157,7 +157,10 @@
         # exactly which wacky database column type you want to use.
         data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
         try:
+            # print get_creation_module().DATA_TYPES, self.get_internal_type(), data
+            # print get_creation_module().DATA_TYPES[self.get_internal_type()]
             return get_creation_module().DATA_TYPES[self.get_internal_type()] % data
+        
         except KeyError:
             return None
 
@@ -349,6 +352,22 @@
     def get_validator_unique_lookup_type(self):
         return '%s__exact' % self.name
 
+    def get_manipulator_new_file_data(self, new_data, rel=False):
+        """
+        Return the file data in order to overcome some nasty 
+        corner cases
+        """
+        if rel:
+            val = new_data.get(self.name+"_file", [self.get_default()])
+            try:
+                return val[0]
+            except(IndexError):
+                return self.get_default()
+        val = new_data.get(self.name+"_file",self.get_default())
+        if not self.empty_strings_allowed and val == '' and self.null:
+            val = None
+        return val
+
     def get_manipulator_new_data(self, new_data, rel=False):
         """
         Given the full new_data dictionary (from the manipulator), returns this
@@ -518,6 +537,37 @@
         defaults.update(kwargs)
         return super(CharField, self).formfield(**defaults)
 
+class BinaryField(Field):
+    """Sometimes we have fields that need to store a small amount of binary
+    data. This is different then a varchar on postgresql at least because it
+    will not allow fields that are just nul bytes.
+    """
+    def get_manipulator_field_objs(self):
+        # XXX We should probably use a better form field for this. Like
+        # XXX something that can grok colon-separated hexlify.
+        #
+        return [django.forms.TextField]
+
+    def get_internal_type(self):
+        return "BinaryField"
+
+
+class BlobField(Field):
+    """Sometimes we have fields that need to store a large amounts of binary
+    data. 
+    """
+
+    def get_internal_type(self):
+        return "BlobField"
+
+
+    def get_manipulator_field_objs(self):
+        # XXX We should probably use a better form field for this. Like
+        # XXX something that can grok colon-separated hexlify.
+        #
+        return [django.forms.TextField]
+
+
 # TODO: Maybe move this into contrib, because it's specialized.
 class CommaSeparatedIntegerField(CharField):
     def get_manipulator_field_objs(self):
Index: django/db/backends/postgresql/creation.py
===================================================================
--- django/db/backends/postgresql/creation.py	(revision 7996)
+++ django/db/backends/postgresql/creation.py	(working copy)
@@ -4,6 +4,8 @@
 # If a column type is set to None, it won't be included in the output.
 DATA_TYPES = {
     'AutoField':         'serial',
+    'BinaryField':       'bytea',
+    'BlobField':         'bytea', 
     'BooleanField':      'boolean',
     'CharField':         'varchar(%(max_length)s)',
     'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
Index: django/db/backends/sqlite3/creation.py
===================================================================
--- django/db/backends/sqlite3/creation.py	(revision 7996)
+++ django/db/backends/sqlite3/creation.py	(working copy)
@@ -3,6 +3,8 @@
 # schema inspection is more useful.
 DATA_TYPES = {
     'AutoField':                    'integer',
+    'BinaryField':                  'BLOB', 
+    'BlobField':                    'BLOB', 
     'BooleanField':                 'bool',
     'CharField':                    'varchar(%(max_length)s)',
     'CommaSeparatedIntegerField':   'varchar(%(max_length)s)',
Index: django/db/backends/mysql/introspection.py
===================================================================
--- django/db/backends/mysql/introspection.py	(revision 7996)
+++ django/db/backends/mysql/introspection.py	(working copy)
@@ -75,7 +75,7 @@
     return indexes
 
 DATA_TYPES_REVERSE = {
-    FIELD_TYPE.BLOB: 'TextField',
+    FIELD_TYPE.BLOB: 'BlobField',
     FIELD_TYPE.CHAR: 'CharField',
     FIELD_TYPE.DECIMAL: 'DecimalField',
     FIELD_TYPE.DATE: 'DateField',
Index: django/db/backends/mysql/creation.py
===================================================================
--- django/db/backends/mysql/creation.py	(revision 7996)
+++ django/db/backends/mysql/creation.py	(working copy)
@@ -4,6 +4,8 @@
 # If a column type is set to None, it won't be included in the output.
 DATA_TYPES = {
     'AutoField':         'integer AUTO_INCREMENT',
+    'BinaryField':       'varbinary(%(max_length)s)', 
+    'BlobField':         'blob', 
     'BooleanField':      'bool',
     'CharField':         'varchar(%(max_length)s)',
     'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
@@ -13,8 +15,8 @@
     'FileField':         'varchar(%(max_length)s)',
     'FilePathField':     'varchar(%(max_length)s)',
     'FloatField':        'double precision',
+    'IPAddressField':    'char(15)',
     'IntegerField':      'integer',
-    'IPAddressField':    'char(15)',
     'NullBooleanField':  'bool',
     'OneToOneField':     'integer',
     'PhoneNumberField':  'varchar(20)',
Index: django/db/backends/__init__.py
===================================================================
--- django/db/backends/__init__.py	(revision 7996)
+++ django/db/backends/__init__.py	(working copy)
@@ -146,9 +146,9 @@
         # Convert params to contain Unicode values.
         to_unicode = lambda s: force_unicode(s, strings_only=True)
         if isinstance(params, (list, tuple)):
-            u_params = tuple([to_unicode(val) for val in params])
+            u_params = tuple([to_unicode(repr(val)) for val in params])
         else:
-            u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()])
+            u_params = dict([(to_unicode(k), to_unicode(repr(v))) for k, v in params.items()])
 
         return smart_unicode(sql) % u_params
 
Index: tests/modeltests/binary/__init__.py
===================================================================
Index: tests/modeltests/binary/tests.py
===================================================================
--- tests/modeltests/binary/tests.py	(revision 0)
+++ tests/modeltests/binary/tests.py	(revision 0)
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+# encoding: utf-8
+
+from models import Document, BinaryFieldTest
+
+import unittest
+
+
+class BlobFieldTests( unittest.TestCase ):
+    
+     def test_blob(self):
+         test_title = u'Hi there! привет!'
+         test_descr = u'описание документа'
+
+         s = '' 
+         for i in range(0,256):
+              s += chr(i)
+              
+         
+         test_data = buffer(s)
+         
+         
+         doc = Document(title = test_title,
+                        description = test_descr,
+                        document = test_data)
+         doc.save()
+         doc_id = doc.id
+         doc = None
+         doc = Document.objects.get(id=doc_id)
+         assert doc.title == test_title, type(doc.title)
+         assert doc.description == test_descr, type(doc.description)
+         assert doc.document == test_data, type(doc.document)
+
+class BinaryFieldTests( unittest.TestCase ):
+    
+     def test_binary(self):
+         test_title = u'Hi there! привет!'
+
+         s = '' 
+         for i in range(0,19):
+              s += chr(i)
+         test_data = buffer(s)
+
+         tst = BinaryFieldTest(title = test_title,
+                          binfield = test_data)
+         tst.save()
+         tst_id = tst.id
+         tst = None
+         tst = BinaryFieldTest.objects.get(id=tst_id)
+         assert tst.title == test_title, type(tst.title)
+         assert tst.binfield == test_data, type(tst.binfield)
+                         
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(BlobFieldTests),
+        unittest.makeSuite(BinaryFieldTests)
+        ))
+
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
Index: tests/modeltests/binary/models.py
===================================================================
--- tests/modeltests/binary/models.py	(revision 0)
+++ tests/modeltests/binary/models.py	(revision 0)
@@ -0,0 +1,18 @@
+"""
+BlobField and BinaryField tests
+
+"""
+
+from django.db import models
+
+# Create your models here.
+class Document(models.Model):
+    title = models.CharField(max_length=50)
+    description = models.TextField()
+    document = models.BlobField()
+
+class BinaryFieldTest(models.Model):
+    title = models.CharField(max_length=20)
+    binfield = models.BinaryField(max_length=20)
+
+
