[PYTHON] Django beginners create simple apps 3

Introduction

A continuation of 2 where Django beginners create simple apps. Last time, I created urls.py, views.py, template, and created R of CRUD, that is, Read part. This time I want to create the Create part with Class-based-view.

Series table of contents for beginners to create simple apps

-Django Beginners Create Easy Apps 1 --Preparation-Overview of Django-Creating models.py -Django beginners make simple apps 2 --Implementation of Read part (creation of urls.py, views.py, template file) -Django Beginners Create Easy Apps 3 (← Now here) --Implementation of Create part (creation of form.py etc.) --Django Beginners make simple apps 4 --Comparison of Class-based-view and Function-view --Django Beginners make simple apps 5 (Completed) --Implementation of Update part and Delete part

environment

Ubuntu 20.04 LTS Python 3.8.2 Django 3.02

Premise

The project name is config and the app name is myapp. In other words, the following two commands have been executed

(myenv)$ django-admin startproject config .
(myenv)$ python manage.py startapp myapp

The templates directory is created in the same hierarchy as manage.py, and setting.py has also been modified. (See "Beginners make simple apps 1")

0. Rough design

Actually, I wanted to be able to enter the movie title, director name, viewing date, and impressions all at once on one screen. It turns out that it is not so easy to link with ForeignKey (you can see the inconvenience after actually making this kind of thing ...). Although it can be implemented with an "inline form set", it is a little difficult for beginners, so we adopted a method of registering the director name, the movie, and the impression separately. The image is shown below.

08116AEF-A591-4655-A10C-14065C8E4BB8.jpeg

1. Implementation of Create

Until now, each data was input from the management site of 127.0.0.1:8000/admin/, but I want to create a page for input from the web. That is the Create part. The order of making is as follows.

  1. Create forms.py
  2. Determine the address in urls.py
  3. Write how to enter the director's name and movie information in views.py
  4. Create an HTML file for the page you want to enter

This form is the entrance to input to the database called model. Rather, it seems to be an interface that connects model and HTML forms. When I started playing with Django, I had no idea what I was doing because I thought Django's Form and HTML forms were the same thing. ** Form and form are different. ** I've always wondered why there is a form, but ** the washed clothes (data) can't be put into the chest of drawers (model) without permission. I need someone who can fold it up properly, and that's form + view ** and self-solve.

E635ADCB-33A0-4A9A-9BFA-C7593213C02E.jpeg

Write the Form in the middle of the above figure in form.py.

form.py code

myapp/form.py


from django.forms import ModelForm
from myapp.models import Movie, Director, Log

class DirectorForm(ModelForm):
    class Meta:
        model = Director
        fields = ('name',)

class MovieForm(ModelForm):
    class Meta:
        model = Movie
        fields = ('title','watch_date', 'director')

class LogForm(ModelForm):
    class Meta:
        model = Log
        fields = ('movie','text')

Since there are 3 Models, 3 Forms are also described. There are two types of Form classes, forms.Form and forms.ModelForm, and ModelForm is easier. Since form is the entrance to the input data, it is directly connected to model. Just describe what the model (database) uses and which field (item) to use under the class Meta. Next, write the address of the input page in urls.py.

Code in urls.py

myapp/urls.py


from django.urls import path, include
from myapp import views

app_name = 'myapp'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('movie/<int:pk>/', views.MovieDetailView.as_view(), name='movie_detail'),
    path('register/director/', views.RegisterDirectorView.as_view(), name='registerdirector'), #Add this
    path('register/movie/', views.RegisterMovieView.as_view(), name='registermovie'), #Add this
    path('writing/log/', views.WritingLogView.as_view(), name='writinglog'), #Add this
]

Then create a Class-based-view (here RegisterDirectorView, RegisterMovieView and WritingLogView) as specified in urls.py.

Views.py code

First, View for registering the director name.

myapp/views.py



class RegisterDirectorView(generic.CreateView):
    model = Director
    form_class = DirectorForm
    template_name = 'myapp/register.html'
    def get_success_url(self):
        return reverse('myapp:registermovie') 

Next, View to register movie information.

myapp/views.py



class RegisterMovieView(generic.CreateView):
    model = Movie
    form_class = MovieForm
    template_name = 'myapp/register.html'
    def get_success_url(self):
        return reverse('myapp:movie_detail', kwargs={'pk': self.object.pk }) 

Finally, View to write the impression of the movie.

