About | Blog | xapy

Django ManyToMany field со своими именами колонок

Некоторое время назад столкнулся с задачей, близкой к описанной в джанговской доке Integrating with a legacy database. В контексте общей задачи, прикрутить джанго-админку к существующей БД, возник небольшой вопрос, ответ на который в Сети тогда так и не нашёл. Итак, вопрос: имеем табличку с many-to-many маппингом model1 <-> model2. Хочется это описать в терминах привычных для django отношений между моделями. Разумеется, описывалось бы это лучше всего стандартным полем ManyToManyField, если бы не одно “но” — по умолчанию такое поле создаёт таблицу (её название настраиваемо с помощью keyword-argument db_table) с полями, названными соответственно model1_id и model2_id. Так как схема БД задана заранее и не подлежит изменению, а названия полей в нашей таблице, разумеется, с упомянутыми не совпадают, потребовалось слегка нестандартное решение. Т.о. постановка задачи: есть модель Product с полем guid и модель Category с полем id. По умолчанию имеем таблицу с полями product_id, category_id, хотим: guid, manual_classification. И, собственно, простое решение:

class ManyToManyFieldWithCustomColumns(models.ManyToManyField):
    def _get_m2m_column_name(self, related):
        return related.model._meta.pk.db_column
    def _get_m2m_reverse_name(self, related):
        return self.db_column

После этого в модели Product определяем нужное поле в виде:

categories = ManyToManyFieldWithCustomColumns(Category,db_column='manual_classification',              
                                              db_table='product_classification')

Уверен, должно найтись и более элегантное решение, например усовершенствование в сторону имени колонки, обозначающей ключ текущей модели (в моём случае взял db_column от ключа, не меняя). Кто может предложить — велкам в коменты :)

Add post to: Delicious Reddit Slashdot Digg Technorati Google
Comment

Comments

No comments for this post

Comment form for «manytomanywithcustomfield»

Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image