2013-04-16 41 views
14

Tôi có một truy vấn đơn giản trên của django xây dựng trong mô hình ý kiến ​​và nhận được báo lỗi dưới đây với cơ sở dữ liệu PostgreSQL Heroku của:heroku, postgreSQL, django, comments, tastypie: Không có toán tử nào khớp với tên và kiểu đối số đã cho. Bạn có thể cần phải thêm loại rõ ràng phôi

DatabaseError: operator does not exist: integer = text LINE 1: 
... INNER JOIN "django_comments" ON ("pi ns_pin"."id" = "django_... 
                 ^
HINT: No operator matches the given name and argument type(s). 
You might need to add explicit type casts. 

Sau khi googling xung quanh nó dường như lỗi này đã được giải quyết nhiều lần trước đây trong django, nhưng tôi vẫn nhận được nó (tất cả các vấn đề liên quan đã được đóng cửa 3-5 năm trước). Tôi đang sử dụng phiên bản django 1.4 và phiên bản mới nhất của món ăn ngon.

Các truy vấn được thực hiện theo các bộ lọc orm và hoạt động hoàn hảo với cơ sở dữ liệu phát triển của tôi (sqlite3):

class MyResource(ModelResource):  

    comments = fields.ToManyField('my.api.api.CmntResource', 'comments', full=True, null=True) 

    def build_filters(self, filters=None): 
     if filters is None: 
      filters = {} 

     orm_filters = super(MyResource, self).build_filters(filters) 

     if 'cmnts' in filters: 
      orm_filters['comments__user__id__exact'] = filters['cmnts'] 

class CmntResource(ModelResource): 
    user = fields.ToOneField('my.api.api.UserResource', 'user', full=True) 
    site_id = fields.CharField(attribute = 'site_id') 
    content_object = GenericForeignKeyField({ 
     My: MyResource, 
    }, 'content_object') 
    username = fields.CharField(attribute = 'user__username', null=True) 
    user_id = fields.CharField(attribute = 'user__id', null=True) 

Bất kỳ ai có bất cứ kinh nghiệm với việc xung quanh lỗi này mà không cần viết SQL thô?

+0

Giống như lỗi nói, bạn đang cố gắng so sánh số nguyên với giá trị văn bản. Ngừng làm điều đó và lỗi sẽ biến mất. –

+0

Ngẫu nhiên, đây là một ví dụ tốt về lý do tại sao việc thử nghiệm nên được thực hiện với một môi trường tương tự nhất có thể với nơi bạn triển khai: tuy nhiên nhiều khung công tác tuyên bố trừu tượng về nó, một thứ phức tạp như DBMS bị ràng buộc có hành vi và giới hạn khác nhau . – IMSoP

+0

IMSoP, có thực sự tôi đã học được bài học hôm nay! Chỉ cần thay đổi DB phát triển của tôi sang PostgreSQL để làm việc về vấn đề này. – arctelix

Trả lời

4

Xây dựng dựa trên câu trả lời của IMSoP: Đây là giới hạn của lớp ORM của django khi khóa ngoài chung sử dụng trường văn bản cho object_id và trường id của đối tượng không phải là trường văn bản. Django không muốn thực hiện bất kỳ giả định hoặc đúc id của đối tượng như một cái gì đó nó không. Tôi đã tìm thấy một bài viết tuyệt vời về điều này http://charlesleifer.com/blog/working-around-django-s-orm-to-do-interesting-things-with-gfks/.

Tác giả bài viết, Charles Leifer đã đưa ra một giải pháp rất tuyệt vời cho truy vấn bị ảnh hưởng bởi điều này và sẽ rất hữu ích trong việc giải quyết vấn đề này trong tương lai.

Ngoài ra, tôi quản lý để có được truy vấn của tôi để làm việc như sau:

if 'cmnts' in filters: 
    comments = Comment.objects.filter(user__id=filters['cmnts'], content_type__name = 'my', site_id=settings.SITE_ID).values_list('object_pk', flat=True) 
    comments = [int(c) for c in comments] 
    orm_filters['pk__in'] = comments 

Nguyên tôi đã được tìm kiếm một cách để sửa đổi các SQL tương tự như những gì Charles đã làm, nhưng nó quay ra tất cả tôi đã phải làm là phá vỡ các truy vấn ra thành hai phần và chuyển đổi str (id) 's để int (id)' s.

29

PostgreSQL được "nhập mạnh" - nghĩa là mọi giá trị trong mỗi truy vấn đều có loại cụ thể, được xác định rõ ràng (ví dụ: loại cột trong bảng) hoặc ngầm (ví dụ: giá trị nhập vào mệnh đề WHERE) . Tất cả các hàm và toán tử, kể cả =, phải được định nghĩa là chấp nhận các loại cụ thể - ví dụ, có toán tử cho VarChar = VarChar và một số khác cho .

Trong trường hợp của bạn, bạn có một cột được định nghĩa rõ ràng là loại int, nhưng bạn đang so sánh nó với giá trị mà PostgreSQL đã hiểu là loại text.

SQLite, mặt khác, được "nhập sai" - các giá trị được xử lý tự do như bất kỳ loại nào phù hợp nhất với hành động đang được thực hiện. Vì vậy, trong cơ sở dữ liệu SQLite dev của bạn, hoạt động '42' = 42 có thể được tính toán tốt, nơi PostgreSQL sẽ cần định nghĩa cụ thể của VarChar = int (hoặc text = int, text là loại cho chuỗi không bị chặn trong PostgreSQL).

Bây giờ, PostgreSQL sẽ đôi khi hữu ích và tự động "bỏ" giá trị của bạn để làm cho các loại khớp với toán tử đã biết, nhưng thường xuyên hơn, như gợi ý, bạn cần làm điều đó một cách rõ ràng. Nếu bạn đang tự viết SQL, một trường hợp kiểu rõ ràng có thể trông giống như WHERE id = CAST('42' AS INT) (hoặc WHERE CAST(id AS text) = '42').

Vì bạn không, bạn cần đảm bảo rằng đầu vào bạn cung cấp cho trình tạo truy vấn là một số nguyên thực, không chỉ là một chuỗi xảy ra bao gồm các chữ số. Tôi nghi ngờ điều này đơn giản như sử dụng fields.IntegerField thay vì fields.CharField, nhưng tôi không thực sự biết Django, hoặc thậm chí Python, vì vậy tôi nghĩ tôi sẽ cung cấp cho bạn nền với hy vọng bạn có thể lấy nó từ đó.

+0

Cảm ơn các thông tin, rất tốt đặt và tôi hiểu rằng đó là những gì gây ra lỗi. Vấn đề là gfk của django cho mô hình bình luận sử dụng một trường văn bản cho object_id và đối tượng được nhận xét sử dụng một trường số nguyên .. Vì vậy, thực sự nhiệm vụ nên có được làm thế nào để tôi có được xung quanh điều này mà không giới hạn mô hình bình luận để số nguyên của id. – arctelix