프레임워크/Django

장고 모델

험자 2020. 6. 6. 16:10

Database setup

Setting up the database is done by updating the DATABASES variable in settings.py in the project folder.

# project_folder/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

As shown above, SQLite is the default database for which no additional setup is needed. However, any other databases like PostgreSQL require modification that is not only ENGINE and NAME, but also USER, PASSWORD, AND HOST must be provided.

# project_folder/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'dbname',
        'USER': 'username',
        'PASSWORD': 'password',
        'HOST': '127.0.0.1',
        'PORT': '',
    }
}

After database configuration, try creating tables in database by

# project_folder/
python manage.py migrate

Without any updates in models.py, migrate app looks at the INSTALLED_APPS setting and creates database tables accordingly.

There are a few errors that might potenitally occur when implementing migrate

django.core.exceptions.ImproperlyConfigured: Error loading psycopg2 module: No module named 'psycopg2'

Resolved by

pip install psycopg2

FATAL: password authentication failed for user "username"

The user provided in DATABASE['USER'] of settings.py does not exist or the password given inDATABASE['USER'] is incorrect.

resolved by

username@domain:~$sudo su - postgres
postgres@domain:~$psql
postgres=#CREATE USER username WITH ENCRYPTED PASSWORD 'password';
postgres=#\du
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 username  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 

django.db.utils.OperationalError: FATAL: database "database" does not exist

resolved by

username@domain:~$sudo su - postgres
postgres@domain:~$psql
postgres=# CREATE DATABASE database;
postgres=#\l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 database  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 

Model creation

# app/models.py
from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date_published')


class Choice(models.Model):
    CATEGORIES = ['good', 'bad']
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    category = models.CharField(choices=CATEGORIES, max_length=10)

In models.py, each class represents a database table and it inherits models.Model.

Each field is represented by an instance of a Field class – e.g., CharField for character fields and DateTimeField for datetimes.

The name of each Field instance (e.g. question_text or pub_date) is the field’s name.

Refer to Model Field Reference

Activating models

Once model creation or update in models.py is complete,

first, the app that contains models.py needs to be added to settings.py as below:

# project/project/settings.py
INSTALLED_APPS = [
    'app.apps.PollsConfig', # make sure the class PollsConfig is in app/apps.py
    'django.contrib.admin'
]

and second, two following commands are consecutively to be executed.

# project_folder/
python manage.py makemigrations # to create migrations for those changes
python manage.py migrate # to apply those changes to the database

Field options Link to API reference

  • null: False by default. If set to True, store empty value as NULL in database. Recommended to avoid using null=True on string-based fields such as CharField and TextField because , combined with blank=True (see below), there are two possibilities for an empty entry, either NULL i.e., no data or empty string, which leads to confusion. The Django convention, therefore, is to use empry string, i.e., blank=True. However, it seems to me okay to use null=True when the field entry comes with choices.
  • blank:
  • choices
  • validators