Система личных сообщений в базе данных - PullRequest
1 голос
/ 08 августа 2009

Я новичок в базах данных и хотел бы знать, как лучше хранить личные сообщения в базе данных (с помощью SQLAlchemy).

Поскольку я не был уверен, я попробовал следующую таблицу для PM

pm_table = Table('personal_message', metadata,
     Column('id', Integer, primary_key=True, autoincrement=True),
     Column('from_id', Integer, ForeignKey('user.id')),
     Column('to_id', Integer, ForeignKey('user.id')),
     Column('message', Text),
     Column('sent_at', DateTime)     
)

и затем это отображается

session.mapper(User, user_table, properties={
     'messages_sent': relation(PM, backref='sender'),
     'messages_received': relation(PM, backref='receiver')
})

Я получаю следующее сообщение об ошибке:

Не удалось определить условие соединения между родительскими / дочерними таблицами для отношения User.messages_sent. Укажите выражение «primaryjoin». Если это отношение «многие ко многим», необходимо также «вторичное соединение».

Из того, что я понимаю до сих пор, это отношение один ко многим, но с двумя внешними ключами одного и того же класса. Это даже правильный подход, или я должен иметь две таблицы, messages_sent и messages_received? Или еще что-то еще? Любые указатели в правильном направлении будут очень благодарны.

EDIT:
Чтобы уточнить, я после хорошего шаблона проектирования базы данных, чтобы решить эту проблему. Если кто-то может помочь с SQLAlchemy, это было бы здорово, но ни в коем случае не обязательно.

но столбец from_id будет идентификатором пользователя отправителя, а to_id будет идентификатором получателя?

Точно.

Ваш пример кода неполон.

Я попытался опустить ненужный код в этом посте, кажется, я пошел далеко. Вот недостающие определения.

class PM(object):

    def __init__(self, from_id, to_id, message):
        self.from_id = from_id
        self.to_id = to_id
        self.message = message
        self.sent_at = datetime.utcnow()

session.mapper(PM, pm_table)



class User(object):

    def __init__(self, username, pwsalt, pwhash, email):
        self.username = username
        self.pwsalt = pwsalt
        self.pwhash = pwhash
        self.email = email
        self.since = datetime.utcnow()
        self.status = 0

user_table = Table('user', metadata,
    Column('id', Integer, primary_key=True, autoincrement=True),
    Column('username', String(20)),
    Column('pwsalt', String(32)),
    Column('pwhash', String(64)),
    Column('email', String(320)),
    Column('since', DateTime),
    Column('status', SmallInteger)
)

Ответы [ 3 ]

3 голосов
/ 10 августа 2009

Я не знаю, принят ли здесь ответ на мой собственный вопрос, но я думаю, что лучше иметь какой-то ответ, а не ни один.

Два внешних ключа к одному и тому же классу не работали, поэтому мне придется запросить в базе данных исходящие сообщения пользователей. Но по крайней мере входящие могут быть доступны через user.inbox. Ниже приведен рабочий код.

class PM(object):

    def __init__(self, sender_id, receiver_id, subject, message):
        self.sender_id = sender_id
        self.receiver_id = receiver_id
        self.subject = subject
        self.message = message
        self.sent_at = datetime.utcnow()
        self.read = False
        self.deleted_sender = False
        self.deleted_receiver = False

    def __repr__(self):
        return '' % (self.from_id, self.to_id)

    def markread(self):
        self.read = True

    def delete(self, deleter_id):
        if deleter_id == self.sender_id:
            self.deleted_sender = True
        else:
            self.deleted_receiver = True

pm_table = Table('personal_message', metadata,
    Column('id', Integer, primary_key=True, autoincrement=True),
    Column('sender_id', Integer),
    Column('receiver_id', Integer, ForeignKey('user.id')),
    Column('subject', Text),
    Column('message', Text),
    Column('read', Boolean),
    Column('deleted_sender', Boolean),
    Column('deleted_receiver', Boolean),
    Column('sent_at', DateTime)     
)


class User(object):

    def __init__(self, username, pwsalt, pwhash, email):
        self.username = username
        self.pwsalt = pwsalt
        self.pwhash = pwhash
        self.email = email
        self.since = datetime.utcnow()
        self.status = 0

    def __repr__(self):
        return '' % (self.id, self.username, userstatus[self.status])

user_table = Table('user', metadata,
    Column('id', Integer, primary_key=True, autoincrement=True),
    Column('username', String(20)),
    Column('pwsalt', String(32)),
    Column('pwhash', String(64)),
    Column('email', String(320)),
    Column('since', DateTime),
    Column('status', SmallInteger)
)

userstatus = {
    0: 'user',
    1: 'vip',
    2: 'moderator',
    3: 'admin'
}


session.mapper(User, user_table, properties={
    'inbox': relation(PM)
})
session.mapper(PM, pm_table)
1 голос
/ 08 августа 2009

Я не знаю, как использовать программу или язык, который вы используете, но я могу дать несколько советов по использованию двух БД против одной.

Вы должны использовать только одну БД для сообщений. Отправленные сообщения будут точно такими же, как и сообщения, полученные в любом случае. Я не понимаю, что вы подразумеваете под двумя внешними ключами (мой английский не очень хорош), но столбец from_id будет идентификатором отправителя, а to_id - идентификатором приемник?

Еще несколько столбцов, которые было бы разумно включить, - это «удаленный» столбец для отправителя и получателя и «прочитанный» столбец для получателя.

0 голосов
/ 09 августа 2009

Ваш пример кода неполон.

Вы опустили любое определение для user_table или User класса.

Также вы опустили определение для класса PM.

Без других определений трудно понять, что не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...