Ticket #2417: patch.2.txt

File patch.2.txt, 9.2 KB (added by Alex Koval, 15 years ago)

patch against latest trunk (tested to work on 8960...9002)

Line 
1Index: django/db/models/fields/__init__.py
2===================================================================
3--- django/db/models/fields/__init__.py (revision 9285)
4+++ django/db/models/fields/__init__.py (working copy)
5@@ -417,6 +417,26 @@
6 defaults.update(kwargs)
7 return super(CharField, self).formfield(**defaults)
8
9+
10+class BinaryField(Field):
11+ """Sometimes we have fields that need to store a small amount of binary
12+ data. This is different then a varchar on postgresql at least because it
13+ will not allow fields that are just nul bytes.
14+ """
15+
16+ def get_internal_type(self):
17+ return "BinaryField"
18+
19+class BlobField(Field):
20+ """Sometimes we have fields that need to store a large amounts of binary
21+ data.
22+ """
23+
24+ def get_internal_type(self):
25+ return "BlobField"
26+
27+
28+
29 # TODO: Maybe move this into contrib, because it's specialized.
30 class CommaSeparatedIntegerField(CharField):
31 def formfield(self, **kwargs):
32Index: django/db/backends/postgresql/introspection.py
33===================================================================
34--- django/db/backends/postgresql/introspection.py (revision 9285)
35+++ django/db/backends/postgresql/introspection.py (working copy)
36@@ -4,6 +4,7 @@
37 # Maps type codes to Django Field types.
38 data_types_reverse = {
39 16: 'BooleanField',
40+ 17: 'BlobField',
41 21: 'SmallIntegerField',
42 23: 'IntegerField',
43 25: 'TextField',
44Index: django/db/backends/postgresql/creation.py
45===================================================================
46--- django/db/backends/postgresql/creation.py (revision 9285)
47+++ django/db/backends/postgresql/creation.py (working copy)
48@@ -8,6 +8,8 @@
49 # If a column type is set to None, it won't be included in the output.
50 data_types = {
51 'AutoField': 'serial',
52+ 'BinaryField': 'bytea',
53+ 'BlobField': 'bytea',
54 'BooleanField': 'boolean',
55 'CharField': 'varchar(%(max_length)s)',
56 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
57Index: django/db/backends/sqlite3/creation.py
58===================================================================
59--- django/db/backends/sqlite3/creation.py (revision 9285)
60+++ django/db/backends/sqlite3/creation.py (working copy)
61@@ -9,6 +9,8 @@
62 # schema inspection is more useful.
63 data_types = {
64 'AutoField': 'integer',
65+ 'BinaryField': 'BLOB',
66+ 'BlobField': 'BLOB',
67 'BooleanField': 'bool',
68 'CharField': 'varchar(%(max_length)s)',
69 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
70Index: django/db/backends/mysql/base.py
71===================================================================
72--- django/db/backends/mysql/base.py (revision 9285)
73+++ django/db/backends/mysql/base.py (working copy)
74@@ -29,6 +29,7 @@
75 from django.db.backends.mysql.creation import DatabaseCreation
76 from django.db.backends.mysql.introspection import DatabaseIntrospection
77 from django.db.backends.mysql.validation import DatabaseValidation
78+from django.utils.encoding import smart_unicode
79
80 # Raise exceptions for database warnings if DEBUG is on
81 from django.conf import settings
82@@ -46,10 +47,22 @@
83 # behavior as they are signed and include days -- and Django expects time, so
84 # we still need to override that.
85 django_conversions = conversions.copy()
86+
87+binstr_conversion = [(FLAG.BINARY, buffer),
88+ (FLAG.BLOB, smart_unicode),
89+ ]
90+
91 django_conversions.update({
92 FIELD_TYPE.TIME: util.typecast_time,
93 FIELD_TYPE.DECIMAL: util.typecast_decimal,
94 FIELD_TYPE.NEWDECIMAL: util.typecast_decimal,
95+ FIELD_TYPE.TINY_BLOB: binstr_conversion,
96+ FIELD_TYPE.MEDIUM_BLOB: binstr_conversion,
97+ FIELD_TYPE.LONG_BLOB: binstr_conversion,
98+ FIELD_TYPE.BLOB: binstr_conversion,
99+ FIELD_TYPE.VARCHAR: binstr_conversion,
100+ FIELD_TYPE.VAR_STRING: binstr_conversion,
101+ FIELD_TYPE.STRING: binstr_conversion,
102 })
103
104 # This should match the numerical portion of the version numbers (we can treat
105Index: django/db/backends/mysql/introspection.py
106===================================================================
107--- django/db/backends/mysql/introspection.py (revision 9285)
108+++ django/db/backends/mysql/introspection.py (working copy)
109@@ -7,7 +7,10 @@
110
111 class DatabaseIntrospection(BaseDatabaseIntrospection):
112 data_types_reverse = {
113- FIELD_TYPE.BLOB: 'TextField',
114+ FIELD_TYPE.BLOB: 'BlobField',
115+ FIELD_TYPE.LONG_BLOB: 'BlobField',
116+ FIELD_TYPE.TINY_BLOB: 'BlobField',
117+ FIELD_TYPE.MEDIUM_BLOB: 'BlobField',
118 FIELD_TYPE.CHAR: 'CharField',
119 FIELD_TYPE.DECIMAL: 'DecimalField',
120 FIELD_TYPE.NEWDECIMAL: 'DecimalField',
121Index: django/db/backends/mysql/creation.py
122===================================================================
123--- django/db/backends/mysql/creation.py (revision 9285)
124+++ django/db/backends/mysql/creation.py (working copy)
125@@ -8,6 +8,8 @@
126 # If a column type is set to None, it won't be included in the output.
127 data_types = {
128 'AutoField': 'integer AUTO_INCREMENT',
129+ 'BinaryField': 'varbinary(%(max_length)s)',
130+ 'BlobField': 'blob',
131 'BooleanField': 'bool',
132 'CharField': 'varchar(%(max_length)s)',
133 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
134@@ -63,4 +65,4 @@
135 field.rel.to._meta.db_table, field.rel.to._meta.pk.column)
136 ]
137 return table_output, deferred
138-
139\ No newline at end of file
140+
141Index: django/db/backends/__init__.py
142===================================================================
143--- django/db/backends/__init__.py (revision 9285)
144+++ django/db/backends/__init__.py (working copy)
145@@ -164,7 +164,11 @@
146 from django.utils.encoding import smart_unicode, force_unicode
147
148 # Convert params to contain Unicode values.
149- to_unicode = lambda s: force_unicode(s, strings_only=True)
150+ def to_unicode(s):
151+ if isinstance(s,buffer):
152+ return u'<binary data buffer size %d>' % len(s)
153+ return force_unicode(s, strings_only=True)
154+
155 if isinstance(params, (list, tuple)):
156 u_params = tuple([to_unicode(val) for val in params])
157 else:
158Index: tests/modeltests/binary/__init__.py
159===================================================================
160Index: tests/modeltests/binary/tests.py
161===================================================================
162--- tests/modeltests/binary/tests.py (revision 0)
163+++ tests/modeltests/binary/tests.py (revision 0)
164@@ -0,0 +1,70 @@
165+#!/usr/bin/python
166+# encoding: utf-8
167+
168+try:
169+ from models import Document, BinaryFieldTest
170+except: # for local testing
171+ from binary.models import Document, BinaryFieldTest
172+
173+import unittest
174+
175+
176+class BlobFieldTests( unittest.TestCase ):
177+
178+ def test_blob(self):
179+ test_title = u'Hi there! привет!'
180+ test_descr = u'описание документа'
181+
182+ s = ''
183+ for i in range(0,256):
184+ s += chr(i)
185+ s+= '\xff\xff'
186+
187+
188+ test_data = buffer(s)
189+
190+ doc = Document(title = test_title,
191+ description = test_descr,
192+ document = test_data)
193+ doc.save()
194+ doc_id = doc.id
195+ doc = None
196+ doc = Document.objects.get(id=doc_id)
197+ assert doc.title == test_title, type(doc.title)
198+ assert doc.description == test_descr, type(doc.description)
199+ assert doc.document == test_data, type(doc.document)
200+
201+class BinaryFieldTests( unittest.TestCase ):
202+
203+ def test_binary(self):
204+ test_title = u'Hi there! привет!'
205+
206+ s = ''
207+ for i in range(0,10):
208+ s += chr(i)
209+
210+ s+= '\xff\xff'
211+
212+ test_data = buffer(s)
213+
214+
215+ tst = BinaryFieldTest(title = test_title,
216+ binfield = test_data)
217+ tst.save()
218+ tst_id = tst.id
219+ tst = None
220+ tst = BinaryFieldTest.objects.get(id=tst_id)
221+ assert tst.title == test_title, type(tst.title)
222+ assert tst.binfield == test_data, type(tst.binfield)
223+
224+
225+def test_suite():
226+ return unittest.TestSuite((
227+ unittest.makeSuite(BlobFieldTests),
228+ unittest.makeSuite(BinaryFieldTests)
229+ ))
230+
231+
232+
233+if __name__ == '__main__':
234+ unittest.main(defaultTest='test_suite')
235Index: tests/modeltests/binary/models.py
236===================================================================
237--- tests/modeltests/binary/models.py (revision 0)
238+++ tests/modeltests/binary/models.py (revision 0)
239@@ -0,0 +1,18 @@
240+"""
241+BlobField and BinaryField tests
242+
243+"""
244+
245+from django.db import models
246+
247+# Create your models here.
248+class Document(models.Model):
249+ title = models.CharField(max_length=50)
250+ description = models.TextField()
251+ document = models.BlobField()
252+
253+class BinaryFieldTest(models.Model):
254+ title = models.CharField(max_length=20)
255+ binfield = models.BinaryField(max_length=20)
256+
257+
Back to Top