Django Tastypie:PUT请求返回状态204,但创建一个新对象而不是更新

时间:2014-03-18 14:28:52

标签: python django tastypie

我正在为使用Tastypie创建的资源编写单元测试。创建,读取和删除测试工作得很好,但每次我尝试发出PUT请求时,都会在数据库中创建一个新的Sample对象,而不是更新现有记录,即使正确的状态代码(204)是被退回。

这是失败的测试:

def test_user_can_update_own_sample(self):
    credentials = self.get_credentials()
    nt.assert_equal(Sample.objects.count(), 1)
    sample = self.deserialize(client.get('/tastyapi/v1/sample/1/',
                              authentication=credentials, format='json'))
    nt.assert_equal("Created by a test case", sample['description'])
    sample['description'] = "Updated by a test case"

    resp = client.put('/tastyapi/v1/sample/1/', data=sample,
                       authentication=credentials, format='json')

    self.assertHttpAccepted(resp)

    # The following test fails saying 2 != 1
    nt.assert_equal(Sample.objects.count(), 1)

这是我的模特:

class Sample(models.Model):
    sample_id = models.BigIntegerField(primary_key=True)
    version = models.IntegerField()
    sesar_number = models.CharField(max_length=9, blank=True)
    public_data = models.CharField(max_length=1)
    collection_date = models.DateTimeField(null=True, blank=True)
    date_precision = models.SmallIntegerField(null=True, blank=True)
    number = models.CharField(max_length=35)
    rock_type = models.ForeignKey(RockType)
    user = models.ForeignKey('User', related_name='+')
    location_error = models.FloatField(null=True, blank=True)
    country = models.CharField(max_length=100, blank=True)
    description = models.TextField(blank=True)
    location_text = models.CharField(max_length=50, blank=True)
    location = models.PointField()
    objects = models.GeoManager()
    metamorphic_grades = ManyToManyField(MetamorphicGrade, through='SampleMetamorphicGrade')
    metamorphic_regions = ManyToManyField(MetamorphicRegion, through='SampleMetamorphicRegion')
    minerals = ManyToManyField(Mineral, through='SampleMineral')
    references = ManyToManyField('Reference', through='SampleReference')
    regions = ManyToManyField(Region, through='SampleRegion')
    group_access = generic.GenericRelation(GroupAccess)

def __unicode__(self):
    return u'Sample #' + unicode(self.sample_id)

class Meta:
    # managed = False
    db_table = u'samples'
    permissions = (('read_sample', 'Can read sample'),)

这是资源:

class SampleResource(VersionedResource, FirstOrderResource):
rock_type = fields.ToOneField("tastyapi.resources.RockTypeResource",
                              "rock_type")
user = fields.ToOneField("tastyapi.resources.UserResource", "user")
class Meta:
    queryset = models.Sample.objects.all()
    allowed_methods = ['get', 'post', 'put', 'delete']
    authentication = ApiKeyAuthentication()
    authorization = ObjectAuthorization('tastyapi', 'sample')
    excludes = ['user', 'collector']
    filtering = {
            'version': ALL,
            'sesar_number': ALL,
            'public_data': ALL,
            'collection_date': ALL,
            'rock_type': ALL_WITH_RELATIONS,
            }
    validation = VersionValidation(queryset, 'sample_id')

1 个答案:

答案 0 :(得分:0)

看来对象的pk没有在put中发送。如果Tastypie在请求数据中找不到pk,则默认情况下会在PUT上创建一个新对象。 (检查here)。

您没有显示所有代码,因此无法确定请求中是否存在字段sample_id,或者您是否正在将get(通过测试)检索的数据放入其中。

另一个可能的问题是,BigIntegerField未被tastypie正确检查,并被视为Charfield。 Check this pull request

因此要么使用提到的fork,要么更改BigInteger,或者在特定字段的水合物中将char值转换为int值。

def hydrate_sample_id(self ,value):
    return long(value)