示例#1
0
class QueryFilterResource(ModelResource):
    query = ToOneField(QueryResource,
                       attribute='query',
                       help_text="query to which the filter belongs")
    field = ToOneField(CensusFieldResource,
                       attribute='field',
                       help_text="field by which to filter")

    class Meta:
        queryset = QueryFilter.objects.all()
        authentication = SessionAuthentication()
        authorization = OwnedOnlyAuthorization()
        validation = QueryFilterValidation()

    def apply_authorization_limits(self, request, object_list):
        return object_list.filter(query__account=request.user.account)

    def obj_create(self, bundle, **kwargs):
        result = super(QueryFilterResource, self).obj_create(bundle, **kwargs)
        if result.obj.query.account != bundle.request.user.account:
            raise Unauthorized("Can't attach to a query that is not yours")
        return result

    def obj_get_list(self, bundle, **kwargs):
        return [
            f for f in super(QueryFilterResource, self).obj_get_list(
                bundle, **kwargs)
            if f.query.account == bundle.request.user.account
        ]

    def obj_get(self, bundle, **kwargs):
        result = super(QueryFilterResource, self).obj_get(bundle, **kwargs)
        if result.query.account != bundle.request.user.account:
            raise Unauthorized("Forbidden")
        return result
示例#2
0
class PropertyResource(FlatListMixin, ModelResource):
    contact = ToOneField('nexus.api.ContactResource', 'contact', null=True)
    portfolio = ToOneField('nexus.api.PortfolioResource',
                           'portfolio',
                           null=True)
    client = ToOneField('nexus.api.ClientResource',
                        'client',
                        null=True,
                        full=False)
    addresses = ToManyField('nexus.api.AddressResource',
                            'address_set',
                            null=True,
                            full_detail=True,
                            full=True,
                            related_name='property')

    class Meta:
        queryset = Property.objects.all()
        resource_name = 'property'
        authorization = Authorization()
        always_return_data = True
        include_absolute_url = True
        filtering = {
            'client': ALL_WITH_RELATIONS,
            'portfolio': ALL_WITH_RELATIONS
        }
示例#3
0
class EventResource(ModelResource):
    cid = ToOneField(CalResource, "cal", full=True)
    user = ToOneField(UserResource, 'user', full=True)

    class Meta:
        queryset = Event.objects.all()
        paginator_class = Paginator
        always_return_data = True
        authorization = EventAuth()

    def dehydrate_cid(self, bundle):
        return bundle.obj.cal.id

    def hydrate_cid(self, bundle):
        bundle.data["cid"] = "/cal/%d/" % bundle.data["cid"]
        return bundle

    def dehydrate_user(self, bundle):
        return bundle.obj.user.id

    def hydrate_user(self, bundle):
        bundle.data["user"] = "******" % bundle.request.user.id
        return bundle

    def hydrate_id(self, bundle):
        if bundle.data["id"] == 0:
            bundle.data["id"] = None
        return bundle
class FeatureBehaviorResource(FootprintResource):
    behavior = ToOneField(BehaviorResource, attribute='behavior', null=False)
    db_entity = ToOneField('footprint.main.resources.db_entity_resources.DbEntityResource', attribute='db_entity', null=True, readonly=True)
    intersection = ToOneFieldWithSubclasses(IntersectionResource, attribute='intersection_subclassed', null=True)

    class Meta(FootprintResource.Meta):
        queryset = FeatureBehavior.objects.filter(is_template=False)
        resource_name= 'feature_behavior'