myapp/views.py


class WritingLogView(generic.CreateView):
    model = Log
    form_class = LogForm
    template_name = 'myapp/register.html'
    def get_success_url(self):
        return reverse('myapp:movie_detail', kwargs={'pk': self.object.movie.pk }) 

The following four items are common to the above three CreateViews.

  1. What is the database that stores the input data (model = part)
  2. What form to use (form_class = part)
  3. What is the HTML file that displays the input screen (template_name = part)
  4. If the data input and storage in the database are successful, which page should be displayed (def get_success_url part)

If you decide on these 4 items, CreateView will automatically do various things for you.

Explain the last line of the three views

  1. return reverse('myapp:registermovie')

RegisterDirectorView. The reverse function means to jump to the address written in (). This time myapp: registermovie corresponds to the last part ofpath ('register / movie /', views.RegisterMovieView.as_view (), name ='registermovie'),described in urls.py. In other words, go to 127.0.0.1:8000/myapp/register/movie/.

  1. return reverse('myapp:movie_detail', kwargs={'pk': self.object.pk })

RegisterMovieView. kwargs = {'pk': self.object.pk} is a keyword argument and is a dictionary type. In my understanding ... The input data is instantiated into an object (instance). That is self.object. The thing automatically has a pk (primary key: an id number that can be assigned arbitrarily), and that pk (self.object.pk) is linked to the pk (key part of the dictionary) of movie_detail. Will be done. Use it to go to the movie_detail page. In other words, if the pk of the object "Sonatine: Takeshi Kitano: 2020-05-01" is 1, it means to fly to 127.0.0.1:8000/myapp/movie/1/.

  1. return reverse('myapp:movie_detail', kwargs={'pk': self.object.movie.pk })

WritingLogView. Keyword argument part. Earlier it was self.object.pk and this time it is self.object.movie.pk. why. RegisterMovieView's self.object was a movie object, but WritingLogView's self.object is an impression object. It becomes self.object.movie.pk to pull the pk of the movie associated with the impression. By the way, this movie part means the movie described inclass Log (models.Model)of models.py.

Create an HTML file

Create retister.html described in the previous code (template_name = part). Create a register.html file in the templates directory and the myapp directory under it, and write the following code.

templates/myapp/register.html


<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">save</button>
</form>

This is the HTML form. Write {% csrf_token%} because it is not a magical requirement for security. The following {{form.as_p}} will automatically create and display the contents of the form. It is said that one code is required for three forms: director name input, movie information input, and impression input. It's amazing. It's really smart.

Display result of register.html

Enter http://127.0.0.1:8000/myapp/register/director/ directly in the browser to go to the" Director name input screen ". If it is http://127.0.0.1:8000/myapp/register/movie/, go to the "movie information input screen". If it is http://127.0.0.1:8000/myapp/writing/log/, it will jump to the "impression input screen". The director field of the "movie information input screen" and the title field of the "impression input screen" are drop-down selection formulas (because they are linked by Foreign Key).

Director name input screen Movie information input screen Impression input screen
Screenshot from 2020-05-20 20-09-30.png Screenshotfrom2020-05-2020-08-22.png Screenshotfrom2020-05-2020-39-27.png

With the above, the Create part has been implemented.

Afterword

Now that we've reached half of CRUD, the rest are UPDATE and DELETE. But next time, I'll take a short detour and rewrite the code I've written in Class-based-view with Function-view, and compare both to see how Django works. If you have any mistakes, please point out and give us guidance.

Recommended Posts

Django beginners create simple apps 3
Django beginners create simple apps 1
Django beginners create simple apps 2
Django beginners create simple apps 5
Django beginners make simple apps 4
Create initial settings and staff apps in Django
Create a Django schedule
django oscar simple tutorial
Create Django Todo list
Create an API with Django
Create a (simple) REST server
Create ToDo List [Python Django]
Create a homepage with django
Shell to create django project
Create a Django login screen
Create your own Django middleware
Create a simple textlint server
Create and list Django models
(For beginners) Try creating a simple web API with Django
Hello World (beginners) on Django
Create a social integration API for smartphone apps with Django
Rails users try to create a simple blog engine with Django
Steps to create a Django project
Django beginners tried building an environment
[For beginners] Django -Development environment construction-
Create new application use python, django
[Django] Create your own 403, 404, 500 error pages
Create a file uploader with Django
Create a LINE Bot in Django