pip install --upgrade django==3.0
django-admin startproject todolist[name of project]
inside the project folder
ctrl + c: break on server
python manage.py migrate
by default, django uses sqlite but normally you'd wanna use postgresql or mysql.
created our default table: user
python manage.py createsuperuser
python manage.py startapp [app name]
Register an App into settings
settings.py
INSTALLED_APPS
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("hello world")
from django.urls import path
from . import views
urlpatterns = [
path('', views.index)
]
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
app> templates > tasks > html
Note the file name
def index(request):
return render(request, 'tasks/list.html')
__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
views.py
from .models import *
def index(request):
tasks = Task.objects.all()
context = { 'tasks': tasks }
return render(request, 'tasks/list.html', context)
list.html
<h3>todo</h3>
{% for task in tasks %}
<div>
<p>
{{ task }}
</p>
</div>
{% endfor %}
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'
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__'
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)
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>
when we submit data, it's gonna send it back to view
list.html
{% csrf_token %}
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)
pk == primary key
grab the pk from url pattern
<str:pk>
: str value works with numbers and lettersurls.py
urlpatterns = [
path('', views.index, name="list"),
path('update_task/<str:pk>',
views.update_task, name="update_task"),
]
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)
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)
<a href="{% url 'update_task' task.id %}">Update</a>
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>
UI: Ask user to confirm their action: sure you want to delete?
path('delete_task/<str:pk>',views.delete_task,
name="delete_task"),
Get confirmation
def delete_task(request, pk):
item = Task.objects.get(id=pk)
context = {'item': item}
return render(request, 'tasks/delete.html', context)
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)
list.html
<a href="{% url 'delete_task' task.id %}">Delete</a>
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>
list.html
{% if task.complete == True %}
<strike>{{ task }}</strike>
{% else %}
<span> {{task}} </span>
{% endif %}
models.py
class Task(models.Model):
complete = models.BooleanField(default=False)
video 36:05 - Style template
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...'}))