Django uses an Object-Relational-Mapper (ORM) to map model definitions in the Django code to the data structure used by the underlying database. As we change our model definitions, Django tracks the changes and can create database migration scripts (in /yourproject/yourapps/migrations/) to automatically migrate the underlying data structure in the database to match the model.

Makemigrations & Migrate

When we created the website Django automatically added a number of models for use by the admin section of the site (which we’ll look at later). Run the following commands to define tables for those models in the database (make sure you are in the directory that contains manage.py):

Some of these applications make use of at least one database table, though, so we need to create the tables in the database before we can use them. To do that, run the following command:

1
2
$python manage.py makemigrations
$python manage.py migrate

Important:

You’ll need to run the above commands every time your models change in a way that will affect the structure of the data that needs to be stored (including both addition and removal of whole models and individual fields).

The makemigrations command creates (but does not apply) the migrations for all applications installed in your project (you can specify the application name as well to just run a migration for a single project). This gives you a chance to checkout the code for these migrations before they are applied — when you’re a Django expert you may choose to tweak them slightly!

The migrate command actually applies the migrations to your database (Django tracks which ones have been added to the current database).

You can see from your yourapps/migrations/0001_initial.pythat would be like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
...
('rating_status', models.CharField(choices=[('n', 'Not interested'), ('a', 'Add to Watchlist'), ('h', 'Have Watched'), ('w', 'Waiting / Watching')], default='n', max_length=1)),
('rating_comment', models.CharField(blank=True, max_length=250)),
('movie', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='movie.movie')),
],
options={
'ordering': ['-rating_time'],
},
),
]

Let’s run another command to print the sql grammar like code, the sqlmigrate command takes migration names and returns their SQL (0001_initial.py):

1
python manage.py sqlmigrate movie 0001

You should see something similar to the following (we’ve reformatted it for readability)::

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
BEGIN;
--
-- Create model Director
--
...
--
-- Create model Rating
--
CREATE TABLE "movie_rating" (
"id" char(32) NOT NULL PRIMARY KEY,
"rating_movie" integer NOT NULL,
"votes" integer NOT NULL,
"rating_time" datetime NOT NULL,
"rating_status" varchar(1) NOT NULL,
"rating_comment" varchar(250) NOT NULL,
"movie_id" integer NULL REFERENCES "movie_movie" ("id") DEFERRABLE INITIALLY DEFERRED
);
CREATE INDEX "movie_movie_director_id_0c15103f" ON "movie_movie" ("director_id");
CREATE UNIQUE INDEX "movie_movie_genre_movie_id_genre_id_71670816_uniq" ON "movie_movie_genre" ("movie_id", "genre_id");
CREATE INDEX "movie_movie_genre_movie_id_eb49a2f5" ON "movie_movie_genre" ("movie_id");
CREATE INDEX "movie_movie_genre_genre_id_42d26c87" ON "movie_movie_genre" ("genre_id");
CREATE INDEX "movie_rating_movie_id_4dfd52d9" ON "movie_rating" ("movie_id");
COMMIT;

Note the following:

  • The exact output will vary depending on the database you are using. The example above is generated for SQLite.
  • Table names are automatically generated by combining the name of the app and the lowercase name of the model. (You can override this.)
  • Primary keys (IDs) are added automatically. (You can override this, too.)
  • By convention, Django appends "_id" to the foreign key field name. (Yes, you can override this, as well.)
  • The foreign key relationship is made explicit by a FOREIGN KEY constraint. Don’t worry about the DEFERRABLE parts; that’s just telling SQLite to not enforce the foreign key until the end of the transaction.
  • It’s tailored to the database you’re using, so database-specific field types such as auto_increment (MySQL), serial (PostgreSQL), or integer primary key autoincrement (SQLite) are handled for you automatically.

If you’re interested, you can also run python manage.py check; this checks for any problems in your project without making migrations or touching the database.

1
System check identified no issues (0 silenced).

Now that we’ve updated our models, we’ll need to make fresh migrations on the project and then apply those migrations:

1
2
python manage.py makemigrations
python manage.py migrate

Playing with the API

Now, let’s hop into the interactive Python shell and play around with the free API Django gives you. To invoke the Python shell, use this command:

1
$ python manage.py shell

You can search for records that match a certain criteria using the model’s objects attribute (provided by the base class).

We can get all records for a model as a QuerySet, using objects.all(). The QuerySet is an iterable object, meaning that it contains a number of objects that we can iterate/loop through.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## Import the model classes we just wrote.
from movie.models import Movie, Director, Rating

all_movies = Movie.objects.all()
all_movies_10 = Movie.objects.all()[:10]

all_movies
# <QuerySet [<Movie: Aquaman>, <Movie: Inception>, ..., <Movie: Rebecca>]>
all_movies.count()
# 31

## print all movie titles
for e in Movie.objects.all():
print(e.movie_title)

## order
all_movies.order_by('movie_title')

Django’s filter() method allows us to filter the returned QuerySet to match a specified text or numeric field against a particular criteria. For example, to filter for directors that contain “hitchcock” in his/her name filter for movie directors that contain “hitchcock” in his/her name or and then count them, we could do the following.

1
2
3
4
5
6
7
8
Director.objects.filter(director_name__contains='hitchcock').count()
# 1

## Use double underscores to separate relationships.
Movie.objects.filter(director__director_name__contains='hitchcock',director__director_name_CN__contains='希区柯克').count()
##==
Movie.objects.filter(director__director_name__contains='hitchcock').filter(director__director_name_CN__contains='希区柯克').exclude(director__director_name__startswith='James').count()
# 10

