学习目标:
- 学习resetfull接口
- 掌握Django web基础设施
学习内容:
1.学习resetfull接口
简介
人工智能解释:
 
应用场景
以下是人工智能使用Django框架实现的restfull接口代码:
#views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import UserModel
import json
 @csrf_exempt
def user_list(request):
    # GET方法,获取用户列表
    if request.method == 'GET':
        users = UserModel.objects.all()
        data = []
        for user in users:
            data.append({'id': user.id, 'name': user.name, 'age': user.age})
        return JsonResponse(data, safe=False)
     # POST方法,创建新用户
    elif request.method == 'POST':
        # 从请求中获取 JSON 数据,并解析
        data = json.loads(request.body.decode('utf-8'))
        name = data['name']
        age = data['age']
        # 创建新用户并保存到数据库
        user = UserModel(name=name, age=age)
        user.save()
        # 返回创建的用户信息
        return JsonResponse({'id': user.id, 'name': user.name, 'age': user.age})
 @csrf_exempt
def user_detail(request, user_id):
    # 获取指定 ID 的用户
    try:
        user = UserModel.objects.get(id=user_id)
    except UserModel.DoesNotExist:
        return JsonResponse({'error': 'User does not exist'}, status=404)
     # GET 方法,获取指定 ID 的用户信息
    if request.method == 'GET':
        data = {'id': user.id, 'name': user.name, 'age': user.age}
        return JsonResponse(data)
     # PUT 方法,更新指定 ID 的用户信息
    elif request.method == 'PUT':
        # 从请求中获取 JSON 数据,并解析
        data = json.loads(request.body.decode('utf-8'))
        user.name = data['name']
        user.age = data['age']
        # 更新用户信息并保存到数据库
        user.save()
        # 返回更新后的用户信息
        data = {'id': user.id, 'name': user.name, 'age': user.age}
        return JsonResponse(data)
     # DELETE 方法,删除指定 ID 的用户信息
    elif request.method == 'DELETE':
        user.delete()
        return JsonResponse({'message': 'User deleted'})
在这个示例中,我们使用Python的Django框架实现了一个简单的RESTful API,包括获取所有用户、获取指定用户、创建用户、更新用户和删除用户等操作。我们通过HTTP协议中的GET、POST、PUT和DELETE方法来对用户资源进行不同的操作,并返回不同的响应状态码和数据格式。使用这个API,我们可以通过浏览器、命令行工具或其他HTTP客户端发送请求,并与服务端进行通信,实现数据的增删改查等操作。
学习点记录:
 Q:from django.views.decorators.csrf import csrf_exempt 这句代码意思是?
 A: 这句代码的作用是使视图函数免除跨站请求伪造(CSRF)保护。
 在Django中,默认情况下,所有的POST、PUT、DELETE等需要修改数据的请求都需要附带CSRF令牌,以防止跨站请求伪造的攻击。如果没有加上csrf_exempt装饰器,则视图函数会检查请求中是否包含有效的CSRF令牌,如果没有,则会返回403 Forbidden。
 而使用csrf_exempt装饰器可以告诉视图函数忽略CSRF令牌的检查,从而使得我们能够方便地对API进行测试和调试。但是,注意要确保在真正的生产环境中,所有的POST、PUT、DELETE请求都要附带有效的CSRF令牌,以保障网站的安全性。
 Q:from .models import UserModel 这句函数什么意思?
 A: 这句代码的含义是从当前目录下的 models 模块中导入 UserModel 模型。其中 . 表示当前目录,而 models 是Python模块的文件名, .py 扩展名可省略。
 在Django中,模型是与数据库表相对应的数据模型。 UserModel 模型是程序中定义的一个简单模型,包含了用户的姓名和年龄两个字段。在实际的应用中,我们可以根据需要定义更加复杂的模型,例如文章、评论、订单等等。
 使用模型的好处是可以方便地通过代码来操作数据库,不需要手写SQL语句。当我们在程序中定义好了模型后,就可以通过Django的ORM框架来实现数据的增删改查等操作。ORM框架会自动将我们的操作转化为对数据库的增删改查操作,并且在必要的时候还会自动处理事务、校验数据等问题,使得我们能够更加方便、安全、高效地操作数据库。