示例#5
0
class AppraisalResource(SpecifiedFields):
    engagement_property = ToOneField('nexus.api.EngagementPropertyResource',
                                     'engagement_property',
                                     full=True)

    assignments = ToManyField('nexus.api.AssignmentResource',
                              'assignments',
                              full=True)
    office = ToOneField('nexus.api.OfficeResource',
                        'office',
                        full=True,
                        null=True)

    class Meta:
        queryset = (Appraisal.objects.prefetch_related(
            'assignments', 'assignments__employee').all())
        resource_name = 'appraisal'
        authorization = Authorization()
        filtering = {
            'engagement_property': ALL_WITH_RELATIONS,
            'due_date': ALL,
            'assignments': ALL_WITH_RELATIONS,
            'status': ALL,
            'office': ALL_WITH_RELATIONS,
        }
        always_return_data = True
        include_absolute_url = True
        excludes = [
            'created',
            'changed',
        ]
        max_limit = None

    def dehydrate_fee(self, bundle):
        employee = bundle.request.user.employee
        if employee.title in Title.view_fee_titles:
            return bundle.obj.fee
        return None

    def dehydrate(self, bundle):
        print 'enter AppraisalResource.dehydrate'
        bundle = super(self.__class__, self).dehydrate(bundle)

        assn = bundle.obj.lead_appraiser
        bundle.data['lead_appraiser'] = assn.employee if assn else None
        bundle.data['portfolio'] = bundle.obj.engagement_property.\
            engagement.portfolio.get_absolute_url() if \
            bundle.obj.engagement_property.engagement.\
            portfolio else None
        # TODO: We don't want the serialized string (.json()) here but rather
        #       an actual dict of the address.
        addy = bundle.obj.engagement_property.property.base_address
        bundle.data['base_address'] = addy.json() if addy else None

        print '------- exit AppraisalResource.dehydrate'

        return bundle
示例#6
0
class ChefResource(ModelResource):
    chefify_user = ToOneField(ChefifyUserResource, 'chefify_user', full=True)
    menu = ToOneField(MenuResource, 'menu', full=True, null=True)
    cuisine = ToManyField(CuisineResource, 'cuisine', full=True, null=True)

    class Meta:
        queryset = Chef.objects.all()
        resource_name = 'chef'
        filtering = {'menu': ALL_WITH_RELATIONS, 'price_minimum': ALL}
示例#7
0
class ClickCountResource(ModelResource):
    video = ToOneField(VideoResource, 'video', full=False)
    user = ToOneField(UserResource, 'user', full=False, blank=True)

    class Meta:
        queryset = ClickCount.objects.all()
        resource_name = "click_count"
        authorization = UserObjectsOnlyAuthorization()
        authentication = BasicAuthentication()
        allowed_methods = ['get', 'post']
示例#8
0
class EngagementPropertyResource(ModelResource):
    engagement = ToOneField('nexus.api.EngagementResource', 'engagement')
    property = ToOneField('nexus.api.PropertyResource', 'property', full=True)
    office = ToOneField('nexus.api.OfficeResource', 'office', null=True)

    class Meta:
        queryset = EngagementProperty.objects.all()
        resource_name = 'engagement-property'
        authorization = Authorization()
        excludes = ['created', 'changed']
示例#9
0
 def test_traversed_attribute_dehydrate(self):
     mediabit = MediaBit(id=1, note=self.note_1)
     bundle = Bundle(obj=mediabit)
     
     field_1 = ToManyField(SubjectResource, 'note__subjects')
     field_1.instance_name = 'm2m'
     self.assertEqual(field_1.dehydrate(bundle), ['/api/v1/subjects/1/', '/api/v1/subjects/2/'])
 
     field_2 = ToOneField(SubjectResource, 'fakefield__subjects')
     field_2.instance_name = 'm2m'
     self.assertRaises(ApiFieldError, field_2.hydrate, bundle)
示例#10
0
    def test_resource_from_uri(self):
        ur = UserResource()
        field_1 = ToOneField(UserResource, 'author')
        fk_bundle = field_1.resource_from_uri(ur, '/api/v1/users/1/')
        self.assertEqual(fk_bundle.data['username'], u'johndoe')
        self.assertEqual(fk_bundle.data['email'], u'*****@*****.**')
        self.assertEqual(fk_bundle.obj.username, u'johndoe')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')

        fk_bundle = field_1.resource_from_uri(ur, '/api/v1/users/1/', related_obj='Foo', related_name='Bar')
        self.assertEqual(fk_bundle.related_obj, None)
        self.assertEqual(fk_bundle.related_name, None)
