Souvik Ray
Souvik Ray

Reputation: 3038

How to store an array of users in django?

I have a django model which is basically a group called Contexts.It contains some fields like name, description and a user.Below is the model defined

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

Currently there is only one user per Context.But I want to add more users to the same Context.So now I want to change the users field to an array field.By the way I am using django + postgres.

So this is what I do

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

But then how do I append users to the users field?This is what I do normally to add a context

@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)

But how do I append one user at a time to the users field in the same context (assuming same context name is passed)?

Upvotes: 3

Views: 3074

Answers (2)

Prashant Yengantiwar
Prashant Yengantiwar

Reputation: 156

In this case you can do two ways either use the postgres json field or go with django ManyToManyField as below,

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

# users field like below

users = JSONField()

or

users = models.ManyToManyField(User)

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477684

Usually it is better not to store things as an array. First of all, not all databases have arrays, and furthermore, it usually will only create more trouble to do (efficient) querying, especially if the elements in the array refer to other objects. You usually store many-to-relations in a separate table. Django has support for this: a ManyToManyField [Django-doc].

Furthermore the code probably already has a problem: you store users as a CharField. Now imagine that a user changes their username, then there is no longer a link here. If you want to refer to objects in (another) model, you should use relations, like a ForeignKey, OneToOneField, or ManyToManyField.

So we can probably rewrite it to:

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)

The nice thing is, we no longer need to care about how Django represents this (efficiently), we can simply obtain all the Users of a some_context with some_context.users.all(). Those are then User objects (or other model objects if you later change the user model).

We can then add a User to an objects as follows:

@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)

So we can fetch the user, and add it to the field. If you user_request.get('user') contains the primary key of the user, we can even omit fetching the User object, and use:

@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)

Upvotes: 3

Related Questions