实验途径
使用如下方法,我们可以向一个URL发送不同的resetfull请求:
# 发起GET请求
import requests
 response = requests.get('http://example.com')
print(response.content)
# 发起POST请求
import requests
 url = 'http://example.com/api/create'
data = {'name': 'John', 'age': 30}
 response = requests.post(url, data=data)
print(response.content)
# 发起PUT请求
import requests
 url = 'http://example.com/api/update'
data = {'name': 'John', 'age': 31}
 response = requests.put(url, data=data)
print(response.content)
# 发起DELETE请求
import requests
 url = 'http://example.com/api/delete'
data = {'id': 123}
 response = requests.delete(url, data=data)
print(response.content)
2.Django web基础设施
简介
Django提供了很多与浏览器通信的机制,例如url路由、使用模板定制化html、resetfull接口实现等。
应用目录结构
目录结构如下图:
 
demo001\1.asgi.py
此文件用来处理异步请求。ASGI 是一种异步Web服务器网关接口,用于处理异步请求。它是一种全新的接口定义,使用异步I/O来提高性能和伸缩性(以至于服务器忙于等待某个IO到来而阻塞了其他服务,这样会导致cpu时间片的白白浪费),并且可以处理多种数据交换协议,通常使用单线程的事件循环实现,也可以使用多进程或集群进行水平扩展。
demo001\2.wsgi.py
Django 早期的 Web 服务器是基于 WSGI 的服务器。
demo001\3.settings.py
该文件为项目配置文件,在django启动时,会从该文件中获取配置信息,比如安装app。
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'daphne',
    #'django.contrib.staticfiles',
]
demo001\4.urls.py
此文件用于注册url和视图函数。
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
    path('admin/', admin.site.urls),
    path('myapp/', include('myapp.urls')),
]
常用技巧手段
1.使用asgi作为web服务器
1.创建 ASGI 应用程序
 在你的 Django 项目目录下,创建一个名为 asgi.py 的文件,输入以下内容:
import os
from django.core.asgi import get_asgi_application
 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_asgi_application()
注意将 myproject 替换为你的项目名称。
 2.下载 ASGI 服务器
 为了部署 ASGI 应用程序,需要先安装一个 ASGI 服务器。这里我们选择使用 Daphne 作为 ASGI 服务器,可以通过以下命令进行安装:
pip install daphne
3.部署 ASGI 应用程序
 接下来,使用 Daphne 服务器部署 ASGI 应用程序。有两种部署方式,命令行部署如下:
daphne myproject.asgi:application
源码部署方式如下:
修改settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'daphne',
    #'django.contrib.staticfiles',
]
ASGI_APPLICATION = 'myproject.asgi.application'
这将启动一个 Daphne 服务器实例,使用 myproject 应用程序的 ASGI 配置。
2.使用wsgi作为web服务器
作为早期的服务器,不需要适配,Django默认支持。默认配置如下:
# wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'demo001.settings')
application = get_wsgi_application()
# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
# 下面配置无所谓,代码中有动态适配
# 代码app_path = getattr(settings, "WSGI_APPLICATION")
WSGI_APPLICATION = 'demo001.wsgi.application'
3.使用GET接口接收客户端请求
get为获取数据。请求url一般使用的是get命令。
 使用form表单提交get请求:
视图函数
@csrf_exempt
def my_test(request):
    if request.method == 'GET':
        print("This is a GET request!!")
        print("request.GET %s" %request.GET)
    elif request.method == 'POST':
        print("This is a POST request!!")
        print("request.POST %s" %request.POST)
    else:
        pass
    global count
    count += 3
    print("my_test count:%s" %count)
    return render(request, 'test.html')
url路由
app_name = 'myapp'
urlpatterns = [
    path('test', my_test)
]
html form表单
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <form method="get">
        <input type="text" name="hs5name">
        <input type="number" name="h5age">
        <button type="submit">Submit</button>
    </form> 
</body>
</html>
点击Submit向后台请求GET命令。
4.使用POST接口接收客户端请求
post为提交数据。
 使用form表单提交post请求:
html form表单
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <form method="post">
        <input type="text" name="hs5name">
        <input type="number" name="h5age">
        <button type="submit">Submit</button>
    </form> 
</body>
</html>
点击Submit向后台请求POST命令。其他代码与GET命令一致。
5.使用PUT接口接收客户端请求
由于安全原因,Web 应用程序有时会禁用 PUT 和 DELETE 方法。
6.使用DELETE接口接收客户端请求
由于安全原因,Web 应用程序可能会禁用 PUT 和 DELETE 方法。
7.创建视图函数和url路由表
视图函数一般分为函数视图、类视图、通用视图
7.1. 函数视图
urls.py
urlpatterns = [
    path('hello', hello),
]
views.py
def hello(request):
    return HttpResponse("Hello, Django!")
7.2. 类视图
一种继承自 View 类的自定义实现的视图类。
views.py
from django.views import View
from django.http import HttpResponse
class HelloView(View):
    def get(self, request):
        return HttpResponse("Hello, Django!")
urls.py
urlpatterns = [
    path('helloview', HelloView.as_view())
]
7.3. 通用视图
提供了一些常用的类试图工具。
 1.TemplateView类
urls.py
from django.urls import path
from django.views.generic.base import TemplateView
urlpatterns = [
    path('about/', TemplateView.as_view(template_name='about.html'), name='about')
]
views.py
from django.urls import path
from django.views.generic.base import TemplateView
urlpatterns = [
    path('about/', TemplateView.as_view(template_name='about.html'), name='about')
]
templates/about.html
<!-- templates/about.html -->
<!DOCTYPE html>
<html>
    <head>
        <title>About Us</title>
    </head>
    <body>
        <h1>About Us</h1>
        <p>We are a company that does amazing things.</p>
    </body>
</html>
2.RedirectView类
urls.py
from django.urls import path
from django.views.generic.base import RedirectView
urlpatterns = [
    path('home/', RedirectView.as_view(url='http://www.baidu.com'), name='home')
]
3.ArchiveIndexView类
 每次查询数据库所有的目标,最终按日志进行排序归类,并返回给前端。
models.py
class Article(models.Model):
    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField()
    def __str__(self):
        return self.title
    
    class Meta:
        app_label = 'myapp'
urls.py
path('archiveindex/', BlogArchiveIndexView.as_view(), name='archiveindex'),
views.py
class BlogArchiveIndexView(ArchiveIndexView):
    date_field = 'pub_date'
    template_name = 'archiveindex.html'
    queryset = Article.objects.all()
    
    def get(self, request, *args, **kwargs):
        self.date_list, self.object_list, extra_context = self.get_dated_items()
        context = self.get_context_data(
            object_list=self.object_list, date_list=self.date_list, **extra_context
        )
        
        Article.objects.create(title=generate_random_chinese(5), pub_date='2023-05-20')
        Article.objects.create(title=generate_random_chinese(5), pub_date='2023-05-21')
        Article.objects.create(title=generate_random_chinese(5), pub_date='2023-05-22')
        class_list = []
        for date in self.date_list:
            article_list = []
            for article in self.object_list:
                if date.year == article.pub_date.year:
                    article_list.append(article)
            class_list.append([date, article_list])
        
        context.setdefault("class_list", class_list)
        return self.render_to_response(context)
archiveindex.html
<!DOCTYPE html>
<html>
  <head>
    <title>Blog Archive</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.0.0/css/bootstrap.min.css">
  </head>
  <body>
    <div class="container">
      <h1 class="mt-4 mb-3">Blog Archive</h1>
      {% for date, articles in class_list %}
        <div class="card mb-4">
          <div class="card-header">
            {{ date|date:"F Y" }}
          </div>
          <ul class="list-group list-group-flush">
            {% for article in articles %}
              <li class="list-group-item">
                <a href="{{ article.get_absolute_url }}">{{ article.title }}</a>
                <a href="{{ article.get_absolute_url }}">{{ article.pub_date }}</a>
              </li>
            {% endfor %}
          </ul>
        </div>
      {% endfor %}
    </div>
  </body>