示例#11
0
    def test_traversed_attribute_dehydrate(self):
        user = User.objects.get(pk=1)
        mediabit = MediaBit(note=Note(author=user))
        bundle = Bundle(obj=mediabit)
        
        field_1 = ToOneField(UserResource, 'note__author')
        field_1.instance_name = 'fk'
        self.assertEqual(field_1.dehydrate(bundle), '/api/v1/users/1/')

        field_2 = ToOneField(UserResource, 'fakefield__author')
        field_2.instance_name = 'fk'
        self.assertRaises(ApiFieldError, field_2.hydrate, bundle)
示例#12
0
class CharityfullResource(ModelResource):
    charity = ToOneField(CharityResource, 'charity', full=True)
    click_count = ToOneField(ClickCountResource,
                             "click_count",
                             full=True,
                             null=True)

    class Meta:
        queryset = Video.objects.all()
        resource_name = "charity_full"
        authorization = Authorization()
        allowed_methods = ['get', 'post']
示例#13
0
class DishResource(ModelResource):
    type = ToOneField(DishTypeResource, 'type', full=True)
    cuisine = ToOneField(CuisineResource, 'cuisine', full=True)

    class Meta:
        queryset = Dish.objects.all()
        resource_name = 'dish'
        filtering = {
            'name': ALL,
            'type': ALL_WITH_RELATIONS,
            'cuisine': ALL_WITH_RELATIONS
        }
class IntersectionResource(FootprintResource):

    # join_type is readonly. The API only expects a subclass to be saved, so we never have to set the
    # join_type
    join_type = ToOneField(JoinTypeResource, attribute='join_type', readonly=True)
    feature_behavior = ToOneField('footprint.main.resources.db_entity_resources.FeatureBehaviorResource', attribute='feature_behavior', readonly=True)

    def dehydrate_join_type(self, bundle):
        return bundle.obj.join_type.key

    class Meta(FootprintResource.Meta):
        queryset = Intersection.objects.all()
示例#15
0
class AppointmentsResource(ModelResource):
    chef = ToOneField(ChefResource, 'chef', full=True)
    event_type = ToOneField(EventTypeResource, 'event_type', full=True)
    location = ToOneField(LocationResource, 'location', full=True, null=True)
    menu = ToOneField(MenuResource, 'menu', full=True, null=True)
    customer = ToOneField(CustomerResource, 'customer', full=True, blank=True)

    class Meta:
        allowed_methods = ['get', 'post', 'put']
        queryset = Appointments.objects.all()
        resource_name = 'appointments'
        authorization = CustomerObjectsOnlyAuthorization()
        authentication = SessionAuthentication()
示例#16
0
    def test_resource_from_pk(self):
        user = User.objects.get(pk=1)
        ur = UserResource()
        field_1 = ToOneField(UserResource, 'author')
        fk_bundle = field_1.resource_from_pk(ur, user)
        self.assertEqual(fk_bundle.data['username'], u'johndoe')
        self.assertEqual(fk_bundle.data['email'], u'*****@*****.**')
        self.assertEqual(fk_bundle.obj.username, u'johndoe')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')

        fk_bundle = field_1.resource_from_pk(ur, user, related_obj='Foo', related_name='Bar')
        self.assertEqual(fk_bundle.related_obj, None)
        self.assertEqual(fk_bundle.related_name, None)
示例#17
0
class BillResource(ModelResource):
    call = ToManyField('bills.api.resources.CallResource', 'call', full=True, null=True)
    booster = ToManyField('bills.api.resources.BoosterResource', 'booster', full=True, null=True)
    data = ToManyField('bills.api.resources.DataResource', 'data', full=True, null=True)
    roaming = ToManyField('bills.api.resources.RoamingResource', 'roaming', full=True, null=True)
    subscriber = ToOneField(SubscriberResource, 'subscriber', full=False, null=True)
    plan = ToOneField(PlanResource, 'plan', full=False, null=True)

    class Meta:
        queryset = Bill.objects.all()
        resource_name = 'bill'
        authorization = Authorization()
        authentication = Authentication()
        cache = SimpleCache(timeout=1000)
