Проблема с дизайном Django- моделей

#python #sql #django #database

#python #sql #django #База данных

Вопрос:

Я изо всех сил пытаюсь разработать свои модели на Django (используя PostgreSQL).

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

Пользователь владеет объектами. Затем он может сортировать их по группам. Но ему не нужно этого делать.

Я создал группу пользовательских элементов ( UserItemGroup ), которые принадлежат пользователю ( User ). Затем я создал модель элемента ( UserItem ). Эта модель представляет элемент, который пользователь может разбить на группы. Элементы могут принадлежать нескольким группам одновременно, но должны быть уникальными! Я использовал 2 ForeignKey в UserItem модели, но это кажется очень странным… Смотрите ниже:

 class UserItemGroup(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    name = models.CharField(max_length=200, blank=False, null=False)
    slug = models.CharField(max_length=200, blank=False, null=False)

class UserItem(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    group = models.ForeignKey(UserItemGroup, on_delete=models.CASCADE)
 

Элементы могут быть расположены следующим образом:

 user_x
------group_a
------------item_1
------------item_2
------------item_3
------group_b
------------item_1
------------item_4
 

Надеюсь, я понял, заранее спасибо за помощь.

Ответ №1:

Поэтому я думаю, что этот дизайн должен быть лучше :

 class ItemGroup(models.Model):
    # Add next line only if you want to restrict Groups to user (if they are not shared)
    # user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    slug = models.CharField(max_length=200)

class UserItem(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    groups = models.ManyToManyField(UserItemGroup, blank=True)
    name = models.CharField(max_length=200, unique=True)

    def __str__(self):
        return self.name
 

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

 # Get all possible groups from the user items
for group in ItemGroup.objects.filter(useritem__user=user).distinct():
    print(group.name)
    # Display all user items from this group
    print(user.useritem_set.filter(groups=group))
# Print items that are not in a group
print(user.useritem_set.filter(groups=None))
 

Комментарии:

1. Как вы определяете свой useritem_set?

2. Я просто догадываюсь об этом, потому что, если модель UserItem имеет ForeignKey значение для пользователя (без определения a related_name ), тогда у пользователя должен быть атрибут useritem_set (см. docs.djangoproject.com/en/stable/topics/db/queries /… )

Ответ №2:

Я думаю, вам не нужен user внешний ключ в вашем UserItem , поскольку элемент является частью группы, а группа зависит от пользователя.

Кроме того, вы сказали, что элемент может принадлежать нескольким группам, поэтому отношение должно быть ManyToManyField :

 class UserItem(models.Model):
    group = models.ManyToManyField(UserItemGroup, blank=True)
    name = models.CharField(max_length=200, unique=True)
 

Я добавил name поле и установил его как уникальное, чтобы обеспечить уникальность элемента.
Вы можете удалить the blank=True из ManyToManyField , если элемент должен быть частью группы.

Если вы хотите получить все элементы от пользователя, вы можете сделать :

 UserItem.objects.filter(group__user=user).distinct()
 

Или сортируется по группе :

 for group in user.useritemgroup_set.all():
    print(group.name)
    print(group.useritem_set.all())
 

Комментарии:

1. Я не проголосовал против этого. Хотя, это немного неудобно, потому что мне нужно запрашивать группы и элементы групп, чтобы получить все элементы, которые принадлежат пользователю, верно? Это также вернет мне дубликаты элементов, потому что они могут быть в нескольких группах.

2. Вы можете использовать .distinct() в своем запросе для устранения дубликатов, это правильное моделирование базы данных

3. Для меня элементы должны быть основным, о чем нужно думать. Затем мы думаем о сортировке элементов по группам, вы понимаете, что я имею в виду?

4. Я не хочу, чтобы элементы были в группах, я хочу, чтобы они были отсортированы по группам. В то время как группы — это таблицы, которые тоже содержат данные.

5. Я отредактировал свой ответ, чтобы показать вам, как вы можете запрашивать объекты с помощью этого дизайна, который кажется наиболее подходящим для вашего варианта использования.