Monday, January 6, 2020

Python 3.7.5 : Post class and migration process.

Today I will solve some issues with the Django framework like:
  • create a new class for posts;
  • explain how the migration process works.
  • use the database with Django shell;
Let's activate the environment:
[mythcat@desk django]$ source env/bin/activate
I used my old project django-chart, see my old tutorials.
Let's add some source code to the models.py to create a class for the post into my website:
...
# Post data 
from django.utils import timezone
from django.contrib.auth.models import User
...
#create a post
class Post(models.Model):
  title = models.CharField(max_length = 100)
  content = models.TextField()
  date_posted = models.DateTimeField(default = timezone.now)
  #if the user is deleted their posts is deleted 
  author = models.ForeignKey(User, on_delete = models.CASCADE)
Let's use the migration process to update the database:
(env) [mythcat@desk django]$ cd mysite/
(env) [mythcat@desk mysite]$ python3 manage.py makemigrations
Migrations for 'test001':
  test001/migrations/0003_post.py
  - Create model Post
Before to run the migrate command I will show what happened with this migration output from SQL view.
This is great to solve issues and see the exact SQL code generated.
I have in the output of command makemigrations the application name test001 and the migration number 0003.
I will use all of this information output to show how you can see the SQL code:
(env) [mythcat@desk mysite]$ python3 manage.py sqlmigrate test001 0003
BEGIN;
--
-- Create model Post
--
CREATE TABLE "test001_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
"title" varchar(100) NOT NULL, "content" text NOT NULL, "date_posted" datetime NOT NULL, 
"author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "test001_post_author_id_fed29ee6" ON "test001_post" ("author_id");
COMMIT;
This print SQL code that it's going to run when I will use the next command:
(env) [mythcat@desk mysite]$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, test001
Running migrations:
  Applying test001.0003_post... OK
The migration process solves issues linked to changes in the database.
Let's use the Django shell to see the User changes into the database:
(env) [mythcat@desk mysite]$ python3 manage.py shell
Python 3.7.5 (default, Dec 15 2019, 17:54:26) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from test001.models import Post
>>> from django.contrib.auth.models import User
>>> User.objects.all()
...
>>> User.objects.first()
...
>>> User.objects.filter(username='catalin')
...
>>> User.objects.filter(username='catalin').first()
...
>>> user = User.objects.filter(username='catalin').first()
>>> user
...
>>> user.id
1
>>> user.pk
1
>>> Post.objects.all()
...
Let's add a post to the database and show it:
>>> post_1=Post(title='First title', content='The first content!',author=user)
>>> post_1.save()
>>> Post.objects.all()
...
I can see the posts and information about the user with the Django shell.
>>> post = Post.objects.first()
>>> post.content
'The first content!'
>>> post.date_posted
...
>>> post.author
...
>>> post.author.email
...
>>> user.post_set.all()
...
You need to add to views.py the new model changes:
...
from .models import Post
...
def posts(request):
  context = {
  'posts':Post.objects.all()
  }
  return render(request, 'test001/posts.html', context)
...
Into the templates folder, I created the file named posts.html to load the data to HTML5.
{% extends 'base.html' %}
{% block content %}
  {% for post in posts %}
  <article>
  <div>{{ post.title }}</div>
  <div>{{ post.content }}</div>
  <div>{{ post.author }}</div>
  <div>{{ post.date_posted|date:"F d, Y" }}</div>
  </article>
  {% endfor %}
{% endblock content %}
To see these changes into the website I add the route to this HTML5 file posts.html into urls.py file:
app_name = 'test001'
urlpatterns = [
...
    path('posts/',posts, name = 'posts'),
...
]
Now I can run the server and see the output from the database into posts URL.
(env) [mythcat@desk mysite]$ python3 manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 06, 2020 - 17:52:29
Django version 3.0.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
...
This is the output of my running server...