Todo List with Django (Dennis Ivy)
0. Upgrade Django Version
pip install --upgrade django==3.0
1. Create Project
django-admin startproject todolist[name of project]
2. Run Server
inside the project folder
ctrl + c: break on server
3. Migrate DB
python manage.py migrate
by default, django uses sqlite but normally you'd wanna use postgresql or mysql.
created our default table: user
4. Create Admin(User)
python manage.py createsuperuser
5. Launch an App
python manage.py startapp [app name]
Register an App into settings
settings.py
INSTALLED_APPS
6. url Routing
1. Create 'index function' at views.py
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("hello world")
2. Create urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index)
]
3. Include url in base urls.py
This should sets up the response. Turn on server to check.
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('tasks.urls'))
]
Successfully set up
7. Templates
app> templates > tasks > html
Note the file name
def index(request):
return render(request, 'tasks/list.html')
8. Create Model
__str__
when you retrieve data from DB with
Blog.objects.all()
, It will return<QuerySet [<Blog:>,<Blog:>,...]
It's hard to recognize the objects.
Better way is retrieving them by one of its properties which you set it as name.
<QuerySet [<Blog:itsName>,<Blog:itsName>,...]
models.py
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
any new models?
python manage.py makemigrations
create in DB
python manage.py migrate
Register model at admin
admin.py
from .models import *
admin.site.register(Task)
so we can see table in our server admin section
9. Render Data in template
- context is our third parameter that passes DB object.
views.py
from .models import *
def index(request):
tasks = Task.objects.all()
context = { 'tasks': tasks }
return render(request, 'tasks/list.html', context)
- I already added tasks into db through admin website to see if it's rendered correctly.
list.html
<h3>todo</h3>
{% for task in tasks %}
<div>
<p>
{{ task }}
</p>
</div>
{% endfor %}
10. Model Forms
Ivy prefers to use 'Model Forms' over 'built-in Class based views forms'. He thinks It's too easy to make it work but not helps to underderstand it.
Hence, He goes for 'Model Forms'
1. Create folder 'forms.py'**
inside app folder
form representation of a model
forms.py
from django import forms
from django.forms import ModelForm
from .models import *
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = '__all__'
2. Pass the data as parameter
Pass form instance as 3rd parameter inside context
views.py
from .forms import *
def index(request):
tasks = Task.objects.all()
form = TaskForm()
context = {'tasks': tasks, 'form': form}
return render(request, 'tasks/list.html', context)
3. Into Template
Pass the form into template
create html form element and get passed the data
list.html
<form>
{{ form.title }}
<input type="submit" name="Create Task">
</form>
CRUD
11. Create Item
when we submit data, it's gonna send it back to view
1. template
- make sure to include csrf_token
list.html
{% csrf_token %}
2. view
- passing the 'post method' into the form
views.py
def index(request):
tasks = Task.objects.all()
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {'tasks': tasks, 'form': form}
return render(request, 'tasks/list.html', context)
12. Update Item (Edit)
pk == primary key
grab the pk from url pattern
<str:pk>
: str value works with numbers and letters- Dynamic Name: make url dynamic by assigning name.
how we call the url pattern
1. url
urls.py
urlpatterns = [
path('', views.index, name="list"),
path('update_task/<str:pk>',
views.update_task, name="update_task"),
]
2. view
1) GET
pre-populated form
views.py
def update_task(request, pk):
task = Task.objects.get(id=pk)
form = TaskForm(instance=task)
context = {'form': form}
return render(request, 'tasks/update_task.html', context)
2) POST
Add post. if we only pass request.POST, it will create a new obj. Make sure to pass instance we are updating.
form = TaskForm(request.POST, instance=task)
def update_task(request, pk):
task = Task.objects.get(id=pk)
form = TaskForm(instance=task)
context = {'form': form}
if request.method == 'POST':
form = TaskForm(request.POST, instance=task)
if form.is_valid():
form.save()
return redirect('/')
return render(request, 'tasks/update_task.html', context)
3. template
- Create Update link to direct to edit page
-used 'name' 'update_task' in url pattern
<a href="{% url 'update_task' task.id %}">Update</a>
== update_task/1
list.html
{% for task in tasks %}
<div>
<a href="{% url 'update_task' task.id %}">Update</a>
<p>{{ task }}</p>
</div>
{% endfor %}
update_task.html
<h3>Update Task</h3>
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" name="Update Task">
</form>
13. Delete Item
UI: Ask user to confirm their action: sure you want to delete?
1. url
path('delete_task/<str:pk>',views.delete_task,
name="delete_task"),
2. views
1. GET
Get confirmation
def delete_task(request, pk):
item = Task.objects.get(id=pk)
context = {'item': item}
return render(request, 'tasks/delete.html', context)
2. POST
Actually delete from DB
def delete_task(request, pk):
item = Task.objects.get(id=pk)
context = {'item': item}
if request.method == 'POST':
item.delete()
return redirect('/')
return render(request, 'tasks/delete.html', context)
3. templates
list.html
<a href="{% url 'delete_task' task.id %}">Delete</a>
- We don't need a form as it will just delete the item.
delete.html
<p> Are you sure you want to delete "{{ item }}"? </p>
<a href="{% url 'list' %}"> Cancel </a>
<form action="" method="POST">
{% csrf_token %}
<input type="submit" name="Confirm">
</form>
14. Cross out complete items
- html strike tag will place a strikethrough (horizontal line) over text on the complete task (ticked off)
list.html
{% if task.complete == True %}
<strike>{{ task }}</strike>
{% else %}
<span> {{task}} </span>
{% endif %}
- complete is from form model
models.py
class Task(models.Model):
complete = models.BooleanField(default=False)
15. Style template
video 36:05 - Style template
form: sets a place holder
as we don't use html form, we can't set placeholder directly from html form element.
-customizing the form field
form.py
class TaskForm(forms.ModelForm):
title = forms.CharField(
widget= forms.TextInput(
attrs={'placeholder': 'Add new task...'}))
Result
Author And Source
이 문제에 관하여(Todo List with Django (Dennis Ivy)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@daylee/Todo-List-with-Django-Dennis-Ivy저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)