示例#18
0
class AssignmentResourceThin(ModelResource):
    employee = ToOneField('nexus.api.EmployeeResource', 'employee')
    appraisal = ToOneField('nexus.api.AppraisalResource', 'appraisal')

    class Meta:
        queryset = Assignment.objects.all()
        resource_name = 'assignment-thin'
        authorization = Authorization()
        filtering = {
            'appraisal': ALL_WITH_RELATIONS,
            'employee': ALL_WITH_RELATIONS,
            'role': ('exact', ),
        }
        always_return_data = True
示例#19
0
class ContactResource(ModelResource):
    client = ToOneField('nexus.api.ClientResource', 'client', null=True)
    amf = ToOneField('nexus.api.AMFResource', 'amf', null=True)
    employee = ToOneField('nexus.api.EmployeeResource', 'employee', null=True)

    class Meta:
        queryset = Contact.objects.all()
        resource_name = 'contact'
        authorization = Authorization()
        always_return_data = True
        filtering = {
            'client': ALL_WITH_RELATIONS,
            'amf': ALL_WITH_RELATIONS,
        }
示例#20
0
class ScheduledAssignmentResource(FlatListMixin, ModelResource):
    engagement_property = ToOneField('nexus.api.EngagementPropertyResource',
                                     'engagement_property')
    employee = ToOneField('nexus.api.EmployeeResource', 'employee')

    class Meta:
        queryset = ScheduledAssignment.objects.all()
        resource_name = 'scheduled-assignment'
        authorization = Authorization()
        filtering = {
            'engagement_property': ALL_WITH_RELATIONS,
            'employee': ALL_WITH_RELATIONS,
            'role': ('exact', )
        }
        always_return_data = True
示例#21
0
class LicenseResource(ModelResource):
    employee = ToOneField('nexus.api.EmployeeResource', 'employee')

    class Meta:
        queryset = License.objects.all()
        resource_name = 'license'
        authorization = Authorization()
示例#22
0
class UserResource(ModelResource):
    giver = ToOneField(GiverResource, 'giver', full=True)
    class Meta:
        queryset = User.objects.all()
        resource_name = 'user'
        authorization = UserObjectsOnlyAuthorization()
        authentication = BasicAuthentication()
示例#23
0
class CommandResource(ModelResource):
    script = ToOneField(RedirectResource, 'script')
    suffix = ToOneField(SuffixResource, 'suffix', null=True)

    class Meta:
        cache = SimpleCache()
        queryset = Command.objects.all()
        serializer = api.Serializer()
        #resource_name = 'command'
        filtering = {
            "id": ALL,
            "command": ALL,
            "url": ALL,
            "script": ALL_WITH_RELATIONS,
            "suffix": ALL_WITH_RELATIONS,
        }
示例#24
0
class AnalysisModuleResource(FootprintResource):

    config_entity = ToOneField(
        'footprint.main.resources.config_entity_resources.ConfigEntityResource',
        attribute='config_entity',
        full=False,
        null=False,
        readonly=True)
    analysis_tools = ToManyField(AnalysisToolResource,
                                 attribute='analysis_tools')

    started = DateField(readonly=True)
    completed = DateField(readonly=True)
    failed = DateField(readonly=True)

    class Meta(FootprintResource.Meta):
        always_return_data = True,
        excludes = ('creator', 'updater')
        filtering = {"config_entity": ALL_WITH_RELATIONS}
        queryset = AnalysisModule.objects.all()
        resource_name = 'analysis_module'

    def hydrate(self, bundle):
        if not bundle.obj.id:
            bundle.obj.creator = self.resolve_user(bundle.request.GET)
        bundle.obj.updater = self.resolve_user(bundle.request.GET)
        return bundle
