2017-07-01 92 views
1

我正在尋找一種在仍然保持順序的同時在對象之間具有Many-to-many關係的方法。這是一個示例用例,它是一個註冊表。用戶可以註冊許多事件,但我需要知道誰註冊了第一,第二,第三等...Django模型 - 多對多持久訂單

是否有直接的方法來做到這一點?

+3

添加時間戳字段? –

回答

1

你必須做這樣的事的兩種簡單的方法:

  1. 使用時間戳,如已經摩西Koledoye建議。
  2. 使用任何SEQUENCE編號(或SERIAL列)。

舉例來說,假設這些都是你usersevents表:

CREATE TABLE users 
(
    user_id INTEGER /* or SERIAL */ PRIMARY KEY, 
    user_name text 
) ; 

CREATE TABLE events 
(
    event_id INTEGER /* or SERIAL */ PRIMARY KEY, 
    event_name text 
) ; 

你可以以兩種不同的方式定義了許多一對多連接表:

CREATE TABLE users_x_events 
(
    user_id INTEGER REFERENCES users (user_id), 
    event_id INTEGER REFERENCES events (event_id), 
    created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT now(), 
    PRIMARY KEY (user_id, event_id) 
) ; 

CREATE TABLE users_x_events_v2 
(
    user_id INTEGER REFERENCES users (user_id), 
    event_id INTEGER REFERENCES events (event_id), 
    serial_id SERIAL, 
    PRIMARY KEY (user_id, event_id) 
) ; 

我寧願有一個時間戳比一個序列,因爲它提供了一個通常有用的信息。你經常想知道發生的事情(和誰做的)。

如果您想要額外的安全性,可以使用ON BEFORE INSERT OR UPDATE觸發器來防止對created_at(或serial_id)列進行任何更改。

+1

通常沒有理由使用'timestamp'而不是'timestamptz'。它們都是8個字節,而'timestamptz'是「更聰明」。 (例如見Momjian發佈的這篇文章:https://momjian.us/main/blogs/pgblog/2017.html#June_19_2017) – Nick

+0

@Nick:我總是發現這個類型的名字絕對是誤導性的:'WITH時區應該被稱爲'WITH TIME ZONE TRANSLATION',因爲沒有關於時區的信息被存儲。時間僅存儲爲UTC,並且在顯示(或轉換爲文本)時,會根據客戶端的時區(而不是事件發生的時區)進行調整。所以,它實際上應該叫做'UTC TIMESTAMP'或'TIMESTAMP WITH TIME ZONE TRANSLATION'。這可能是我試圖避免這種類型的一個(半意識)原因。 – joanolo

+0

客戶端有時區,並且還有插入的初始值的時區。您可以考慮「帶時區的時間戳」,例如具有關於兩個時區的信息的智能數據類型。無論它如何存儲(它從客戶端隱藏),重要的是邏輯和功能。 – Nick