[不做怎么知道系列之Android开发者的30天后端养成故事 Day7] - 资料飞来飞去 #怎么传资料? #Djang

http://img2.58codes.com/2024/20124548TlT0wznW8G.png

大家好,我们又见面了,今天来看看怎么在网页上,直接对资料库新增资料吧!

透过 Form 的方式来新增资料

Django 有个很方便的功能是,定义好 form 的格式后,它会帮你把栏位给补到 html 去,来看看怎么做吧~

models.py,是之前 Day4 从 Django Girls Tutorial 借过来的 Post model

from django.db import modelsfrom django.utils import timezonefrom django.contrib.auth.models import User    class Post(models.Model):    # 这边我把 author 加了 null=True    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)    title = models.CharField(max_length=200)    content = models.TextField()    created_date = models.DateTimeField(        default=timezone.now()    )    published_date = models.DateTimeField(        blank=True, null=True    )        def publish(self):        self.published_date = timezone.now()        self.save()        def __str__(self):        return self.title

新增 forms.py

定义好 Form 的栏位之后,透过 views.py 把 form 包在 context 传给 html,就可以在 html 上,呈现出我们想要让使用者填的栏位,在这边我只显示 title 和 content,因为其他的栏位是作者、建立的时间、发布的时间,不是让使用者自己填的。

from django import formsfrom .models import Postclass PostForm(forms.ModelForm):class Meta:model = Postfields= {'title','content'}

views.py

from django.shortcuts import renderfrom django.http import JsonResponsefrom django.http import HttpRequestfrom .forms import PostFormfrom .models import Post# 这次我们试着接受 Form 的 POST# 收到的 form 如果合法,我们就存到 DB 去def post_create_view(request):form = PostForm(request.POST or None)if form.is_valid():form.save()context = {'form': form}return render(request, 'blog/post_create.html', context)# 上次新增的 viewdef hello(request):return render(request, 'blog/index.html', {"first_var": "Hello Man","second_var": 87.8787,"third_list": ["欢迎", "你好", "我是 RS", "来比对我阿"]})

/templates/blog/post_create.html

{% extends 'blog/base.html' %}{% block content %}<form method="POST"> {% csrf_token %}<!-- 从 context 拿出 form -->{{ form.as_p }}<input type="submit" value="Submit"></form>{% endblock %}

这边有看到 csrf_token 的 template tag,先不要理它,那是 django 内建预设的 authentication 方法,我们先用用看。

urls.py

