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.
-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
Ubuntu 20.04 LTS Python 3.8.2 Django 3.02
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")
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.
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.
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.
Write the Form in the middle of the above figure in form.py.
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.
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.
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.
If you decide on these 4 items, CreateView will automatically do various things for you.
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/
.
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/
.
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 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.
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 |
---|---|---|
With the above, the Create part has been implemented.
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