2011-07-19 17 views
9

Trong dự án django của tôi, tôi sử dụng db mysql cho sản xuất và sqlite để kiểm tra.Bật tính năng kiểm tra tính toàn vẹn với sqlite trong django

Vấn đề là, một số mã của tôi dựa vào kiểm tra tính toàn vẹn của mô hình. Nó hoạt động tốt với mysql, nhưng lỗi toàn vẹn không được ném khi cùng một mã được thực thi trong các thử nghiệm.

Tôi biết rằng các phím nước ngoài kiểm tra phải được kích hoạt trong sqlite:

PRAGMA foreign_keys = 1; 

Tuy nhiên, tôi không biết đâu là cách tốt nhất để làm kích hoạt này (same question here).

Hơn nữa, đoạn code sau sẽ không làm việc:

def test_method(self): 
    from django.db import connection 
    cursor = connection.cursor() 
    cursor.execute('PRAGMA foreign_keys = ON') 
    c = cursor.execute('PRAGMA foreign_keys') 
    print c.fetchone() 
    >>> (0,) 

Bất kỳ ý tưởng?

+3

Tại sao bạn không sử dụng cùng một DB cho các thử nghiệm được sử dụng trong sản xuất? Không phải là mục tiêu của môi trường thử nghiệm để tái tạo môi trường sản xuất? * –

+0

Thử nghiệm một ứng dụng duy nhất, với 'thời gian python manage.py kiểm tra sản phẩm'. Mysql: 0m58.232s. Sqlite: 0m5.153s. –

+0

Không phải là một khởi đầu của một giải pháp ở đây nhưng có vẻ như rất nhiều thảo luận (và các bản vá lỗi) đang diễn ra trên vé này về loại vấn đề bạn đang nêu tại đây https://code.djangoproject.com/ticket/11665 – NiKo

Trả lời

14

Vì vậy, nếu cuối cùng đã tìm thấy câu trả lời đúng. Tất cả những gì tôi phải làm là thêm mã này vào tệp __init__.py trong một trong các ứng dụng đã cài đặt của tôi:

from django.db.backends.signals import connection_created 


def activate_foreign_keys(sender, connection, **kwargs): 
    """Enable integrity constraint with sqlite.""" 
    if connection.vendor == 'sqlite': 
     cursor = connection.cursor() 
     cursor.execute('PRAGMA foreign_keys = ON;') 

connection_created.connect(activate_foreign_keys) 
+0

Điều này dường như không hoạt động trên [dữ liệu ban đầu] (https://docs.djangoproject.com/en/dev/howto/initial-data/) được thêm vào trong syncdb. – user240515

+0

Đảm bảo xóa các tệp di chuyển cũ không tạo khóa ngoài, nếu không các khóa ngoại sẽ không được tạo. Tôi đã bị mắc kẹt bởi điều này trong một thời gian. – fossilet

+1

Mặc dù tôi đã xóa tệp DB của mình, xóa tất cả các lần di chuyển trước đó và tạo các di chuyển mới, điều này không tạo ra sự khác biệt nào đối với tôi. Các bảng không được tạo bằng "on delete cascade" như mong đợi. Tôi tự hỏi tại sao điều đó không xảy ra. –

2

Bạn có thể sử dụng tín hiệu django, nghe post_syncdb.

from django.db.models.signals import post_syncdb 

def set_pragma_on(sender, **kwargs): 
    "your code here" 

post_syncdb.connect(set_pragma_on) 

Điều này đảm bảo rằng bất cứ khi nào syncdb chạy (syncdb được chạy, khi tạo cơ sở dữ liệu thử nghiệm), cơ sở dữ liệu SQLite của bạn đã đặt 'pragma' thành 'bật'. Bạn nên kiểm tra xem bạn đang sử dụng cơ sở dữ liệu nào trong phương thức 'set_pragma_on' ở trên.

+0

Câu trả lời của bạn không hoàn toàn chính xác, nhưng nó đã hướng dẫn tôi hướng tới giải pháp đúng (xem câu trả lời của tôi trên cùng một trang). Muchos gracias. –

+0

Điều này sẽ không có hiệu ứng mong đợi: lệnh 'post_syncdb' chỉ chạy sau' syncdb', không phải cho bất kỳ kết nối nào khác (và pragma không tồn tại lâu hơn kết nối hiện tại). –