from django.contrib import adminfrom django.urls import pathfrom blog.views import hello, post_create_view, test_json_response_viewurlpatterns = [    path('admin/', admin.site.urls),    path('blog/', hello),# 新增一个 让使用者发布文章的页面    path('blog/create/', post_create_view)]

来新增资料看看啰

来到 127.0.0.1/blog/create,可以看到画面上已经有丑丑的简易输入格 XD,这是 django 的 form 帮我们做的,如果不符合你想要的,也可以参考 官方文件 来变成你想要的样式。

http://img2.58codes.com/2024/20124548rpctQWyCLv.png

点下 Submit 后

点下 Submit 后,可以在 开发者工具 的 网路,看到我们从前端传出去的 request,收到 200 OK 的回应,表示应该是没问题才对。

http://img2.58codes.com/2024/2012454824BbZvqzte.png

来到 admin 看看是不是真的有存进去 DB

有耶,hen 棒~

http://img2.58codes.com/2024/20124548y3W3NFaln5.png

再进去到里面,看看是不是真的刚刚新增的那一笔

http://img2.58codes.com/2024/201245489m1Rn6nj3v.png

好的,那么还有没有别的方式来传资料呢 ?

既然你诚心诚意的发问了,那我就大发慈悲的告诉你,有的 ! 那么就是今天的主题:开 API,因为有些情况是希望除了透过网页的方式传资料,有可能是 mobile app 要传资料到我们后端资料库,这时候就需要一支 API 来沟通。

假设我想要让前端,透过一个 POST 塞入 JSON 资料,来新增一笔发文呢?

我的最初想法是,在 Android 端,可以用 Retrofit 轻鬆丢出一个含有 JSON 资料的 POST request,我就想试试看后端要怎么做,才能吃下含 JSON 的 POST request,我们来看看怎么做。

上範例 !

根据 TDD(Test Driven Development),我们先定义出最后要测试的 request 和 response 长什么样子。

利用 Postman 来模拟传、收 request 的情境

request 长这样:

method = POSTurl = 127.0.0.1:8000/testbody = {"title": "Add article by postman POST with json body","content": "yohohoho."}

希望收到的 response 长这样:

{"status": "ok, I got you."}

先据透,最后在 Postman 的结果长这样:

http://img2.58codes.com/2024/201245486sycQBTC72.png

那要怎么做呢?

整体概念是,urls.py 会收到 request,再根据我们自定义的 url 规则,将 request 转发到 views.py 里的 test_json_response_view(request),然后再将 request 里的 body 解析为 JSON 格式,并转成 Post 物件再透过 django model 存到 DB 里,再回个 response 回去,that's it !

views.py

from django.shortcuts import renderfrom django.http import JsonResponsefrom django.views.decorators.csrf import csrf_exemptfrom django.core.handlers.wsgi import WSGIRequestimport jsonfrom .forms import PostFormfrom .models import Post# 让这支 API 免 csrf authentication# (之后我们再来深入!)@csrf_exemptdef test_json_response_view(request: WSGIRequest):print('-----------------------------------')if request.method == 'GET':print("get GET request: ", request)return JsonResponse({'first': 'content', 'second': 'test'})elif request.method == 'POST':# get json datadata = json.loads(request.body)print("get POST request data: ", data)# save to dbPost.objects.create(title=data['title'], content=data['content'])# check posts in dbprint('all posts in db: ', Post.objects.all())# send response to clientreturn JsonResponse({'status': 'ok, I got you.'})else:print("get unknown request: ", request)return JsonResponse({'status': 'no, I don\'t know it.'})# ----------- 以下在这个範例用不到 -----------# Form 的 requestdef post_create_view(request):form = PostForm(request.POST or None)print("form valid: ", form.is_valid, ", request: ", request)if form.is_valid():form.save()context = {'form': form}return render(request, 'blog/post_create.html', context)# template tag testingdef hello(request):return render(request, 'blog/index.html', {"first_var": "Hello Man","second_var": 87.8787,"third_list": ["欢迎", "你好", "我是 RS", "来比对我阿"]})

urls.py

from django.contrib import adminfrom django.urls import pathfrom blog.views import hello, post_create_view, test_json_response_viewurlpatterns = [    path('admin/', admin.site.urls),    path('blog/', hello),    path('blog/create/', post_create_view),# 转发 request 到 views.py 的 JSON API    path('test/', test_json_response_view)]

Django 跑起来

$ python manage.py runserver

再到 Postman 送出 request ! 所以结果就是前面所看到的这张

给没用过 postman 的人们的简易导览,思考顺序是从红色(request method and url) → 橘色(put json data in body) → 黄色(get response)

http://img2.58codes.com/2024/20124548iZG3U75eP8.png

如果是 GET 的话,也可以用浏览器访问 127.0.0.1:8000/test/,就回一个含有 JSON 的 response,这样就达到一支 API 可以同时符合 GET 和 POST 两种。

http://img2.58codes.com/2024/20124548GSTsEFXNRJ.png

再到 admin 确认是不是有真的存进去 DB

http://img2.58codes.com/2024/20124548NGy1CJQeiS.png

单日心得总结

恩... 其实我犯了一个错误,我在 Day5 和 Day6 提到说要开 API,原本以为开个 API 应该可以用很简单的方式做,才知道我把这个饼画得太大,就不知道该怎么写这一篇,所以你可以观察到,恩,我漏了一天,这件事对你们来说虽然没什么,但是对我来讲是没有达到对自己的承诺,昨天随着时间越拖越晚,就渐渐进入到一个低潮的状态,谢谢我的女朋友给我打气,今天才能再复活。

老实说,学会了之后再回去看都会觉得不难,但是我在走这段路的时候,真的是觉得超级难懂,为什么还有 csrf token 问题、在 postman 明明加上 csrf token 却还是没办法 POST 成功,我没想到会这么早碰到 authentication 的问题 QQ,还傻傻地想要在这篇一起把它给解决了,年轻人终究是年轻人。

感谢看到文章最后的你们,还有感谢我的女朋友。

我是 RS,这是我的 不做怎么知道系列 文章,我们 明天见。


喜欢我的文章吗? 赶快来看看我都发了什么文章吧:我的文章目录

欢迎阅读我的上一篇: [不做怎么知道系列之Android开发者的30天后端养成故事 Day6] - 运用框架的槓桿 #前后端怎么结合 #框架的威力 #Django Template Engine

欢迎阅读我的下一篇: [不做怎么知道系列之Android开发者的30天后端养成故事 Day8] - 换个皮 #怎么套用前端样版? #DjangoFileManagment #StaticFiles


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章