5

Tôi có cơ sở dữ liệu cũ, trong đó một số bảng chứa khóa chính kết hợp. Mô hình tôi nhận được bằng cách chạy lệnh manage.py inspectdb giống như thế này.Làm việc với khóa chính kết hợp trong dự án django với cơ sở dữ liệu kế thừa

class MyTable(models.Model): 
    field1_id = models.IntegerField(db_column='field1id', primary_key=True) 
    is_favorite = models.BooleanField(db_column='isfavorite', default=False, null=False) 
    is_admin = models.BooleanField(db_column='isadmin', default=False, null=False) 
    role = models.IntegerField(default=USER_GUEST, null=False) 
    field2 = models.BooleanField(null=False, default=True) 
    field3 = models.BooleanField(null=False, default=True) 
    is_active = models.BooleanField(db_column='isactive', null=False, default=True) 

    user = models.ForeignKey(
     CustomUser, models.DO_NOTHING, db_column='userid', primary_key=True) 

    class Meta: 
     managed = False 
     db_table = 'mytable' 
     unique_together = (('user', 'field1_id'),) 

Tôi có thể tìm nạp dữ liệu bình thường. Tuy nhiên, vấn đề phát sinh khi tôi muốn chạy lệnh save() trên một số phiên bản mẫu. Truy vấn django thực thi không đúng. Ví dụ:

>>> from web_services.apps.my_app.models import MyTable 
>>> g = MyTable.objects.get(field1_id=12) 
>>> g.is_active = True 
>>> g.save() 
>>> connection.queries[-1] 
{'time': '0.000', 'sql': 'UPDATE `mytable` SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 WHERE `mytable`.`field1id` = 12'} 

Nhưng tôi cần:

{'time': '0.000', 'sql': 'UPDATE `mytable` SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 WHERE `mytable`.`field1id` = 12' AND `mytable`.`userid` = 1'} 

Kể từ django không hỗ trợ khóa chính composite, những gì sẽ là giải pháp tốt nhất để khắc phục vấn đề đó? Lưu ý, đó là bảng cơ sở dữ liệu cũ và nó không có AutoField.

EDIT: thêm cấu trúc bảng di sản

+------------+------------+------+-----+---------+-------+ 
| Field  | Type  | Null | Key | Default | Extra | 
+------------+------------+------+-----+---------+-------+ 
| userid  | int(11) | NO | PRI | NULL |  | 
| field1id | int(11) | NO | PRI | NULL |  | 
| isfavorite | int(11) | NO |  | 0  |  | 
| isadmin | int(11) | NO |  | 0  |  | 
| role  | int(11) | YES |  | NULL |  | 
| field2  | tinyint(1) | NO |  | 1  |  | 
| field3  | tinyint(1) | NO |  | 1  |  | 
| isactive | tinyint(4) | NO |  | 1  |  | 
+------------+------------+------+-----+---------+-------+ 
+0

Sẽ tốt nhất nếu bạn thêm cấu trúc bảng. – e4c5

+0

@ e4c5 đã thêm cấu trúc bảng kế thừa – AmirM

Trả lời

1

Thật không may django không not yet have a composite primary key (phím composite tiểu học còn được gọi là phím đa cột chính)

Có một thư viện của bên thứ ba, gì ngạc nhiên tên django-compositekey rằng làm cho nó có thể tạo ra một mô hình có một khóa chính đa cột. Tuy nhiên dự án đó hiện được duy trì và không tương thích với các phiên bản mới nhất của django.

Đặt cược tốt nhất của bạn, là thêm cột mới vào bảng của bạn, đây là một AutoField và đặt nó làm khóa chính mới. Các trường tạo nên khóa chính hiện tại có thể được đánh dấu là unique_together. Mặc dù điều này có thể không lý tưởng cho một vài truy vấn. Nó đủ tốt cho hầu hết mọi người.

Nếu bạn cập nhật câu hỏi của mình với cấu trúc bảng hiện tại (như được hiển thị trong bảng điều khiển sql), tôi sẽ cập nhật câu trả lời của mình để hiển thị mô hình trông như thế nào.

Cập nhật Có nhiều cách khác nhau để bạn có thể thả khóa chính cũ và thay thế bằng khóa chính tăng tự động mới. Đây là cách dễ nhất, nó chỉ liên quan đến SQL

CREATE TABLE newtable LIKE mytable; 
ALTER TABLE newtable DROP PRIMARY KEY; 
ALTER TABLE newtable ADD `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY; 
RENAME TABLE mytable to mytable_old; 
RENAME TABLE newtable to mytable; 
INSERT INTO mytable(userid,field1id, rest of the fields) 
    SELECT * FROM mytable_old; 

Sau đó, chỉnh sửa mô hình của bạn và xóa primary_key = Cờ thực sự từ các trường đó.

Footnote:
Một số cơ sở dữ liệu như SQLite ví dụ không hỗ trợ LIKE điều khoản trong một CREATE TABLE. Trong những trường hợp này, bạn sẽ phải tìm kiếm câu lệnh tạo bảng cho bảng gốc và sao chép dán sau khi chỉnh sửa tên bảng. Đánh giá cấu trúc bảng của bạn dường như bạn đang sử dụng mysql và nó hỗ trợ mệnh đề LIKE.

+0

Có phải đó là 'SQL thuần túy 'không? Tôi không chắc 'LIKE' trong' CREATE TABLE' là SQL chuẩn, có thể thêm thay đổi vào 'pure MySQL' hay cái gì đó tương tự?(MySQL/MyISAM hỗ trợ LIKE nhưng Firebird không, không chắc chắn về các công cụ khác/RDMBSs) –

+0

@JanSegre bạn nói đúng là nó không được hỗ trợ bởi tất cả các cơ sở dữ liệu. Khi tôi đã viết sql tinh khiết trong câu trả lời trên tôi đã chỉ đơn thuần là suy nghĩ không liên quan đến django nd không phải của tiêu chuẩn ansi. Cập nhật câu trả lời của tôi. – e4c5

0

Bạn phải xóa lệnh managed = False từ mô hình để có thể chỉnh sửa bảng

Các vấn đề liên quan