zl程序教程

您现在的位置是:首页 >  后端

当前栏目

[Django] 00 - What is Django

django is What 00
2023-09-27 14:23:24 时间

资源

MVT (MVC)

 

十借课,每节一个小时。

01 Django框架简介与环境搭建【先把 django-admin的命令装好】

 

每节比较短。

6节课入门Django框架web开发

 

有多用讲解的课程,较好。

Django Tutorials

 

 

一、创建项目

先安装虚拟环境。

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方法

request是直接发给“视图”的。

在./Book/views.py中,创建视图方法。

from django.shortcuts import render
from dgango.http import HttpResponse

def test(request):
  response = HttpResponse('测试')
  return response

补充:另一个 rest api 的例子

 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),
 ]

 

   

模板

在./Book/views.py中,创建视图方法,调用template。

  • 如何查找模板路径?

settings.py 中,

BASE_DIR = os.path.dirname(...),在系统中引入模板路径 by 'DIRS'。

 

  • 如何调用模板?

return掉html模板作为rest返回值。

带有参数dict:context 

模板中存在变量。

 

End.