Permalink
Browse files

Fixed ``auto_now/_add`` & ``blank`` introspection bugs. Thanks to alt…

…option & jude for the reports!
  • Loading branch information...
1 parent 6b93f68 commit 9c50dfdfed85416ce47d8c67f4587881f5506adc @toastdriven toastdriven committed Feb 10, 2012
Showing with 124 additions and 10 deletions.
  1. +7 −0 tastypie/resources.py
  2. +16 −3 tests/core/models.py
  3. +101 −7 tests/core/tests/resources.py
View
@@ -1541,13 +1541,20 @@ def get_fields(cls, fields=None, excludes=None):
if not f.null and f.blank is True:
kwargs['default'] = ''
+ kwargs['blank'] = True
if f.get_internal_type() == 'TextField':
kwargs['default'] = ''
if f.has_default():
kwargs['default'] = f.default
+ if getattr(f, 'auto_now', False):
+ kwargs['default'] = f.auto_now
+
+ if getattr(f, 'auto_now_add', False):
+ kwargs['default'] = f.auto_now_add
+
final_fields[f.name] = api_field_class(**kwargs)
final_fields[f.name].instance_name = f.name
View
@@ -15,11 +15,11 @@ class Note(models.Model):
def __unicode__(self):
return self.title
-
+
def save(self, *args, **kwargs):
self.updated = now()
return super(Note, self).save(*args, **kwargs)
-
+
def what_time_is_it(self):
return aware_datetime(2010, 4, 1, 0, 48)
@@ -45,6 +45,19 @@ class MediaBit(models.Model):
note = models.ForeignKey(Note, related_name='media_bits')
title = models.CharField(max_length=32)
image = models.FileField(blank=True, null=True, upload_to='bits/')
-
+
+ def __unicode__(self):
+ return self.title
+
+
+class AutoNowNote(models.Model):
+ # Purposely a bit more complex to test correct introspection.
+ title = models.CharField(max_length=100)
+ slug = models.SlugField(unique=True)
+ content = models.TextField(blank=True)
+ is_active = models.BooleanField(default=True)
+ created = models.DateTimeField(auto_now_add=now, null=True)
+ updated = models.DateTimeField(auto_now=now)
+
def __unicode__(self):
return self.title
@@ -22,9 +22,9 @@
from tastypie.resources import Resource, ModelResource, ALL, ALL_WITH_RELATIONS, convert_post_to_put, convert_post_to_patch
from tastypie.serializers import Serializer
from tastypie.throttle import CacheThrottle
-from tastypie.utils import aware_datetime, make_naive
+from tastypie.utils import aware_datetime, make_naive, now
from tastypie.validation import Validation, FormValidation
-from core.models import Note, Subject, MediaBit
+from core.models import Note, Subject, MediaBit, AutoNowNote
from core.tests.mocks import MockRequest
from core.utils import SimpleHandler
try:
@@ -725,6 +725,15 @@ class Meta:
fields = ['title', 'content', 'created', 'is_active']
+class AutoNowNoteResource(ModelResource):
+ class Meta:
+ resource_name = 'autonownotes'
+ queryset = AutoNowNote.objects.filter(is_active=True)
+
+ def get_resource_uri(self, bundle_or_obj):
+ return '/api/v1/autonownotes/%s/' % bundle_or_obj.obj.id
+
+
class CustomPaginator(Paginator):
def page(self):
data = super(CustomPaginator, self).page()
@@ -1082,6 +1091,91 @@ def test_fields(self):
self.assertEqual(resource_1.fields['subjects']._resource, resource_1.__class__)
self.assertEqual(resource_1.fields['subjects'].instance_name, 'subjects')
+ # Sanity check the other introspected fields.
+ annr = AutoNowNoteResource()
+ self.assertEqual(len(annr.fields), 8)
+ self.assertEqual(sorted(annr.fields.keys()), ['content', 'created', 'id', 'is_active', 'resource_uri', 'slug', 'title', 'updated'])
+
+ self.assertTrue(isinstance(annr.fields['content'], fields.CharField))
+ self.assertEqual(annr.fields['content'].attribute, 'content')
+ self.assertEqual(annr.fields['content'].blank, True)
+ self.assertEqual(annr.fields['content']._default, '')
+ self.assertEqual(annr.fields['content'].instance_name, 'content')
+ self.assertEqual(annr.fields['content'].null, False)
+ self.assertEqual(annr.fields['content'].readonly, False)
+ self.assertEqual(annr.fields['content'].unique, False)
+ self.assertEqual(annr.fields['content'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['created'], fields.DateTimeField))
+ self.assertEqual(annr.fields['created'].attribute, 'created')
+ self.assertEqual(annr.fields['created'].blank, False)
+ self.assertTrue(isinstance(annr.fields['created']._default(), datetime.datetime))
+ self.assertEqual(annr.fields['created'].instance_name, 'created')
+ self.assertEqual(annr.fields['created'].null, True)
+ self.assertEqual(annr.fields['created'].readonly, False)
+ self.assertEqual(annr.fields['created'].unique, False)
+ self.assertEqual(annr.fields['created'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['id'], fields.CharField))
+ self.assertEqual(annr.fields['id'].attribute, 'id')
+ self.assertEqual(annr.fields['id'].blank, True)
+ self.assertEqual(annr.fields['id']._default, '')
+ self.assertEqual(annr.fields['id'].instance_name, 'id')
+ self.assertEqual(annr.fields['id'].null, False)
+ self.assertEqual(annr.fields['id'].readonly, False)
+ self.assertEqual(annr.fields['id'].unique, True)
+ self.assertEqual(annr.fields['id'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['is_active'], fields.BooleanField))
+ self.assertEqual(annr.fields['is_active'].attribute, 'is_active')
+ self.assertEqual(annr.fields['is_active'].blank, True)
+ self.assertEqual(annr.fields['is_active']._default, True)
+ self.assertEqual(annr.fields['is_active'].instance_name, 'is_active')
+ self.assertEqual(annr.fields['is_active'].null, False)
+ self.assertEqual(annr.fields['is_active'].readonly, False)
+ self.assertEqual(annr.fields['is_active'].unique, False)
+ self.assertEqual(annr.fields['is_active'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['resource_uri'], fields.CharField))
+ self.assertEqual(annr.fields['resource_uri'].attribute, None)
+ self.assertEqual(annr.fields['resource_uri'].blank, False)
+ self.assertEqual(annr.fields['resource_uri']._default, fields.NOT_PROVIDED)
+ self.assertEqual(annr.fields['resource_uri'].instance_name, 'resource_uri')
+ self.assertEqual(annr.fields['resource_uri'].null, False)
+ self.assertEqual(annr.fields['resource_uri'].readonly, True)
+ self.assertEqual(annr.fields['resource_uri'].unique, False)
+ self.assertEqual(annr.fields['resource_uri'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['slug'], fields.CharField))
+ self.assertEqual(annr.fields['slug'].attribute, 'slug')
+ self.assertEqual(annr.fields['slug'].blank, False)
+ self.assertEqual(annr.fields['slug']._default, fields.NOT_PROVIDED)
+ self.assertEqual(annr.fields['slug'].instance_name, 'slug')
+ self.assertEqual(annr.fields['slug'].null, False)
+ self.assertEqual(annr.fields['slug'].readonly, False)
+ self.assertEqual(annr.fields['slug'].unique, True)
+ self.assertEqual(annr.fields['slug'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['title'], fields.CharField))
+ self.assertEqual(annr.fields['title'].attribute, 'title')
+ self.assertEqual(annr.fields['title'].blank, False)
+ self.assertEqual(annr.fields['title']._default, fields.NOT_PROVIDED)
+ self.assertEqual(annr.fields['title'].instance_name, 'title')
+ self.assertEqual(annr.fields['title'].null, False)
+ self.assertEqual(annr.fields['title'].readonly, False)
+ self.assertEqual(annr.fields['title'].unique, False)
+ self.assertEqual(annr.fields['title'].value, None)
+
+ self.assertTrue(isinstance(annr.fields['updated'], fields.DateTimeField))
+ self.assertEqual(annr.fields['updated'].attribute, 'updated')
+ self.assertEqual(annr.fields['updated'].blank, True)
+ self.assertTrue(isinstance(annr.fields['updated']._default(), datetime.datetime))
+ self.assertEqual(annr.fields['updated'].instance_name, 'updated')
+ self.assertEqual(annr.fields['updated'].null, False)
+ self.assertEqual(annr.fields['updated'].readonly, False)
+ self.assertEqual(annr.fields['updated'].unique, False)
+ self.assertEqual(annr.fields['updated'].value, None)
+
def test_urls(self):
# The common case, where the ``Api`` specifies the name.
resource = NoteResource(api_name='v1')
@@ -1229,7 +1323,7 @@ def test_build_schema(self):
'nullable': False,
'default': True,
'readonly': False,
- 'blank': False,
+ 'blank': True,
'help_text': 'Boolean data. Ex: True',
'unique': False,
'type': 'boolean'
@@ -1238,7 +1332,7 @@ def test_build_schema(self):
'nullable': False,
'default': '',
'readonly': False,
- 'blank': False,
+ 'blank': True,
'help_text': 'Unicode string data. Ex: "Hello World"',
'unique': False,
'type': 'string'
@@ -1946,7 +2040,7 @@ def test_get_schema(self):
"default_limit": 20,
"fields": {
"content": {
- "blank": False,
+ "blank": True,
"default": "",
"help_text": "Unicode string data. Ex: \"Hello World\"",
"nullable": False,
@@ -1964,7 +2058,7 @@ def test_get_schema(self):
"unique": False
},
"id": {
- "blank": False,
+ "blank": True,
"default": "",
"help_text": "Unicode string data. Ex: \"Hello World\"",
"nullable": False,
@@ -1973,7 +2067,7 @@ def test_get_schema(self):
"unique": True
},
"is_active": {
- "blank": False,
+ "blank": True,
"default": True,
"help_text": "Boolean data. Ex: True",
"nullable": False,

0 comments on commit 9c50dfd

Please sign in to comment.