示例#25
0
class ScheduledAppraisalResource(FlatListMixin, SpecifiedFields):
    engagement_property = ToOneField('nexus.api.EngagementPropertyResource',
                                     'engagement_property')

    class Meta:
        queryset = ScheduledAppraisal.objects.all()
        resource_name = 'scheduled-appraisal'
        authorization = Authorization()
        filtering = {
            'engagement_property': ALL_WITH_RELATIONS,
            'due_date': ALL
        }
        always_return_data = True
        include_absolute_url = True
        excludes = ['created', 'changed', 'legacy_job_number']
        max_limit = None

    def dehydrate(self, bundle):
        bundle = super(self.__class__, self).dehydrate(bundle)
        bundle.data['job_number'] = bundle.obj.job_number
        bundle.data['status'] = AppraisalStatus.SCHEDULED
        bundle.data['lead_appraiser'] = None
        bundle.data['invoice_sent'] = None
        # TODO: We don't want the serialized string (.json()) here but rather
        #       an actual dict of the address.
        addy = bundle.obj.engagement_property.property.base_address
        bundle.data['base_address'] = addy.json() if addy else None
        bundle.data.setdefault('absolute_url', bundle.obj.get_absolute_url())
        return bundle
示例#26
0
class SubmissionEventResource(ModelResource):
    submission = ToOneField(SubmissionResource, 'submission')
    by = ToOneField(PersonResource, 'by', null=True)

    class Meta:
        cache = SimpleCache()
        queryset = SubmissionEvent.objects.all()
        serializer = api.Serializer()
        #resource_name = 'submissionevent'
        filtering = {
            "id": ALL,
            "time": ALL,
            "desc": ALL,
            "submission": ALL_WITH_RELATIONS,
            "by": ALL_WITH_RELATIONS,
        }
示例#27
0
文件: api.py 项目: pombreda/ralph
class CIOwnersResource(MResource):
    profile = ToOneField(ProfileResource, 'profile', full=True)

    class Meta:
        queryset = CIOwner.objects.all()
        authentication = ApiKeyAuthentication()
        authorization = RalphAuthorization(required_perms=[
            Perm.read_configuration_item_info_generic,
        ])
        list_allowed_methods = ['get', 'post']
        filtering = {
            'cache_version': ALL,
            'created': ALL,
            'id': ALL,
            'modified': ALL,
            'resource_uri': ALL,
            'profile': ALL_WITH_RELATIONS,
        }
        excludes = ('cache_version', )
        resource_name = 'ciowners'
        throttle = CacheThrottle(
            throttle_at=THROTTLE_AT,
            timeframe=TIMEFRAME,
            expiration=EXPIRATION,
        )

    def dehydrate(self, bundle):
        for field in [
                'first_name',
                'last_name',
                'sAMAccountName',
                'email',
        ]:
            bundle.data[field] = getattr(bundle.obj, field)
        return bundle
示例#28
0
class AnalysisToolResource(FootprintResource):

    config_entity = ToOneField(ConfigEntityResource,
                               attribute='config_entity',
                               full=False,
                               null=False)
    behavior = ToOneField(BehaviorResource,
                          attribute='behavior',
                          full=False,
                          null=True)

    class Meta(FootprintResource.Meta):
        always_return_data = True,
        filtering = {"config_entity": ALL_WITH_RELATIONS}
        queryset = AnalysisTool.objects.all()
        resource_name = 'analysis_tool'
示例#29
0
class CalResource(ModelResource):
    user = ToOneField(UserResource, 'user', full=True)

    #user = model.ForeignKey(UserResource, 'username')
    class Meta:
        queryset = Cal.objects.all()
        paginator_class = Paginator
        authorization = CalAuth()
示例#30
0
class PortfolioResource(FlatListMixin, ModelResource):
    client_contact = ToOneField('nexus.api.ContactResource',
                                'contact',
                                null=True,
                                full=True)
    client = ToOneField(ClientResource, 'client', null=True)

    properties = ToManyField('nexus.api.PropertyResource',
                             'property_set',
                             null=True)

    class Meta:
        queryset = Portfolio.objects.all()
        resource_name = 'portfolio'
        authorization = Authorization()
        always_return_data = True
        filtering = {'client': ALL_WITH_RELATIONS}
示例#31
0
class AppraisalStatusChangeResource(ModelResource):
    appraisal = ToOneField('nexus.api.AppraisalResource', 'appraisal')

    class Meta:
        queryset = AppraisalStatusChange.objects.all()
        resource_name = 'appraisal-status-change'
        authorization = Authorization()
        always_return_data = True
