如何配置 Tastypie 将字段视为唯一字段?
如何配置 Tastypie 将字段视为唯一字段?如果我尝试为标记为唯一的字段插入重复条目,我的期望是收到某种非 500 错误(可能是 409 冲突?)作为响应。
我已经浏览了文档,看起来这对我来说应该是显而易见的,但由于某种原因,我没有得到我期望看到的响应。
这是文档链接:
http://readthedocs.org/ docs/django-tastypie/en/latest/fields.html?highlight=unique
示例代码如下:
urls.py
v1_api = Api(api_name='v1')
v1_api.register(CompanyResource())
urlpatterns = patterns('',
(r'^api/', include(v1_api.urls)),
)
resources.py
class CompanyResource(ModelResource):
CompanyName = fields.CharField(attribute='company_name')
CompanyId = fields.CharField(attribute='company_id', unique=True)
Contact = fields.CharField(attribute='contact')
Email = fields.CharField(attribute='email')
Phone = fields.CharField(attribute='phone')
class Meta:
queryset = Company.objects.all()
authentication = BasicAuthentication()
authorization = Authorization()
allowed_methods = ['get', 'post']
models.py
class Company(models.Model):
company_name = models.TextField(default=None, blank=True, null=True)
company_id = models.CharField(default='', unique=True, db_index=True, max_length=20)
contact = models.TextField(default=None, blank=True, null=True)
email = models.EmailField(default=None, blank=True, null=True)
phone = models.TextField(default=None, blank=True, null=True)
我收到的错误是以下(使用curl来访问我的本地服务):
curl --dump-header - -H "Content-Type: application/json" -X POST --user user:password --data '{"CompanyName": "company", "CompanyId": "1234567890", "Contact": "John", "Email": "[email protected]", "Phone": "555-555-5555"}' http://localhost:8000/api/v1/company/
HTTP/1.0 500 INTERNAL SERVER ERROR
Date: Thu, 15 Sep 2011 18:25:20 GMT
Server: WSGIServer/0.1 Python/2.7.1
Content-Type: application/json; charset=utf-8
{"error_message": "(1062, \"Duplicate entry '1234567890' for key 'api_company_company_id_uniq'\")",
...<snip>...
raise errorclass, errorvalue\n\nIntegrityError: (1062, \"Duplicate entry '1234567890' for key 'api_company_company_id_uniq'\")\n"}
当我从公司模型中删除unique=True, db_index=True,
时,我没有收到完整性错误,而是收到一个新的重复错误资源已创建。同样,这不是预期的结果,因为我期望 unique 执行一些验证并导致一些非 500 响应。
How do I configure Tastypie to treat a field as unique? My expectation would be to receive some sort of non-500 error (possibly a 409 conflict?) as a response if I try to insert duplicate entries for the field marked as unique.
I've looked through the docs and it looks like it should be obvious to me, but for some reason I'm not getting the response I would expect to see.
Here's the documentation link:
http://readthedocs.org/docs/django-tastypie/en/latest/fields.html?highlight=unique
The sample code is as follows:
urls.py
v1_api = Api(api_name='v1')
v1_api.register(CompanyResource())
urlpatterns = patterns('',
(r'^api/', include(v1_api.urls)),
)
resource.py
class CompanyResource(ModelResource):
CompanyName = fields.CharField(attribute='company_name')
CompanyId = fields.CharField(attribute='company_id', unique=True)
Contact = fields.CharField(attribute='contact')
Email = fields.CharField(attribute='email')
Phone = fields.CharField(attribute='phone')
class Meta:
queryset = Company.objects.all()
authentication = BasicAuthentication()
authorization = Authorization()
allowed_methods = ['get', 'post']
models.py
class Company(models.Model):
company_name = models.TextField(default=None, blank=True, null=True)
company_id = models.CharField(default='', unique=True, db_index=True, max_length=20)
contact = models.TextField(default=None, blank=True, null=True)
email = models.EmailField(default=None, blank=True, null=True)
phone = models.TextField(default=None, blank=True, null=True)
The error I receive is the following (using curl to hit my local service):
curl --dump-header - -H "Content-Type: application/json" -X POST --user user:password --data '{"CompanyName": "company", "CompanyId": "1234567890", "Contact": "John", "Email": "[email protected]", "Phone": "555-555-5555"}' http://localhost:8000/api/v1/company/
HTTP/1.0 500 INTERNAL SERVER ERROR
Date: Thu, 15 Sep 2011 18:25:20 GMT
Server: WSGIServer/0.1 Python/2.7.1
Content-Type: application/json; charset=utf-8
{"error_message": "(1062, \"Duplicate entry '1234567890' for key 'api_company_company_id_uniq'\")",
...<snip>...
raise errorclass, errorvalue\n\nIntegrityError: (1062, \"Duplicate entry '1234567890' for key 'api_company_company_id_uniq'\")\n"}
When I remove unique=True, db_index=True,
from the Company model, I don't receive the Integrity error, but instead, a new, duplicate resource is created. Again, this isn't the expected result as I would expect unique to preform some validation and cause some non-500 response.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
以下是我解决问题的方法:
根据验证文档,我能够实现一个自定义验证器来为我检查字段的唯一性。
http://django-tastypie.readthedocs.org/en/latest/validation。 在CompanyResource
中,我向类元添加了 CustomValidation。我将 CustomValidation 的实现放置在validations.py 文件中。如果 isValid 返回错误,API 将返回 400,并包含错误中的消息。
验证.py
Here is how I solved the problem:
Based on the documentation for validation, I was able to implement a custom validator that checked the uniqueness of the field for me.
http://django-tastypie.readthedocs.org/en/latest/validation.html
In the CompanyResource, I added to the class meta a CustomValidation. I placed the implementation for CustomValidation in a validations.py file. If isValid returns errors, the api will return a 400 with the messages included in errors.
validations.py
我今天也遇到了同样的问题。以下是我的处理方法:
覆盖资源定义中的 [request_method]_[request_type] 方法。例如,我覆盖 FooResource 中的 post_list:
希望它对您有用。
I had the same problem today. Here is how I deal with it:
Override [request_method]_[request_type] method in your resource definition. For example, I override post_list in FooResource:
Hope it works for you.
无论如何,我创建了一个稍微不同的解决方案,它更适合我。它基于 thoslin 的答案。
我发现 e.args[0] == 1062 检查对我来说失败了。我很确定这是一个 MySQL 错误,而且我正在使用 Postgres。
我还在 obj_create 方法中实现了这一点,以便它将处理所有对象创建,而不仅仅是通过 post_list 完成的对象创建。
For what it's worth, I've created a slightly different solution that works better for me. It's based on thoslin's answer.
I found that the e.args[0] == 1062 check fails for me. I'm pretty sure this is a MySQL error and I'm using Postgres.
I also implemented this in the obj_create method so that it will handle all object creation, not just that done via post_list.