image source
前陣子看到了這個
Youtube影片
決定花了一點時間去研究練習Django網站的各種寫法,其中包括原生template、fetch、axios、react,後面其實都在寫Javascript居多,Python改成API後就沒事了XD。
照著影片把最基本的Django template版本先做出來大概會長這樣
# view.py
...
def index(request):
todos = Todo.objects.all()
return render(request, 'base.html', {"todo_list": todos})
@require_http_methods(["POST"])
def add(request):
title = request.POST.get("title", "")
todo = Todo(title=title)
todo.save()
return redirect("index")
def update(request, todo_id):
todo = Todo.objects.get(id=todo_id)
todo.complete = not todo.complete
todo.save()
return redirect("index")
def delete(request, todo_id):
todo = Todo.objects.get(id=todo_id)
todo.delete()
return redirect("index")
首頁+增刪修,且任何動作都直接導回index做重新查詢
// base.html
...
<body>
<div style="margin-top: 50px;" class="ui container">
<h1 class="ui center aligned header">To Do App</h1>
<form class="ui form" action="/add" method="post">
{% csrf_token %}
<div class="field">
<label>Todo Title</label>
<input type="text" name="title" placeholder="Enter Todo..."><br>
</div>
<button class="ui blue button" type="submit">Add</button>
</form>
<hr>
{% for todo in todo_list %}
<div class="ui segment">
<p class="ui big header">{{ todo.id }} | {{ todo.title }}</p>
{% if todo.complete == False %}
<span class="ui gray label">Not Complete</span>
{% else %}
<span class="ui green label">Completed</span>
{% endif %}
<a class="ui blue button" href="/update/{{ todo.id }}">Update</a>
<a class="ui red button" href="/delete/{{ todo.id }}">Delete</a>
</div>
{% endfor %}
</div>
</body>
很簡單且基礎的Jinja2模板,但使用上面的程式碼寫出來的網站不管做什麼事都會重新整理一遍(導回index),現在ajax已經是基本要求了所以開改!
首先先把Django改成API形式吧!這邊就沒用restful framework直接回json
# view.py
...
def index(request):
return render(request, 'base.html')
def api(request):
todos = Todo.objects.all()
return JsonResponse({"data":list(todos.values())})
@require_http_methods(["POST"])
def add(request):
body = request.body.decode("utf-8")
body = json.loads(body)
title = body.get("title", "")
todo = Todo(title=title)
todo.save()
return JsonResponse({"todo_id": todo.id, "complete": todo.complete, "todo_title": todo.title})
def update(request, todo_id):
todo = Todo.objects.get(id=todo_id)
todo.complete = not todo.complete
todo.save()
return JsonResponse({"todo_id": todo_id, "complete": todo.complete})
def delete(request, todo_id):
todo = Todo.objects.get(id=todo_id)
todo.delete()
return JsonResponse({"todo_id": todo_id})
再來就是改base.html
<body onload="get_all_list()">
<div style="margin-top: 50px;" class="ui container">
<h1 class="ui center aligned header">To Do App</h1>
<form class="ui form">
<div class="field">
<label>Todo Title</label>
<input name="title" id="title" placeholder="Enter Todo..." value=""><br>
</div>
<button class="ui blue button" type="button" onclick=add()>Add</button>
</form>
<hr>
<div id="all">
</div>
<script>
document.onkeydown = form_sumbit
function form_sumbit(e){
the_event = e || window.event
code = the_event.keyCode || the_event.which || the_event.charCode
if (code == 13){
add()
return false
}
return true
}
function get_all_list(){
fetch("/api/")
.then(function (response){
return response.json()
})
.then(function (myJosn){
data = myJosn["data"]
data.forEach(todo => {
html = ""
html += '<div id="all_todo'+todo.id+'"> <div class="ui segment"> '
html += '<p class="ui big header">'+todo.id+' | '+todo.title+'</p> '
if (todo.complete){
html += '<span class="ui green label" id="todo'+todo.id+'">Completed</span>'
}
else{
html += '<span class="ui gray label" id="todo'+todo.id+'">Not Complete</span> '
}
html += '<a class="ui blue button" onclick=update_("'+todo.id+'")>Update</a> '
html += '<a class="ui red button" onclick=delete_("'+todo.id+'")>Delete</a> </div></div>'
document.querySelector("#all").innerHTML += html
});
})
}
function add(){
title = document.querySelector("#title").value
data = {
"title": title
}
fetch("/api/add/", {
headers: {
"X-CSRFToken": "{{csrf_token}}",
"user-agent": "Mozilla/4.0 MDN Example",
"content-type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
})
.then(function (response){
return response.json()
})
.then(function (myJson){
todo_id = myJson["todo_id"]
complete = myJson["complete"]
title = myJson["todo_title"]
html = ""
html += '<div id="all_todo'+todo_id+'"> <div class="ui segment"> '
html += '<p class="ui big header">'+todo_id+' | '+title+'</p> '
html += '<span class="ui gray label" id="todo'+todo_id+'">Not Complete</span> '
html += '<a class="ui blue button" onclick=update_("'+todo_id+'")>Update</a> '
html += '<a class="ui red button" onclick=delete_("'+todo_id+'")>Delete</a> </div></div>'
document.querySelector("#all").innerHTML += html
})
}
function update_(todo_id){
fetch("/api/update/"+todo_id)
.then(function (response){
return response.json()
})
.then(function (myJson) {
todo_id = myJson["todo_id"]
complete = myJson["complete"]
ctodo_id = document.querySelector("#todo"+todo_id)
if (complete){
ctodo_id.classList.remove("gray")
ctodo_id.classList.add("green")
ctodo_id.innerHTML = "Completed"
}
else{
ctodo_id.classList.remove("green")
ctodo_id.classList.add("gray")
ctodo_id.innerHTML = "Not Complete"
}
})
}
function delete_(todo_id){
fetch("/api/delete/"+todo_id)
.then(function (response){
return response.json()
})
.then(function (myJson) {
todo_id = myJson["todo_id"]
this_node = document.querySelector("#all_todo"+id)
this_node.parentElement.removeChild(this_node)
})
}
</script>
</div>
</body>
WOW變超多的,我們一個一個拆開來看吧
首先先來看看get_all_list做了什麼
function get_all_list(){
fetch("/api/")
.then(function (response){
return response.json()
})
.then(function (myJosn){
data = myJosn["data"]
data.forEach(todo => {
html = ""
html += '<div id="all_todo'+todo.id+'"> <div class="ui segment"> '
html += '<p class="ui big header">'+todo.id+' | '+todo.title+'</p> '
if (todo.complete){
html += '<span class="ui green label" id="todo'+todo.id+'">Completed</span>'
}
else{
html += '<span class="ui gray label" id="todo'+todo.id+'">Not Complete</span> '
}
html += '<a class="ui blue button" onclick=update_("'+todo.id+'")>Update</a> '
html += '<a class="ui red button" onclick=delete_("'+todo.id+'")>Delete</a> </div></div>'
document.querySelector("#all").innerHTML += html
});
})
}
fetch把過去後回來的response要先過一層json才能使用,而這個就是把原先\