示例#32
0
class StudentProjectResource(ModelResource):
    student = ToOneField(StudentResource, 'student', full=False)

    class Meta:
        queryset = StudentProject.objects.all()
        resource_name = "projects"
        allowed_methods = ['get', 'post', 'put', 'delete']
        authentication = Authentication()
        authorization = Authorization()
示例#33
0
class AddressResource(ModelResource):
    property = ToOneField('nexus.api.PropertyResource', 'property', null=True)

    class Meta:
        queryset = Address.objects.all()
        resource_name = 'address'
        authorization = Authorization()
        always_return_data = True
        excludes = ['created', 'changed']
示例#34
0
class DBTemplateResource(ModelResource):
    type = ToOneField(DBTemplateTypeNameResource, 'type')
    group = ToOneField(GroupResource, 'group', null=True)

    class Meta:
        cache = SimpleCache()
        queryset = DBTemplate.objects.all()
        serializer = api.Serializer()
        #resource_name = 'dbtemplate'
        filtering = {
            "id": ALL,
            "path": ALL,
            "title": ALL,
            "variables": ALL,
            "content": ALL,
            "type": ALL_WITH_RELATIONS,
            "group": ALL_WITH_RELATIONS,
        }
示例#35
0
    def test_resource_from_data(self):
        ur = UserResource()
        field_1 = ToOneField(UserResource, 'author')
        fk_bundle = field_1.resource_from_data(ur, {
            'username': u'mistersmith',
            'email': u'*****@*****.**',
            'password': u'foobar',
        })
        self.assertEqual(fk_bundle.data['username'], u'mistersmith')
        self.assertEqual(fk_bundle.data['email'], u'*****@*****.**')
        self.assertEqual(fk_bundle.obj.username, u'mistersmith')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')

        fk_bundle = field_1.resource_from_data(ur, {
            'username': u'mistersmith',
            'email': u'*****@*****.**',
            'password': u'foobar',
        }, related_obj='Foo', related_name='Bar')
        self.assertEqual(fk_bundle.related_obj, 'Foo')
        self.assertEqual(fk_bundle.related_name, 'Bar')
示例#36
0
    def test_dehydrate(self):
        note = Note()
        bundle = Bundle(obj=note)

        field_1 = ToOneField(UserResource, 'author')
        self.assertRaises(ApiFieldError, field_1.dehydrate, bundle)

        field_2 = ToOneField(UserResource, 'author', null=True)
        self.assertEqual(field_2.dehydrate(bundle), None)

        note = Note.objects.get(pk=1)
        bundle = Bundle(obj=note)

        field_3 = ToOneField(UserResource, 'author')
        self.assertEqual(field_3.dehydrate(bundle), '/api/v1/users/1/')

        field_4 = ToOneField(UserResource, 'author', full=True)
        user_bundle = field_4.dehydrate(bundle)
        self.assertEqual(isinstance(user_bundle, Bundle), True)
        self.assertEqual(user_bundle.data['username'], u'johndoe')
        self.assertEqual(user_bundle.data['email'], u'*****@*****.**')
示例#37
0
    def test_has_default(self):
        field_1 = ToOneField(UserResource, 'author')
        self.assertEqual(field_1.has_default(), False)

        field_1 = ToOneField(UserResource, 'author', default=1)
        self.assertEqual(field_1.has_default(), True)
