[Django] 00 - What is Django
资源
MVT (MVC)
十借课,每节一个小时。
01 Django框架简介与环境搭建【先把 django-admin的命令装好】
每节比较短。
一、创建项目
先安装虚拟环境。
1. 环境变量设置 ./bashrc 132 ### virtualenv and virtualenvwrapper ########### 133 export WORKON_HOME=$HOME/.virtualenvs 134 export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 135 source /usr/local/bin/virtualenvwrapper.sh 2. 根据python3常见一个虚拟环境 mkvirtualenv -p python3 jdango 3. 进入虚拟环境 django $ workon jdango 4, 安装 packages Django==3.0.5 djangorestframework==3.11.0 psycopg2-binary==2.8.5 pytest-django==3.9.0 5. 退出虚拟环境 $ deactivate 6. 删除虚拟环境 $ rmvirtualenv django
开始创建。
(env) jeffrey@unsw-ThinkPad-T490:django$ django-admin startproject BookManager (env) jeffrey@unsw-ThinkPad-T490:django$ ls BookManager env
# BookManager是个包,用于import (env) jeffrey@unsw-ThinkPad-T490:BookManager$ ls BookManager manage.py (env) jeffrey@unsw-ThinkPad-T490:BookManager$ ls BookManager/ asgi.py __init__.py settings.py urls.py wsgi.py
-
补充:新增 db.sqlite3
jeffrey@unsw-ThinkPad-T490:MyProject$ python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying sessions.0001_initial... OK jeffrey@unsw-ThinkPad-T490:MyProject$ ls db.sqlite3 manage.py MyProject
二、创建APP
Book 跟 rest api 有关。
BookManager 跟 django原生项目 有关。
(env) jeffrey@unsw-ThinkPad-T490:BookManager$ python manage.py startapp Book (env) jeffrey@unsw-ThinkPad-T490:BookManager$ ls Book BookManager manage.py
(env) jeffrey@unsw-ThinkPad-T490:BookManager$ tree . ├── Book │ ├── admin.py │ ├── apps.py │ ├── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── BookManager │ ├── asgi.py │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── manage.py
目录结构解析。
三、项目加载APP
貌似,还要在此基础上,添加一个 'rest_framework'。
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # install our own app. 'Book', ]
运行(测试)服务器。
$ python manage.py runserver
点击链接,有admin登录界面。
Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). December 01, 2020 - 03:53:02 Django version 3.1.3, using settings 'MyProject.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. [01/Dec/2020 03:53:06] "GET / HTTP/1.1" 200 16351 [01/Dec/2020 03:53:06] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423 [01/Dec/2020 03:53:06] "GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1" 200 86184 [01/Dec/2020 03:53:06] "GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1" 200 85876 [01/Dec/2020 03:53:06] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 200 85692 Not Found: /favicon.ico [01/Dec/2020 03:53:06] "GET /favicon.ico HTTP/1.1" 404 1975
模型
一、内嵌ORM框架
-
定义模型类
class BookInfo(models.Model): """define book info.""" name = models.CharField(max_length=10) class PeopleInfo(models.Model): """define people info.""" name = models.CharField(max_length=10) gender = models.BooleanField() book = models.ForeignKey(BookInfo)
-
模型迁移
Ref: 理解Django的makemigrations和migrate
将类映射成表: 第一步 生成 “建表”的语句 --> Running migrations --> 表(in db.sqlite3),本质上,大概是如下三个过程。
(1) 相当于在该app下建立 migrations目录。
(2) 并记录下你所有的关于modes.py的改动,比如0001_initial.py, 但是这个改动还没有作用到数据库文件。
(3) 将该改动作用到数据库文件,比如产生table,修改字段的类型等。
$ python manage.py makemigrations
$ python manage.py migrate
补充:看起来是 将与db相关的 model部分,经过操作,添加了新东西在 api_basic/migrations/ 下。
jeffrey@unsw-ThinkPad-T490:MyProject$ ls api_basic db.sqlite3 manage.py MyProject
jeffrey@unsw-ThinkPad-T490:MyProject$ python manage.py makemigrations Migrations for 'api_basic': api_basic/migrations/0001_initial.py - Create model Article
jeffrey@unsw-ThinkPad-T490:MyProject$ python manage.py migrate Operations to perform: Apply all migrations: admin, api_basic, auth, contenttypes, sessions Running migrations: Applying api_basic.0001_initial... OK
首先,定义一个 Article的模型。./api_baic/models.py
from django.db import models # Create your models here. class Article(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=100) email = models.EmailField(max_length=100) date = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
然后,再注册。./api_baic/admin.py
from django.contrib import admin from .models import Article # Register your models here. admin.site.register(Article)
最后,UI界面有对应的URL。
-
数据库 ORM 操作
$ python manage.py shell >>> from Book.models import BookInfo >>> book = BookInfo() >>> book.name = '西游记'
补充: 这里加载的就是 ./api_basic 中刚定义好的 models.py。
jeffrey@unsw-ThinkPad-T490:MyProject$ python manage.py shell Python 3.7.0 (default, Jun 28 2018, 13:15:42) Type 'copyright', 'credits' or 'license' for more information IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: from api_basic.models import Article In [2]: from api_basic.serializers import ArticleSerializer In [3]: from rest_framework.renderers import JSONRenderer In [4]: from rest_framework.parsers import JSONParser In [5]: a = Article(title = 'Article Title', author = 'Parwiz', email = 'par@gmail.com')
In [6]: a.save()
save的结果就是数据库中添加了项,如下。
-
序列化、字符串化
In [7]: a = Article(title = 'New Article', author = 'John', email = 'joh@gmail.com') In [8]: a.save() # *** 序列化,可以直接看到类的内容 In [9]: serializer = ArticleSerializer(a) In [10]: serializer.data Out[10]: {'title': 'New Article', 'author': 'John', 'email': 'joh@gmail.com', 'date': '2020-12-01T07:49:25.041145Z'} # *** json化,可以直接字符串展现 In [11]: content = JSONRenderer().render(serializer.data) In [12]: content Out[12]: b'{"title":"New Article","author":"John","email":"joh@gmail.com","date":"2020-12-01T07:49:25.041145Z"}' In [13]: serializer = ArticleSerializer(Article.objects.all(), many=True) In [14]: serializer.data Out[14]: [OrderedDict([('title', 'Article Title'), ('author', 'Parwiz Hao'), ('email', 'par@gmail.com'), ('date', '2020-12-01T07:14:29.791152Z')]), OrderedDict([('title', 'New Article'), ('author', 'John'), ('email', 'joh@gmail.com'), ('date', '2020-12-01T07:49:25.041145Z')])]
这个序列化为什么要怎么写?内在原理是什么?
/* doto */
貌似 ModelSerializer 比 Serializer 更好一些。
# serializers.py
X from rest_framework import serializers from .models import Article # class ArticleSerializer(serializers.Serializer): class ArticleSerializer(serializers.ModelSerializer): class Meta: model = Article fields = ['id', 'title', 'author'] # ModelSerializer seems to be easier. # title = serializers.CharField(max_length=100) # author = serializers.CharField(max_length=100) # email = serializers.EmailField(max_length=100) # date = serializers.DateTimeField() # # def create(self, validated_data): # return Article.objects.create(validated_data) # # def update(self, instance, validated_data): # instance.title = validated_data.get('title', instance.title) # instance.author = validated_data.get('author', instance.author) # instance.email = validated_data.get('email', instance.email) # instance.date = validated_data.get('date', instance.date) # # instance.save() # # return instance
二、站点管理
-
管理界面本地化
在 .BookManager/settings.py 中。
-
创建管理员
$ python manage.py createsuperuser
$ python manage.py runserver
-
注册模型类
在 ./Book/admin.py中注册。添加:
admin.site.register(BookInfo)
admin.site.register(PeopleInfo)
UI新增内容如下:
-
发布内容到数据库
通过UI添加数据即可。
-
自定义站点管理界面
在BookInfo和PeopleInfo两个类添加 __str__。如此,UI显示属性名字,而非类的名字。
def __str__(self): return self.name
扩展admin.py的能力。
from django.contrib import admin from Book.models import BookInfo, PeopleInfo class PeopleInfoAdmin(admin.ModelAdmin): list_display = ['id', 'name', 'gender', 'book'] admin.site.register(BookInfo) admin.site.register(PeopleInfo, PeopleInfoAdmin)
UI展示内容好看了许多。
视图
一、创建视图HTTP方法
from django.shortcuts import render from dgango.http import HttpResponse def test(request): response = HttpResponse('测试') return response
from django.shortcuts import render from django.http import HttpResponse, JsonResponse from rest_framework.parsers import JSONParser from .models import Article from .serializers import ArticleSerializer from django.views.decorators.csrf import csrf_exempt # Create your views here. # https://www.django-rest-framework.org/tutorial/1-serialization/ # CSRF(跨站请求伪造)概述 @csrf_exempt def article_list(request): if request.method == 'GET': articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return JsonResponse(serializer.data, safe=False) elif request.method == 'POST': data = JSONParser().parse(request) serializer = ArticleSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400)
二、定义路由处理策略
(1) 在 ./BookManager/urls.py 中的路由规则,定义在了 settings.py 中:
ROOT_URLCONF = ‘BookManager.urls’
(2) 类似地,向 应用 ./Book/urls.py 中去找,如下定义。
(3) 创建一个新的 ./Book/urls.py。调用并test这个“视图”。
补充:一个扩展的例子。
from django.urls import path from .views import article_list, article_detail urlpatterns = [ path('article/', article_list), path('detail/<int:pk>', article_detail), ]
模板
-
如何调用模板?
return掉html模板作为rest返回值。
带有参数dict:context
模板中存在变量。
End.