我正在为使用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')
答案 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)