我正面临着django-tastypie的一个非常奇怪的问题。好吧,这有点过于复杂,所以让我从我的应用程序的技术堆栈开始。
我有一个comment
模型和两个用户模型Student
和Teacher
,它们是从基础用户模型的子类化派生而来的。如下所示。
## Base User
class BaseUser(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
# some more common fields here
## Teacher Model
class Teacher(BaseUser):
college = models.ForeignKey(College)
## Student Model
class Student(BaseUser):
Address = models.OneToOneField(Address)
## Comment Model
class Comment(models.Model):
date = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(backend.models.CustomUser)
body = models.TextField()
# Generic Relation with other models
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
user = generic.GenericForeignKey('content_type', 'object_id')
现在您可以在我的comment
模型中看到我使用GenericForeignKey
,以便用户可以对任何其他模型发表评论。
我在tastypie api.py文件中定义的资源如下:
class TeacherResource(BaseModelResource):
college = fields.ToOneField(CollegeResource, 'college', full=True)
class Meta(BaseModelResource.Meta):
queryset = models.Teacher.objects.all()
resource_name = 'teacher'
def dehydrate(self, bundle):
# Add content type url
ctype = models.ContentType.objects.get_for_model(models.Teacher)
bundle.data['content_type_id'] = ctype.id
bundle.data['content_type'] = '/api/v1/contrib/contenttype/%i' % ctype.id
return bundle
class StudentResource(BaseModelResource):
class Meta(BaseModelResource.Meta):
queryset = models.Student.objects.all()
resource_name = 'student'
def dehydrate(self, bundle):
# Add content type url
ctype = models.ContentType.objects.get_for_model(\
models.ProspectiveCandidate)
bundle.data['content_type_id'] = ctype.id
bundle.data['content_type'] = '/api/v1/contrib/contenttype/%i' % ctype.id
return bundle
class CommentResource(BaseModelResource):
custom_user = fields.ToOneField(CustomUserResource,
'custom_user', full=True)
user = fields.ToOneField(ContentTypeResource, 'content_type')
class Meta(MarketingResource.Meta):
queryset = models.Comment.objects.all()
resource_name = 'comment'
always_return_data = True
filtering = {
'user' : ALL_WITH_RELATIONS,
'object_id': ALL_WITH_RELATIONS
}
def hydrate(self, bundle):
print bundle.data
bundle.obj.user = models.ContentType.objects.get_for_id(\
int(bundle.data['object_id']))
bundle.obj.object_id = int(bundle.data['object_id'])
bundle.obj.employee = bundle.request.user.custom_user
return bundle
def dehydrate(self, bundle):
if bundle.obj.date:
bundle.data['date'] = timesince.timesince(bundle.obj.date)
return bundle
以上所有资源均已正确注册。每个资源的GET
方法都可以完美运行。我使用angularjs'
$resource
来调用tastypie的REST api。以下是我用于向CommentResource
发送帖子请求以创建新的commetn对象的通用方法。
function make_comment(service, scope){
service.save({
"user": scope.user.content_type,
"object_id": scope.user.id,
"comments": $("textarea#comment").val()
}, function(data){
// Success callback Method
scope.comments.push(data);
});
}
很简单呃?现在在上面的方法中,scope.user
可以是教师对象或学生对象,并且该方法只是使用该服务来发出具有给定数据的POST请求:
http://127.0.0.1:8000/api/v1/comment
问题是,当scope.user
是学生对象并且我调用上述方法时,我得到201 created
响应,但当它是教师对象时,它会给我404 Not Found
错误
使用student和teacher对象时传入的数据非常相似(如下所示):
传入的学生数据data = {'user':'/ api / v1 / contrib / contenttype / 15','object_id':'16','comments':'sadfsadfsadfasdf'} response = [19 / Mar / 2013 18:08:47]“POST / api / v1 / comment HTTP / 1.1”201 741
传入的教师数据data = {'user':'/ api / v1 / contrib / contenttype / 14','object_id':'62','comments':'test comment'} response = [19 / Mar / 2013 18:09:44]“POST / marketing / api / v1 / comment HTTP / 1.1”404 3211
我无法理解为什么使用相同的代码可以用于一个模型而不用于另一个模型?能不能给我一些指示。感谢。
所以我使用的是自定义http错误跟踪中间件,它将响应发送为404 Not Found
,当我关闭它时,我现在收到以下错误。
ContentType匹配查询不存在
我查了一下数据库,id为14的contenttype是教师,它就在数据库中。
答案 0 :(得分:0)
问题在于水合物方法:
def hydrate(self, bundle):
print bundle.data
bundle.obj.user = models.ContentType.objects.get_for_id(\
int(bundle.data['object_id'])) // this should be content_type_id
bundle.obj.object_id = int(bundle.data['object_id'])
bundle.obj.employee = bundle.request.user.custom_user
return bundle
所以更改了注释函数以传递content_type_id
并将水合物方法更改为
def hydrate(self, bundle):
print bundle.data
bundle.obj.user = models.ContentType.objects.get_for_id(\
int(bundle.data['content_type_id'])) // this was friggin stupid.
bundle.obj.object_id = int(bundle.data['object_id'])
bundle.obj.employee = bundle.request.user.custom_user
return bundle