1👍
A Resource
is ‘just’ a python class so you could simply create a base resource and inherit it with only the queryset
and resource_name
Meta attributes defined.
You could probably automate naming too by fiddling with the Resource
class’s __new__
method or create a custom classmethod
, but I’m not sure the effort will gain you much.
Registering the classes to the api can be automated in numerous ways, of which one could be:
for name, obj in inspect.getmembers(sys.modules['resources']):
if inspect.isclass(obj): # might want to add a few exclusions
v1_api.register(obj())
where ‘resources’ is the name of the module containing resources, but this is kind of implicit..
1👍
create a custom base model derived from models.Model. In that model add an empty Resource class that has no object and follow the instructions in the Tastypie manuals:
https://django-tastypie.readthedocs.io/en/latest/non_orm_data_sources.html
Derive all models in your application from the newly created custom model and you have it.
In order for it to work you will need some magic. I am using a separate class that acts as a middleware between the ORM and the business layer(the model adapter), but I would say it should be possible to go without it.
What got me struggling was the way to pass the correct class in the init of the apiResource.
I ended overriding the init and registering the resource like that:
v1_api.register(BusinessClientContact.apiResource(BusinessClientContact))
Unfortunately there is no way to inject content into the meta class of the resource. You can get it to work, but as you start adding resources you will find out that the interpreter does not create separate instances of the class.Meta and the self._meta unless you do no make explicit changes in the code. The latter leaves all attempts to modify the _meta structure dynamically broken, since you work on the same _meta instance regardless of the fact that each of your resources is a different instance. The workaround I use is to inherit the apiResourceBase class in each of the model classes which I want to expose through the api and manually configure the Meta class. The code in the model class ends looking like that:
class apiResource(SystemModelBase.apiResourceBase):
class Meta:
resource_name = 'client_contacts'
#more stuff here
Depending on the design you go for, you may expand the localized apiResource to enable custom views and filters.
A sample implementation of the resource class itself looks like this:
class apiResourceBase(Resource):
def __init__(self,f_modelClass):
self.m_objMetaModel = f_modelClass.create_model_adapter()
super(SystemModelBase.apiResource,self).__init__()
#obj_create
#obj_update
#obj_delete_list
#obj_delete
#rollback
def detail_uri_kwargs(self, bundle_or_obj):
kwargs = {}
if isinstance(bundle_or_obj, Bundle):
kwargs['pk'] = bundle_or_obj.obj.id
else:
kwargs['pk'] = bundle_or_obj.id
return kwargs
def obj_get_list(self, bundle, **kwargs):
return self.get_object_list(bundle.request)
def get_object_list(self,request):
return self.m_objMetaModel.REST_IMPL.get_object_list(request)
def obj_get(self, bundle, **kwargs):
self.m_objMetaModel.load(kwargs['pk'],True)
return self.m_objMetaModel.instance
def dehydrate(self, bundle):
return self.m_objMetaModel.REST_IMPL.dehydrate(bundle)
the actual implementation here (get_object_list and dehydrate) is out of scope but, it may help someone so I will add it:
def get_object_list(self,request):
l_clientID = request.GET['client']
l_filterDict = {}
l_filterDict['client_account__id']=l_clientID
return self.query_filter(l_filterDict)
def dehydrate(self,bundle):
l_objInstance = bundle.obj
l_apiDict = {}
l_apiDict['resource_uri'] = bundle.data['resource_uri']
l_apiDict['id'] = l_objInstance.id
l_apiDict['name'] = l_objInstance.user_account.name
l_apiDict['email'] = l_objInstance.user_account.email
l_apiDict['phone'] = l_objInstance.user_account.phone
l_apiDict['additional_contacts'] = l_objInstance.user_account.additional_contacts
l_apiDict['is_active'] = l_objInstance.user_account.user.is_active
bundle.data = l_apiDict
return bundl
this is a proof of concept code, in a production you can pretty much replicate the logic Tastypie uses to load models and expose those.
- [Answered ]-Testing celery task
- [Answered ]-Django user not in request object when running tests
- [Answered ]-Django-summernote setting configuration failing only language part