Хранение нескольких значений в одном поле в базе данных MySQL, которые сохраняют порядок в Django - PullRequest
0 голосов
/ 25 января 2019

Я пытался создать систему Tutorial, которую мы обычно видим на веб-сайтах. Как те, которые мы нажимаем next -> next -> previous и т.д., чтобы прочитать.

Все сообщения хранятся в таблице (модель) с именем Post. В основном как пул почтовых объектов.

Post.objects.all() вернет все сообщения.

Теперь есть еще один стол (модель) Tutorial Это будет хранить следующее,

class Tutorial(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    tutorial_heading = models.CharField(max_length=100)
    tutorial_summary = models.CharField(max_length=300)

    series = models.CharField(max_length=40) # <---- Here [10,11,12] 
    ...

Здесь записи в этом series поле - это post_ids, хранящиеся в виде строкового представления списка.

пример: серия будет иметь [10,11,12], где 10, 11 и 12 - это post_id, которые соответствуют их соответствующим записям в таблице Post.

Итак, моя запись в таблице для Tutorial модели выглядит следующим образом.

id       heading                   summary                      series

"5"     "Series 3 Tutorial"    "lorem on ullt consequat."    "[12, 13, 14]"

Поэтому я просто прочитал поле series и получил все сообщения с ids в этом списке, а затем отобразил их, используя pagination в Django.

Теперь , я прочитал из нескольких сообщений stackoverflow, что иметь несколько записей в одном поле - плохая идея. И иметь эту связь, чтобы охватить несколько таблиц в качестве отображения, является лучшим вариантом.

То, что я хочу, это возможность вставлять новые посты в эту серию где угодно. Может быть спереди или посередине. Это может быть легко достигнуто, рассматривая эту серию как список и вставляя, как мне угодно. Изменение "[14,12,13]" изменит порядок отображаемых сообщений.

У меня вопрос: можно ли использовать этот способ хранения нескольких значений в поле для моего варианта использования? Или это займет хит производительности или вообще плохая идея. Если нет, то есть ли способ сохранить или изменить порядок, охватив отношения с помощью другой таблицы, или есть совершенно лучший способ сделать это в Django или MYSQL.

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Я могу думать о двух подходах:

Первый подход: связанный список

Один из способов использования связанного списка такой:

class Tutorial(models.Model):
    ...
    previous = models.OneToOneField('self', null=True, blank=True, related_name="next")

В этом подходе выВы можете получить доступ к предыдущему посту серии следующим образом:

for tutorial in Tutorial.objects.filter(previous__isnull=True):
   print(tutorial)
   while(tutorial.next_post):
      print(tutorial.next)
      tutorial = tutorial.next

Это довольно сложный подход, например, когда вы хотите добавить новый учебник в середине связанного списка, вам нужно изменитьдва места.Например:

post = Tutorial.object.first()
next_post = post.next
new = Tutorial.objects.create(...)
post.next=new
post.save()
new.next = next_post
new.save()

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

Второй подход: создание новой модели

Вы можетепросто создайте новую модель и FK to Tutorial, например:

class Series(models.Model):
    name = models.CharField(max_length=255)


class Tutorial(models.Model):
   ..
   series = models.ForeignKey(Series, null=True, blank=True, related_name='tutorials')
   order = models.IntegerField(default=0)


   class Meta:
      unique_together=('series', 'order')  # it will make sure that duplicate order for same series does not happen

Затем вы можете получить доступ к учебникам последовательно:

series = Series.object.first()
series.tutorials.all().order_by('tutorials__order')

Преимущество этого подхода в том, что он гораздо более гибкийдоступ к учебным пособиям по сериям, но для этого будет создана дополнительная таблица, а также одно дополнительное поле для поддержания порядка.

0 голосов
/ 25 января 2019

Здесь записи в этом поле серии - это post_ids, хранящиеся в виде строкового представления списка. (...) Поэтому я просто читаю поле серии и получаю все сообщения с идентификаторами в этом списке, а затем отображаю их, используя нумерацию страниц в Django.

НЕ ДЕЛАЙТЕ ЭТОГО !!!

Вы работаете с реляционной базой данных. Существует один правильный способ моделирования отношений между сущностями в реляционной базе данных, который заключается в использовании внешних ключей. В вашем случае, в зависимости от того, может ли пост принадлежать только одному учебнику (отношение «один ко многим») или ко многим учебникам одновременно (отношение «многие ко многим»), вы захотите, чтобы вам пришлось опубликовать внешний ключ в учебном пособии или использование промежуточной таблицы post_tutorials с внешними ключами в учебном и учебном материалах.

Ваше решение не позволяет базе данных правильно выполнять свою работу. Он не может применять ограничения целостности (что, если вы удалите сообщение, на которое ссылается учебник?), Не может оптимизировать доступ для чтения (при правильной схеме база данных может извлечь учебник и все свои сообщения в одном запросе), он не может следовать обратным отношениям. (данный пост, доступ к учебному руководству (ям), к которому он принадлежит) и т. д. И для этого требуется внешняя программа (код Python) для взаимодействия с вашими данными, в то время как для правильного моделирования вам просто необходим стандартный SQL.

Наконец, - но это зависит от django - использование правильной схемы лучше работает с функциями администратора и с инфраструктурой отдыха django, если вы собираетесь создать API отдыха.

по отношению к проблеме упорядочения, это давно известная (и решаемая) проблема, вам просто нужно добавить поле "order" (маленького int должно быть достаточно). Есть пара приложений django 3-й части, которые поддерживают эту функцию как для ваших моделей, так и для администратора, так что это почти готово.

Итак, нет абсолютно никаких веских причин для денормализации вашей схемы таким образом, а есть только веские причины использовать правильное реляционное моделирование. FWIW Мне однажды приходилось работать над проектом, основанным на каких-то непонятных (и, возможно, давно умерших) PHP-смсах, у которых была блестящая идея использовать антишаблон «сериализованные списки», и я могу сказать вам, что это была катастрофа по сравнению с производительностью и полный кошмар для поддержания. Так что сделайте себе и миру одолжение: не пытайтесь быть креативными, следуйте хорошо известным и признанным лучшим практикам, и ваша жизнь станет намного счастливее. Мои 2 цента ...

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