A continuation of 4 where Django beginners create simple apps. The purpose is to get rid of complicated and troublesome things as much as possible, create a simplified web application, and learn how Django works. Only understand what is connected and how it moves around the back end. Implement CRUD (Create, Read, Update, Delete) and if it works, you will reach the goal. Last time, I rewrote Class-based-view to Function-view and compared the two to see how Django works. This time I would like to implement the Update part and Delete part of CRUD. So, in fact, it's complete.
-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 make simple apps 3 --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 Create Easy Apps 5 (Completed This Time) --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 "Django Beginners Create Easy Apps 1)
The log is displayed on the page of the movie details screen, and when you want to edit the log for a while, you can edit it by pressing the button.
When creating a new page, create it in the order of urls.py → views.py → template. I think that the omission of thinking will be reduced by fitting the method of making into a mold in this way. First, write the address ʻupdate / log / <int: pk> /` when updating the log (impression) 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'),
# (Omission)
path('update/log/<int:pk>/', views.UpdateLogView.as_view(), name='updatelog'), #Add this line
]
Next, write the code of UpdateLogView which is Class-based-view in views.py.
myapp/views.py
class UpdateLogView(generic.UpdateView):
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 })
#If Function-If you write in view, it is as follows
def updatelog(request, pk):
obj = get_object_or_404(Log, id=pk)
if request.method == "POST":
form = LogForm(request.POST, instance=obj)
if form.is_valid():
form.save()
return redirect('myapp:movie_detail', pk=obj.movie.pk)
else:
form = LogForm(instance=obj)
return render(request, 'myapp/register.html', {'form': form})
Four items should be specified in Class UpdateLogView
(same as the previous CreateView).
So, you can see how it actually works with the def update log
in Function-view.
The request part of (request, pk)
is an HttpRequest object that can be created by pressing the edit button in detail.html. The id number of the log is entered in the pk part. Then, using this pk, a number is entered in the <int: pk>
part of ʻupdate / log / <int: pk> /` in urls.py. Note below.
This completes the Update implementation. Next, implement the Delete part.
I want two functions, one to erase the log (impression) and the other to erase the movie data. Then you should write two sets of code in urls.py and two in views.py.
myapp/urls.py
from django.urls import path, include
from myapp import views
app_name = 'myapp'
urlpatterns = [
path('', views.index, name='index'),
# (Omission)
path('delete/log/<int:pk>/', views.deletelog, name='deletelog'), #Add this line
path('delete/movie/<int:pk>/', views.deletemovie, name='deletemovie'), #Add this line
]
The address described here is the confirmation screen for deletion. The place where "Can I erase this?" Next, write the code in views.py.
myapp/views.py
class DeleteLogView(generic.DeleteView):
model = Log
def get_success_url(self):
return reverse('myapp:movie_detail', kwargs={'pk': self.object.movie.pk })
#Function from here-view
def deletelog(request, pk):
obj = get_object_or_404(Log, id=pk)
movie_id = obj.movie.pk
if request.method =="POST":
obj.delete()
return redirect('myapp:movie_detail', pk=movie_id)
context = {'obj':obj}
return render(request, "myapp/delete.html", context)
In Class-based-view, all you have to do is specify the model and the page to skip when it succeeds. However, if there are only these two items, the name of the deletion confirmation page needs to be "○○ _confirm_delete.html". The name of the model is entered in 〇〇. This time it will be "log_confirm_delete.html". In Function-view, "delete.html" was created and used as a deletion confirmation page.
Class-based-view does it automatically, and what I had to devise in Function-view is that after deleting the log, the details screen after deletion is displayed. If you don't save the movie id of the log before clearing the log, you won't be able to return to the movie details screen. Note below.
myapp/views.py
class DeleteMovieView(generic.DeleteView):
model = Movie
def get_success_url(self):
return reverse('myapp:index')
#Function from here-view
def deletemovie(request, pk):
obj = get_object_or_404(Movie, id=pk)
if request.method == "POST":
obj.delete()
return redirect('myapp:index')
context = {'obj':obj}
return render(request, "myapp/delete.html", context)
The code is almost a repeat of delete log. The only difference is that it jumps to the index after deletion.
This template is the deletion confirmation screen (delete.html). The same delete.html can be used regardless of whether the log is deleted or the movie data is deleted. Although the display looks awkward (one of the top and bottom is blank).
myapp/templates/myapp/delete.html
<form method="POST">
{% csrf_token %}
{{obj.movie}}<br> #This is displayed when deleting the log
{{obj.text}}<br>
------------------------------<br>
{{obj.title}}<br> #This is displayed when you delete the movie
{{obj.director}}<br>
Do you want to delete it?<br>
<button type="submit">OK</button>
</form>
Add edit and delete buttons to detail.html with
templates/myapp/detail.html
{% for log in movie.log.all %}
<li>
<button onclick="location.href='{% url 'myapp:updatelog' log.id %}'">edit</button>
<button onclick="location.href='{% url 'myapp:deletelog' log.id %}'">delete</button>
{{ log.text }}
</li>
{% endfor %}
This completes the implementation of the Delete part.
--Put a link in index.html to jump to each page
index.html
<a href="{% url 'myapp:registerdirector' %}">Register Director</a><br>
<a href="{% url 'myapp:registermovie' %}">Register Movie</a><br>
<a href="{% url 'myapp:writinglog' %}">Writing Log</a>
--Add function + link so that you can enter the log of the movie from detail.html
views.py
def writingthismovielog(request, movie_id):
obj = get_object_or_404(Movie, id=movie_id)
form = LogForm({'movie':obj})
if request.method == "POST":
form = LogForm(request.POST)
if form.is_valid():
l = form.save(commit=False)
l.save()
return redirect('myapp:movie_detail', pk=l.movie.pk)
else:
return render(request, 'myapp/register.html', {'form': form})
When I pressed the button, only the title of the movie was already entered, and I wanted to just write my impressions. The point of ingenuity is form = LogForm ({'movie': obj})
. You created an object, specified the title part in a dictionary type, and put it in LogForm. I tried it and it worked. This is because it should be like this! It's fun if it works as I expected. It's just this one line, but I'm really happy about it.
detail.html
<a href="{% url 'myapp:writingthismovielog' movie.id %}">Write log of this movie data</a><br>
<a href="{% url 'myapp:deletemovie' movie.id %}">Delete this movie data</a><br>
<a href="{% url 'myapp:index' %}">To Index</a><br>
Then paste the above link in detail.html and complete the fine adjustment.
Update and Delete Log | Delete Movie data |
---|---|
For the above gif video, capture the screen as a video with SimpleScreenRecord and convert the video to gif with ffmpeg. It's easy to do and it's out of tune. Isn't the world going too far?
Aiming only to work, it doesn't deploy and looks bad, but I was able to implement CRUD (Create, Read, Update, Delete). At least it's working. So, ** Goooooooaaaaallll! ** I was able to hold down the minimum basics. For the first time, this app (Modoki) was an experience with the feeling that "I was able to program on my own!", Which led to a slight confidence that I made 0 to 1. Name this "movielogrecord" and put the code on github. Both ignorance and shame are open to the public. It is https://github.com/soh506/movielogrecord.git. Thank you for reading. We look forward to helping you even a little. Next, let's study around the front end to make it look better. The eternal beginner's study continues ...
Recommended Posts