2011-09-15 30 views
7

Làm cách nào để định cấu hình Tastypie để xử lý trường là duy nhất? Kỳ vọng của tôi là nhận được một số loại lỗi không phải 500 (có thể là xung đột 409?) Làm phản hồi nếu tôi cố gắng chèn các mục trùng lặp cho trường được đánh dấu là duy nhất.Làm cách nào để định cấu hình Tastypie để xử lý trường là duy nhất?


Tôi đã xem qua các tài liệu và có vẻ như nó phải rõ ràng với tôi, nhưng vì lý do nào đó, tôi không nhận được phản hồi tôi mong đợi.

Đây là liên kết tài liệu:

http://readthedocs.org/docs/django-tastypie/en/latest/fields.html?highlight=unique


Mẫu mã được như sau:

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) 

Các lỗi tôi nhận được như sau (sử dụng curl để đạt dịch vụ địa phương của tôi):

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"} 

Khi tôi loại bỏ unique=True, db_index=True, từ mô hình Công ty , Tôi không nhận được lỗi Integrity, nhưng thay vào đó, một tài nguyên mới trùng lặp được tạo ra. Một lần nữa, đây không phải là kết quả mong đợi như tôi mong đợi duy nhất để tạo ra một số xác nhận hợp lệ và gây ra một số phản hồi không phải 500.

+0

Tôi đang đối mặt với cùng một điều với các trường mô hình được định nghĩa là trống = True. Tastypie đang tạo bản ghi với các mục nhập trống. – Erik

+0

Câu trả lời cho tôi là sử dụng xác nhận = FormValidation (form_class = ). Điều này xác nhận các trường của mô hình của bạn. – Erik

Trả lời

8

Dưới đây là cách tôi giải quyết vấn đề:

Dựa trên các tài liệu để xác nhận, tôi đã có thể thực hiện một validator tùy chỉnh mà kiểm tra sự độc đáo của lĩnh vực này đối với tôi. http://django-tastypie.readthedocs.org/en/latest/validation.html

Trong CompanyResource, tôi đã thêm vào lớp meta một CustomValidation. Tôi đã đặt triển khai cho CustomValidation trong tệp validations.py. Nếu isValid trả về lỗi, thì api sẽ trả về 400 với các thông báo có lỗi.

class CompanyResource(ModelResource): 
    """ 
    CompanyIds should be unique 
    """  
    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']     
     validation = CustomValidation() 

validations.py

class CustomValidation(Validation): 
    """ 
    The custom validation checks two things: 
     1) that there is data 
     2) that the CompanyId exists (unique check) 
    """ 
    def is_valid(self, bundle, request=None): 
     if not bundle.data: 
      return {'__all__': 'Missing data, please include CompanyName, CompanyId, Contact, Email, and Phone.'} 

     errors = {}          
     company_id=bundle.data.get('CompanyId', None) 

     # manager method, returns true if the company exists, false otherwise 
     if Company.objects.company_exists(company_id): 
      errors['CompanyId']='Duplicate CompanyId, CompanyId %s already exists.' % company_id 
     return errors 
+0

Cách này hoạt động với PUT như thế nào? – toucan

+0

Không. Nếu bạn cần hỗ trợ PUT, bạn sẽ cần phải tiếp cận phương pháp 'thoslins' ở trên. – astevanovic

5

tôi đã cùng một vấn đề ngày hôm nay. Đây là cách tôi giải quyết:

Ghi đè phương pháp [request_method] _ [request_type] trong định nghĩa tài nguyên của bạn. Ví dụ: tôi ghi đè lên post_list trong FooResource:

def post_list(self, request, **kwargs): 
    from django.db import IntegrityError 
    try: 
     return super(FooResource, self).post_list(request, **kwargs) 
    except IntegrityError, e: 
     if e.args[0] == 1062: 
      return http.HttpConflict() 

Hy vọng nó hoạt động cho bạn.

+0

Tại sao bạn chọn nhập IntegrityError bên trong phương thức? – Jake

0

Đối với những gì đáng giá, tôi đã tạo một giải pháp hơi khác có hiệu quả hơn đối với tôi. Nó dựa trên câu trả lời của thoslin.

Tôi thấy rằng séc điện tử [0] == 1062 không thành công đối với tôi.Tôi khá chắc chắn đây là một lỗi MySQL và tôi đang sử dụng Postgres.

Tôi cũng đã triển khai phương thức này trong phương thức obj_create để nó xử lý tất cả các đối tượng tạo, không chỉ thực hiện qua post_list.

from tastypie.exceptions import ImmediateHttpResponse 
from tastypie.http import HttpConflict 
from django.db import IntegrityError 

... 

class MyBaseResource(ModelResource): 
    def obj_create(self, bundle, **kwargs): 
     try: 
      return super(MyBaseResource, self).obj_create(bundle, **kwargs) 
     except IntegrityError, e: 
      if e.args[0] == 1062 or e.args[0].startswith('duplicate key'): 
       raise ImmediateHttpResponse(HttpConflict()) 

... 

class MyResource(MyBaseResource): 
    [usual resource stuff] 
Các vấn đề liên quan