</html>
4.YearArchiveView类
 每次查询数据库指定年份的目标,将查询结果返回给前端。
models.py
class Event(models.Model):
    title = models.CharField(max_length=200)
    start_date = models.DateField()
    def __str__(self):
        return self.title
    class Meta:
        app_label = 'myapp'
urls.py
path('events/<int:year>/', EventYearArchiveView.as_view(), name="event_year_archive"),
views.py
class EventYearArchiveView(YearArchiveView):
    def __init__(self, *args, **kwargs):
        Event.objects.create(title='Test 1', start_date='2023-04-01')
        Event.objects.create(title='Test 2', start_date='2023-06-01')
        Event.objects.create(title='Test 3', start_date='2023-08-01')
        super().__init__(**kwargs)
    queryset = Event.objects.all()
    date_field = 'start_date'
    make_object_list = True
    allow_future = False
    allow_empty = True
    template_name = 'event_archive_year.html'
base.html & event_archive_year.html
<html>
<head>
    <title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
    <header>
        {% block header %}
            <h1>Default Header</h1>
        {% endblock %}
    </header>
    <div>
        {% block content %}
            <p>Default Content</p>
        {% endblock %}
    </div>
    <footer>
        {% block footer %}
            <p>Default Footer</p>
        {% endblock %}
    </footer>
</body>
</html>
{% extends "base.html" %}
{% block content %}
  <h2>Events in {{ year }}</h2>
  {% if object_list|length %}
    <ul>
    {% for event in object_list %}
      <li>{{ event.title }}-{{ event.start_date }}</li>
    {% endfor %}
    {% for date in date_list %}
        <li> {{date}} </li>
    {% endfor %}
    </ul>
  {% else %}
    <p>No events found.</p>
  {% endif %}
{% endblock content %}
输入url:http://127.0.0.1:8000/myapp/events/2023/ 既可以查看2023年的数据。
 5.MonthArchiveView类
 每次查询数据库指定月份的目标,将查询结果返回给前端。