The fields to match and the type of match are defined in the filter parameter name, using the format: field_name__match_type (note the double underscore between title and contains above). Above we’re filtering title with a case-sensitive match. There are many other types of matches you can do: icontains (case insensitive), iexact (case-insensitive exact match), exact (case-sensitive exact match) and in, gt (greater than), startswith, etc.

Django provides a rich database lookup API that’s entirely driven by keyword arguments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Movie.objects.filter(movie_title__startswith='Saw')
# <QuerySet [<Movie: Saw II(2005-10-28)>, <Movie: Saw(2004-01-19)>]>

Movie.objects.filter(id=1)
# <QuerySet [<Movie: Inception(2010-07-16)>]>

## Request an ID that doesn't exist, this will raise an exception.
Movie.objects.get(id=2020)
Traceback (most recent call last):
...
DoesNotExist: Movie matching query does not exist.

## Lookup by a primary key is the most common case, so Django provides a
## shortcut for primary-key exact lookups.
## The following is identical to Movie.objects.get(id=1).
Movie.objects.get(pk=1)
# <Movie: Inception(2010-07-16)>

We can also create a new Movie.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.utils import timezone
import datetime
timezone.now()
# datetime.datetime(2018, 12, 3, 14, 24, 44, 318870, tzinfo=<UTC>)
m = Movie(movie_title="Strangers on a Train",movie_title_CN="火车怪客",movie_country ="美国",movie_release_date=datetime.date(1951, 6, 30))
## Save the object into the database. You have to call save() explicitly.
m.save()
## Now it has an ID.
m.id
# 10

## Access model field values via Python attributes.
m.movie_release_date
# datetime.date(1951, 6, 30)

## Change values by changing the attributes, then calling save().
m.movie_title = "Spellbound"
m.save()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
m2 = Movie.objects.get(pk=10)

## Display any movie url from the related object set -- none so far.
m2.movieURL_set.all()
<QuerySet []>

## Create movie url.
m2.movieURL_set.create(movie_url_anno='Bilibili', movie_url="https://www.bilibili.com/bangumi/play/ss29019")
m2.movieURL_set.create(movie_url_anno='iqiyi', movie_url="https://www.iqiyi.com/v_19rrho68iw.html")
movie_url = m2.movieURL_set.create(movie_url_anno='Tecent', movie_url="https://v.qq.com/x/cover/2tzm7pjuff47voq.html")

## Movie URL objects have API access to their related Movie objects.
movie_url.movie
# : <Movie: Strangers on a Train(1951-06-30)>

## And vice versa: Movie objects get access to movie_url objects.
m2.movieURL_set.count()
3

## Let's delete one of the movie urls. Use delete() for that.
movie_url.delete()
#(1, {'movie.movieURL': 1})

We’re using this instead of simply typing “python”, because manage.py sets the DJANGO_SETTINGS_MODULE environment variable, which gives Django the Python import path to your movies/settings.py file.

It’s important to add __str__()methods to your models, not only for your own convenience when dealing with the interactive prompt, but also because objects’ representations are used throughout Django’s automatically-generated admin.

Note these are normal Python methods. Let’s add a custom method, just for demonstration:

ratings/models.py

1
2
3
4
5
6
7
8
9
10
import datetime

from django.db import models
from django.utils import timezone

class Movie(models.Model):
# ...
# Methods
def release_date(self, n):
return self.movie_release_date <= timezone.now().date() + datetime.timedelta(days=n)

Note the addition of import datetime and from django.utils import timezone, to reference Python’s standard datetimemodule and Django’s time-zone-related utilities in django.utils.timezone, respectively. If you aren’t familiar with time zone handling in Python, you can learn more in the time zone support docs.

Save these changes and start a new Python interactive shell by running python manage.py shell again:

1
2
3
4
5
6
7
# Get the question that was published this year.
from django.utils import timezone
current_year = timezone.now().year
m = Movie.objects.get(movie_release_date__year=2022)
# <Movie: Avatar: The Way of Water(2022-12-16)>
m.release_date(720)
# False

we can also this API to create users here:

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.contrib.auth.models import User
user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# At this point, user is a User object that has already been saved
# to the database. You can continue to change its attributes
# if you want to change other fields.
user.last_name = 'Lennon'
user.save()

# Changing passwords
u = User.objects.get(username='john')
u.set_password('new password')
u.save()

MYSQL Database

Because we are using SQLite, we don’t need to do any further setup above. Let’s move on to set up using mysql!

Coz django is one of the best known web frameworks for Python, and the good news is that it works out of the box with MySQL Server 8.

1
2
3
4
5
6
mysqld.exe -install

net start mysql

mysql -u root -p

If you encounter the error likeMySQL 服务无法启动。服务没有报告任何错误。 on your computer.

You cam try:

1
2
3
4
5
6
7
mysqld -remove MySQL

mysqld --initialize-insecure

mysqld -install

net start mysql

Then ,using Navicat for MYSQL,it connected!

navicat for sql

If you want to create a user, it will more complicated then MYSQL5.7,

1
2
3
4
create user 'flur'@'%' identified by 'florence';
grant all privileges on *.* to 'flur'@'%' with grant option;
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'crossingfish';
FLUSH PRIVILEGES;

Create a database names blossom,

blossom

Open reverie/setting.py, change the database settings:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DATABASES = {
'default': {
'NAME': 'blossom',
'ENGINE': 'django.db.backends.mysql',
'USER': 'root',
'PASSWORD': 'crossingfish',
'HOST':'127.0.0.1',
'PORT':'3306',
'OPTIONS': {
'autocommit': True,
},
}
}

Next, install mysqlclient,

1
conda install mysqlclient

Postgresql Database

REFERENES

For More Reference,See