Hyperbola
Hyperbola

Reputation: 528

Switching from NoSQL to SQL land in django

I am porting my Mongo-Express app to Postgres-Django. The app includes a simple form for collecting a student's information and the books they have read over the summer.

The express API writes the payload to MongoDB. The payload looks like below:

{
  student_id: 123,
  student_name: 'James Hook',
  books: [
    { book: 'War and Peace', author: 'Leo Tolstoy' },
    { book: 'Harry Potter', author: 'JK Rowling' }
  ]
}

Mongo is a document-based database so I could store the above payload as-is.


Now moving to django-postgres, I have to define models and I can see two options:

A. Just create one model with three fields - student_id (IntegerField), student_name (CharField), and books (ArrayField(JSONField))

B. Go full RDBMS and create two models - student and books. Student and book have many-many relationship.


Give this, I have a few questions:

Q1. If I don't need to index on books, does option A make more sense?

Q2. In option A, should it be just JSONField or ArrayField(JSONField)?

Q3. In option B, how do we write TWO or more books for one student at a time? Do I need an ArrayFiled there? How does the model would look like and does it violate atomicity constraint of a database?

Upvotes: 1

Views: 76

Answers (1)

Daniel
Daniel

Reputation: 3527

If you're going RDS, leverage it.

We can say that one student can read many books, and a book can be read by many students, so we'll use a ManyToManyField. Your models can look something like this:

models.py

class Student(models.Model):

    first_name = models.Charfield(...)
    last_name = models.Charfield(...)


class Books(models.Model):

    title = models.CharField(...)
    students = models.ManyToManyField('Student', ..., related_name='books')

Now with Django, you can do things like:

# get a particular student based on id:
student = Student.ojects.get(id=<the-id>)

# get the queryset of books they read:
read_books = student.books.all()

# get all of the students that read "Dracula":
dracula = Books.objects.get(title='Dracula')
students_that_read_dracula = dracula.students.all()

Upvotes: 1

Related Questions