示例#38
0
    def test_hydrate(self):
        note = Note()
        bundle = Bundle(obj=note)

        # With no value or nullable, we should get an ``ApiFieldError``.
        field_1 = ToOneField(UserResource, 'author')
        self.assertRaises(ApiFieldError, field_1.hydrate, bundle)

        note = Note.objects.get(pk=1)
        bundle = Bundle(obj=note)

        # The nullable case.
        field_2 = ToOneField(UserResource, 'author', null=True)
        field_2.instance_name = 'fk'
        bundle.data['fk'] = None
        self.assertEqual(field_2.hydrate(bundle), None)

        # Wrong resource URI.
        field_3 = ToOneField(UserResource, 'author')
        field_3.instance_name = 'fk'
        bundle.data['fk'] = '/api/v1/users/abc/'
        self.assertRaises(NotFound, field_3.hydrate, bundle)

        # A real, live attribute!
        field_4 = ToOneField(UserResource, 'author')
        field_4.instance_name = 'fk'
        bundle.data['fk'] = '/api/v1/users/1/'
        fk_bundle = field_4.hydrate(bundle)
        self.assertEqual(fk_bundle.data['username'], u'johndoe')
        self.assertEqual(fk_bundle.data['email'], u'*****@*****.**')
        self.assertEqual(fk_bundle.obj.username, u'johndoe')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')

        field_5 = ToOneField(UserResource, 'author')
        field_5.instance_name = 'fk'
        bundle.data['fk'] = {
            'username': u'mistersmith',
            'email': u'*****@*****.**',
            'password': u'foobar',
        }
        fk_bundle = field_5.hydrate(bundle)
        self.assertEqual(fk_bundle.data['username'], u'mistersmith')
        self.assertEqual(fk_bundle.data['email'], u'*****@*****.**')
        self.assertEqual(fk_bundle.obj.username, u'mistersmith')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')

        # Regression - Make sure Unicode keys get converted to regular strings
        #              so that we can **kwargs them.
        field_6 = ToOneField(UserResource, 'author')
        field_6.instance_name = 'fk'
        bundle.data['fk'] = {
            u'username': u'mistersmith',
            u'email': u'*****@*****.**',
            u'password': u'foobar',
        }
        fk_bundle = field_6.hydrate(bundle)
        self.assertEqual(fk_bundle.data['username'], u'mistersmith')
        self.assertEqual(fk_bundle.data['email'], u'*****@*****.**')
        self.assertEqual(fk_bundle.obj.username, u'mistersmith')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')

        # Attribute & null regression test.
        # First, simulate data missing from the bundle & ``null=True``.
        # Use a Note with NO author, so that the lookup for the related
        # author fails.
        note = Note.objects.create(
            title='Biplanes for all!',
            slug='biplanes-for-all',
            content='Somewhere, east of Manhattan, will lie the mythical land of planes with more one wing...'
        )
        bundle = Bundle(obj=note)
        field_7 = ToOneField(UserResource, 'notinbundle', null=True)
        field_7.instance_name = 'notinbundle'
        self.assertEqual(field_7.hydrate(bundle), None)
        # Then do something in the bundle also with ``null=True``.
        field_8 = ToOneField(UserResource, 'author', null=True)
        field_8.instance_name = 'author'
        fk_bundle = field_8.hydrate(bundle)
        self.assertEqual(field_8.hydrate(bundle), None)
        # Then use an unsaved object in the bundle also with ``null=True``.
        # new_note = Note(
        #     title='Biplanes for all!',
        #     slug='biplanes-for-all',
        #     content='Somewhere, east of Manhattan, will lie the mythical land of planes with more one wing...'
        # )
        # new_bundle = Bundle(obj=new_note)
        field_9 = ToOneField(UserResource, 'author', null=True)
        field_9.instance_name = 'author'
        self.assertEqual(field_9.hydrate(bundle), None)

        # The blank case.
        field_10 = ToOneField(UserResource, 'fk', blank=True)
        field_10.instance_name = 'fk'
        self.assertEqual(field_10.hydrate(bundle), None)

        bundle.data['author'] = '/api/v1/users/1/'
        field_11 = ToOneField(UserResource, 'author', blank=True)
        field_11.instance_name = 'author'
        fk_bundle = field_11.hydrate(bundle)
        self.assertEqual(fk_bundle.obj.username, 'johndoe')

        # The readonly case.
        field_12 = ToOneField(UserResource, 'author', readonly=True)
        field_12.instance_name = 'author'
        self.assertEqual(field_12.hydrate(bundle), None)

        # A related object.
        field_13 = ToOneField(UserResource, 'author')
        field_13.instance_name = 'fk'
        bundle.related_obj = User.objects.get(pk=1)
        bundle.related_name = 'author'
        fk_bundle = field_13.hydrate(bundle)
        self.assertEqual(fk_bundle.obj.username, u'johndoe')
        self.assertEqual(fk_bundle.obj.email, u'*****@*****.**')