假设我有两个Django模型,ModelA和ModelB。在某些情况下,ModelA对象的创建应该触发ModelB对象的创建。目前,在没有使用Tastypie的情况下,我有以下视图来控制A对象的创建:
def new_A_created_view(request):
post_data = json.loads(request.body)
... parse post arguments ...
a = ModelA.objects.create(...)
if conditions_are_met(...):
b = ModelB.objects.create(...)
现在我想转换到REST Api,并使用TastyPie我有以下资源:
class ModelAResource(ModelResource):
class Meta:
queryset = ModelA.objects.all()
authorization = Authorization()
...
def hydrate(self, bundle):
if bundle.request.META['REQUEST_METHOD'] == 'POST':
...compute objects attributes from received post data ...
我知道以下选项来创建相应的B对象:
覆盖save或post_save方法。覆盖保存方法或在ModelA中添加post_save信号,以便创建对象B后立即执行保存A.我在此方法中看到的问题:
覆盖ModelAResource中的Resource.obj_create ,以便根据资源POST信息创建ModelA对象和ModelB对象(如果需要)。在这种情况下,我也觉得对象的创建在某种程度上被遮挡了。
我遗失的任何解决方案?最好的方法是什么?
答案 0 :(得分:0)
因为ModalA与ModelB有关系,并且您希望在保存ModelA时自动保存ModelB,所以您的资源声明应该是,
from tastypie.resources import ModelResource
from tastypie import fields
from yourapp.models import ModelA, ModelB
class ModelAResource(ModelResource):
model_b = fields.ForeignKey(
'yourapp.resources.ModelBResource',
'model_b',
full=True
)
# ....
class Meta:
queryset = ModelA.objects.all()
# ....
class ModelBResource(ModelResource):
# ....
class Meta:
queryset = ModelB.objects.all()
# ....
当您发布/ PUT / PATCH时,您只需将model_b
放入数据中,就像创建/编辑model_b
例如,
{
"field1_of_model_a" : "content_of_field1_of_model_a",
"field2_of_model_a" : "content_of_field2_of_model_a",
"model_b" : {
"field_1_of_model_b" : "content_of_field_1_of_model_b",
"field_2_of_model_b" : "content_of_field_2_of_model_b"
}
}
答案 1 :(得分:0)
最后,我在资源类中添加了一个url,覆盖了资源的入口点,并将其定向到执行所需逻辑的类的自定义函数。我也从资源中删除了任何保湿剂。
class ModelAResource(ModelResource):
class Meta:
queryset = ModelAResource.objects.all()
authentication = MyOwnAuthentication()
resource_name = 'modelAResource'
allowed_methods = ['post']
def prepend_urls(self):
return [url(r"^(?P<resource_name>%s)%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('process_resource'), name="process_resource")]
def process_resource(self, request, **kwargs):
self.method_check(request, allowed=['post'])
self.is_authenticated(request)
data = self.deserialize(request, request.body)
param1 = data.get('param1name', '')
param2 = data.get('param2name', '')
ModelA.objects.create(...)
if it_should_be_done(param1, param2):
ModelB.objects.create(...)
当然这有一些注意事项,因为我已经覆盖了访问API的默认网址,但在我的情况下这没有问题,因为API只会在资源上公开一个操作(创建)。无论如何,前缀的网址可以是任何东西。