【问题标题】:How to store an array of users in django?如何在 django 中存储一组用户?
【发布时间】:2018-08-17 10:17:33
【问题描述】:

我有一个 django 模型,它基本上是一个名为 Contexts 的组。它包含一些字段,如 namedescription 和一个用户。下面是定义的模型

class Contexts(models.Model):
    context_name = models.CharField(max_length=50)
    context_description = models.TextField()
    users = models.CharField(max_length=255, null=False)

目前每个Context只有一个用户。但是我想将更多用户添加到同一个Context。所以现在我想将users字段更改为数组字段。顺便说一下我使用django + postgres。

这就是我的工作

class Contexts(models.Model):
    context_name = models.CharField(max_length=50)
    context_description = models.TextField()
    users = ArrayField(ArrayField(models.TextField()))

但是我如何将用户附加到users 字段?这是我通常会做的添加上下文

@csrf_exempt
def context_operation(request):
    user_request = json.loads(request.body.decode('utf-8'))
    if request.method == "POST":
        try:
            if user_request.get("action") == "add":
                print("add")
                conv = Contexts.objects.create(
                    context_name=user_request.get("context_name"),
                    context_description=user_request.get("context_description"),
                    users=user_request.get("user")
                )

        except Exception as e:
            print("Context saving exception", e)
            return HttpResponse(0)
        return HttpResponse(1)

但是我如何一次将一个用户附加到同一上下文中的users 字段(假设传递了相同的上下文名称)?

【问题讨论】:

  • 通常最好将事物存储为数组。首先,并不是所有的数据库都数组,而且,做(高效的)查询通常只会带来更多的麻烦。您通常将多对关系存储在单独的表中。 Django 对此有支持:ManyToManyField.

标签: python django


【解决方案1】:

通常最好将事物存储为数组。首先,并不是所有的数据库都有数组,而且,做(高效的)查询通常只会造成更多的麻烦,特别是如果数组中的元素引用其他物体。您通常将多对关系存储在单独的表中。 Django 对此提供支持:ManyToManyField [Django-doc]

此外,代码可能已经一个问题:您将users 存储为CharField。现在假设用户更改了他们的用户名,那么这里就不再有链接了。如果您想引用(另一个)模型中的对象,您应该使用关系,例如 ForeignKeyOneToOneFieldManyToManyField

所以我们大概可以改写成:

from django.db import models
from django.conf import settings

class Contexts(models.Model):
    context_name = models.CharField(max_length=50)
    context_description = models.TextField()
    users = ManyToManyField(settings.AUTH_USER_MODEL)

好消息是,我们不再需要关心 Django 如何(有效地)表示它,我们可以简单地用some_context.users.all() 获得some_context 的所有Users。这些是 User 对象(或其他模型对象,如果您稍后更改用户模型)。

然后我们可以向对象添加User,如下所示:

@csrf_exempt
def context_operation(request):
    user_request = json.loads(request.body.decode('utf-8'))
    if request.method == "POST":
        try:
            if user_request.get("action") == "add":
                print("add")
                conv = Contexts.objects.create(
                    context_name=user_request.get("context_name"),
                    context_description=user_request.get("context_description"),
                )
                my_user = User.objects.get(username=user_request.get("user"))
                conv.users.add(my_user)

        except Exception as e:
            print("Context saving exception", e)
            return HttpResponse(0)
        return HttpResponse(1)

所以我们可以获取用户,并将其添加到字段中。如果user_request.get('user') 包含用户的主键,我们甚至可以省略获取User 对象,并使用:

@csrf_exempt
def context_operation(request):
    user_request = json.loads(request.body.decode('utf-8'))
    if request.method == "POST":
        try:
            if user_request.get("action") == "add":
                print("add")
                conv = Contexts.objects.create(
                    context_name=user_request.get("context_name"),
                    context_description=user_request.get("context_description"),
                )
                # if user_request.get('user') contains the *primary* key of the User model
                conv.users.add(user_request.get("user"))

        except Exception as e:
            print("Context saving exception", e)
            return HttpResponse(0)
        return HttpResponse(1)

【讨论】:

  • 嘿,这很棒。但问题是由于某种原因我无法在服务器中运行 django 迁移。所以除了 django 模型之外,我还在使用 postgres。但我很难定义与 postgres 表相同的 Contexts 模型。我在 stackoverflow stackoverflow.com/questions/51810439/… 中提出了类似的问题,但还没有取得任何成功。如果你能在这个问题上给出一些指示,那就太好了。 (支持你的答案)
  • 顺便说一下我用过django的用户模型。
  • "我无法在服务器中运行 django 迁移" => 那么这是您应该解决的真正问题,而不是使用非标准的非正常“功能”。如果您无法在生产服务器上运行迁移的原因是数据库管理员禁止它,那么您想与他联系以讨论问题并了解如何进行所需的架构更改。我从来没有遇到过更喜欢非规范化数据而不是干净的架构更改的数据库管理员,特别是当架构更改只需要添加一个 m2m 表时,这实际上是没有成本的。
  • @SouvikRay:我认为首先尝试(有效地)解决迁移问题比尝试使用不同的列类型“规避”问题要好。当然它现在可能会起作用,但是如果不解决“核心问题”,它会在以后引起很多问题。
【解决方案2】:

在这种情况下,您可以通过两种方式使用 postgres json 字段或使用 django ManyToManyField,如下所示,

from django.db import models
from django.contrib.postgres.fields import JSONField

# users field like below

users = JSONField()

or

users = models.ManyToManyField(User)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-15
    • 2019-06-06
    • 2013-02-06
    • 1970-01-01
    • 2011-10-14
    • 2017-10-18
    • 2020-12-01
    • 2021-05-22
    相关资源
    最近更新 更多