学习目标:
- 学习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标签。