models.py
class BlogPost(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_date = models.DateTimeField(auto_now_add=True)
    is_published = models.BooleanField(default=False)
urls.py
path('monthblog/<int:year>/<str:month>', BlogMonthArchiveView.as_view(), name='archive_month'),
views.py
class BlogMonthArchiveView(MonthArchiveView):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        BlogPost.objects.create(title=generate_random_chinese(5), content=generate_random_chinese(20))
        BlogPost.objects.create(title=generate_random_chinese(5), content=generate_random_chinese(20))
        BlogPost.objects.create(title=generate_random_chinese(5), content=generate_random_chinese(20))
    model = BlogPost
    date_field = 'created_date'
    allow_future = False
    template_name = 'archive_month.html'
    paginate_by = 10
archive_month.html
{% extends "base.html" %}
{% block content %}
  <h2>Blogs in {{ months }}</h2>
  {% if object_list|length %}
    <ul>
    {% for Blog in object_list %}
      <li>{{ Blog.title }}-{{Blog.content}} {{ Blog.created_date }}</li>
    {% endfor %}
    {% for date in date_list %}
        <li> {{date}} </li>
    {% endfor %}
    </ul>
  {% else %}
    <p>No events found.</p>
  {% endif %}
{% endblock content %}
url: http://127.0.0.1:8000/myapp/monthblog/2023/May
 6.WeekArchiveView类
 每次查询数据库指定周的目标,将查询结果返回给前端。
models.py
class WeekReport(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_date = models.DateTimeField(auto_now_add=True)
views.py
class WeekReportArchiveView(WeekArchiveView):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        WeekReport.objects.create(title=generate_random_chinese(4), content=generate_random_chinese(20))
    
    model = WeekReport
    date_field = 'created_date'
    template_name = 'archive_week.html'
urls.py
path('weekreport', WeekReportArchiveView.as_view()),
html
{% extends "base.html" %}
{% block content %}
  <h2>Blogs in {{ week }}</h2>
  {% if object_list|length %}
    <ul>
    {% for Blog in object_list %}
      <li>{{ Blog.title }}-{{Blog.content}} {{ Blog.created_date }}</li>
    {% endfor %}
    {% for date in date_list %}
        <li> {{date}} </li>
    {% endfor %}
    </ul>
  {% else %}
    <p>No events found.</p>
  {% endif %}
{% endblock content %}
url: http://127.0.0.1:8000/myapp/weekreport?year=2023&week=21
 7.DayArchiveView类
 每次查询数据库指定天的目标,将查询结果返回给前端。
models.py
class DayModel(models.Model):
    my_title = models.CharField(max_length=255, verbose_name='标题')
    my_content = models.TextField(verbose_name='内容')
    my_date_field = models.DateTimeField(verbose_name='日期', auto_now_add=True)
    class Meta:
        verbose_name = '我的模型'
        verbose_name_plural = '我的模型'
    def __str__(self):
        return self.my_title
views.py
class MyDayArchiveView(DayArchiveView):
    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        DayModel.objects.create(my_title=generate_random_chinese(4), my_content=generate_random_chinese(20))
    queryset = DayModel.objects.all()
    date_field = "my_date_field"
    template_name = 'archive_day.html'
    allow_future = True
urls.py
path('dayarchive/<int:year>/<str:month>/<int:day>', MyDayArchiveView.as_view()),
archive_day.html
{% extends "base.html" %}
{% block content %}
  <h2>daily in {{ day }}</h2>
  {% if object_list|length %}
    <ul>
      <li>标题-内容-创建时间</li>
    {% for daily in object_list %}
      <li>{{ daily.my_title }}-{{daily.my_content}}: {{ daily.my_date_field }}</li>
    {% endfor %}
    {% for date in date_list %}
        <li> {{date}} </li>
    {% endfor %}
    </ul>
  {% else %}
    <p>No events found.</p>
  {% endif %}
{% endblock content %}
url:http://127.0.0.1:8000/myapp/dayarchive/2023/MAY/27
 8.TodayArchiveView类
 每次查询数据库当天的目标,将查询结果返回给前端。
models.py
class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    def __str__(self):
        return self.title
urls.py
    path('today/', TodayPostArchiveView.as_view()),
    path('post/<int:pk>/', post_detail, name='post_detail'),
views.py
class TodayPostArchiveView(TodayArchiveView):
    queryset = Post.objects.all()
    date_field = "pub_date"
    template_name = "post_archive.html"
    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        try:
            user = User.objects.get(username='jack')
            if user:
                print("user exist!!!")
        except User.DoesNotExist:
            user = User.objects.create(username='jack')
        post = Post.objects.create(
            title='my post',
            content='hello, world!',
            author=user
        )
def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'post_detail.html', {'post': post})
post_archive.html
{% extends "base.html" %}
{% block content %}
  <h1>Archive for {{ day }}</h1>
  <ul>
    {% for post in object_list %}
      <li>
        <a href="{% url 'myapp:post_detail' post.pk %}">{{ post.title }}</a>
        <br>
        <small>Published on {{ post.pub_date }} by {{ post.author }}</small>
      </li>
    {% empty %}
      <li>No posts yet.</li>
    {% endfor %}
  </ul>
{% endblock %}
post_detail.html
{% extends 'base.html' %}
{% block content %}
  <h1>{{ post.title }}</h1>
  <p>{{ post.pub_date|date }}</p>
  <div>{{ post.content }}</div>
{% endblock %}
url:http://127.0.0.1:8000/myapp/today/
 9.DateDetailView类
 每次查询数据库指定天中某个目标(这个目标是唯一的,比如主键),将查询结果返回给前端。
models.py
class DetaiModel(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    def __str__(self):
        return self.title
views.py
class MyModelDetailView(DateDetailView):
    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        DetaiModel.objects.create(title=generate_random_chinese(3), content=generate_random_chinese(200))
    model = DetaiModel
    date_field = "updated_at"
    month_format = "%m"
    day_format = "%d"
    slug_field = "slug"
    context_object_name = "mymodel"
    template_name = "mymodel_detail.html"
urls.py
    path('datedetail/<int:pk>/', MyModelDetailView.as_view()),
mymodel_detail.html
{% extends "base.html" %}
{% block content %}
  <article class="my-model-detail">
    <h1>{{ mymodel.title }}</h1>
    <div class="created-at">创建于:{{ mymodel.created_at }}</div>
    <div class="created-at">更新于:{{ mymodel.updated_at }}</div>
    <div class="content">{{ mymodel.content }}</div>
  </article>
{% endblock %}
url:http://127.0.0.1:8000/myapp/datedetail/20/?year=2023&month=05&day=27
 10.DetailView类
 每次查询数据库指定某个目标(这个目标是唯一的,比如主键),将查询结果返回给前端。
models.py
class MyDetaiModel(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
views.py
class MyDetailView(DetailView):
    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        MyDetaiModel.objects.create(name=generate_random_chinese(3), description=generate_random_chinese(200))
    template_name = 'my_detailview.html'
    model = MyDetaiModel
    context_object_name = 'my_detailview'
    pk_url_kwarg = 'my_id'
urls.py
    path('my_model_detail/<int:my_id>/', MyDetailView.as_view(), name='my_model_detail'),
my_detailview.html
{% block content %}
<h1>{{ my_detailview.name }}</h1>
<p>描述:{{ my_detailview.description }}</p>
<p>创建时间:{{ my_detailview.created_at }}</p>
{% endblock %}
url:http://127.0.0.1:8000/myapp/my_model_detail/16/
 11.FormView类
 处理表单的视图函数,将Web前端提交数据的结果返回给Web前端。
views.py
class ContactForm(forms.Form):
    name = forms.CharField()
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)
class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = reverse_lazy('myapp:success')
    def form_valid(self, form):
        # 处理提交的表单数据
        name = form.cleaned_data['name']
        email = form.cleaned_data['email']
        message = form.cleaned_data['message']
        # ... 这里可以将数据保存到数据库等等操作
        return super().form_valid(form)
def success_view(request):
    return render(request, 'success.html')
urls.py
    path('formview/', ContactView.as_view(), name='contact'),
    path('success/', success_view, name='success'),
contact.html
{% extends "base.html" %}
{% block content %}
  {% if form.errors %}
    <p>Please correct the following errors:</p>
    <ul>
      {% for field in form %}
        {% for error in field.errors %}
          <li>{{ error }}</li>
        {% endfor %}
      {% endfor %}
    </ul>
  {% endif %}
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit</button>
  </form>
{% endblock %}
success.html
{% extends "base.html" %}
{% block content %}
  <h1>Thank you for contacting us!</h1>
{% endblock %}
url:http://127.0.0.1:8000/myapp/success/
 12.CreateView类
 处理表单的视图函数,将Web前端提交数据保存到数据库,并使用post命令查询当前数据库数据返回给Web前端。
models.py
class MyFormModel(models.Model):
    name = models.CharField(max_length=50)
    content = models.TextField()
class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyFormModel
        fields = ['name', 'content']
views.py
class MyModelCreateView(CreateView):
    model = MyFormModel
    form_class = MyModelForm
    template_name = 'mymodel_create.html'
    success_url = reverse_lazy('myapp:mymodel_list')
class MyModelListView(ListView):
    model = MyFormModel
    template_name = 'mymodel_list.html'
    context_object_name = 'mymodels'
urls.py
    path('create/', MyModelCreateView.as_view(), name='mymodel_create'),
    path('mymodel_list/', MyModelListView.as_view(), name='mymodel_list'),
mymodel_create.html
{% extends 'base.html' %}
{% block content %}
  <h1>Create a new MyModel</h1>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Create</button>
  </form>
{% endblock %}
mymodel_list.html
{% extends 'base.html' %}
{% block content %}
  <h1>My Models</h1>
  <ul>
  {% for mymodel in mymodels %}
    <li>{{ mymodel.name }}</li>
  {% empty %}
    <p>No models found.</p>
  {% endfor %}
  </ul>
{% endblock %}
url:http://127.0.0.1:8000/myapp/create/
 13.UpdateView类
 处理表单的视图函数,查询数据库数据并更新数据到数据库,然后查询当前数据库数据返回给Web前端。
views.py
class MyModelUpdateView(UpdateView):
    model = MyFormModel
    form_class = MyModelForm
    template_name = 'mymodel_update.html'
    success_url = reverse_lazy('myapp:mymodel_list')
urls.py
    path('update/<int:pk>/', MyModelUpdateView.as_view(), name='mymodel_update'),
mymodel_update.html
{% extends 'base.html' %}
{% block content %}
  <h1>Edit My Model</h1>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Update</button>
  </form>
{% endblock %}
url:http://127.0.0.1:8000/myapp/update/5/
 14.DeleteView类
 通过url删除数据库指定数据,然后查询当前数据库数据返回给Web前端。
views.py
class MyModelDeleteView(DeleteView):
    model = MyFormModel
    template_name = 'mymodel_delete.html'
    success_url = reverse_lazy('myapp:mymodel_list')
urls.py
    path('delete/<int:pk>/', MyModelDeleteView.as_view(), name='mymodel_delete')
mymodel_delete.html
{% extends 'base.html' %}
{% block content %}
  <h1>Delete My Model</h1>
  <p>Are you sure you want to delete "{{ object }}"?</p>
  <form method="post">
    {% csrf_token %}
    <button type="submit">Delete</button>
    <a href="{% url 'myapp:mymodel_list' %}">Cancel</a>
  </form>
{% endblock %}
url:http://127.0.0.1:8000/myapp/delete/1/
 15.ListView类
 数据库所有数据,然后查询结果给Web前端。
views.py
class MyModelListView(ListView):
    model = MyFormModel
    template_name = 'mymodel_list.html'
    context_object_name = 'mymodels'
urls.py
    path('mymodel_list/', MyModelListView.as_view(), name='mymodel_list')
mymodel_list.html
{% extends 'base.html' %}
{% block content %}
  <h1>My Models</h1>
  <table>
    <thead>
      <tr>
        <th>主键</th>
        <th>名字</th>
        <th>内容</th>
      </tr>
    </thead>
    <tbody>
      {% for mymodel in mymodels %}
        <tr>
          <td>{{ mymodel.pk }}</td>
          <td>{{ mymodel.name }}</td>
          <td>{{ mymodel.content }}</td>
        </tr>
      {% empty %}
        <tr><td>NA</td><td>NA</td><td>NA</td></tr>
      {% endfor %}
  
    </tbody>
  </table>
{% endblock %}
16.GenericViewError类
 当视图函数出现异常时,可以给增加异常处理中间件将错误输出到Web前端。
middleware.py
class MyExceptionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        response = self.get_response(request)
        return response
    def process_exception(self, request, exception):
        if isinstance(exception, GenericViewError):
            error_message = exception.message
            return HttpResponse(error_message, status=500)
views.py
class MyGenericViewError(GenericViewError):
    def __init__(self, message):
        self.message = message
def testGenericViewError(request):
    try:
        indx = list(5)
        indx[5] = 'xxxx'
    except Exception as ext:
        print(str(ext))
        raise MyGenericViewError("请求HTTP时出现错误:" + "testGenericViewError" + str(ext))
urls.py
    path('testViewError/', testGenericViewError),
url:http://127.0.0.1:8000/myapp/testViewError/
8.在html中使用Django模板函数
1.传递变量
使用render函数传递字典变量给模板。格式:{{var}}
urls.py
    path('testVariable/', testVariable),
views.py
def testVariable(request):
    context = {'variable': 12}
    return render(request, 'testVariable.html', context)
testVariable.html
{% extends "base.html" %}
{% block content %}
<h1> 接收到的数据值为:{{ variable }} </h1>
{% endblock %}
url:http://127.0.0.1:8000/myapp/testVariable/
2. 过滤器
Django4.2过滤器
 将传递给模板的变量,按照过滤器指定的格式输出。格式:{{var|过滤器}}
testVariable.html
{% extends "base.html" %}
{% block content %}
<h1> 接收到的数据值为:{{ variable|add:"3" }} </h1>
{% endblock %}
3. 标签
常见的标签有if、for等,如Django4.2标签。













