Django 中的 MTV 是什么意思?
在Django中,MTV指的是"Model-Template-View",而不是常见的MVC(Model-View-Controller)架构。Django的设计理念是基于MTV的
- Model(模型)
模型代表数据存取层,负责与数据库交互,定义数据的结构和业务规则。每个模型都是一个Python类,它们的属性定义了数据库表中的字段。 - Template(模板)
模板是负责定义如何显示数据的部分,它包含了HTML和一些额外的标记(模板标签和过滤器),用于将视图中提供的数据渲染成最终的HTML。 - View(视图)
视图处理用户请求,从模型中获取数据并将其传递给模板进行渲染。视图可以被认为是处理Web应用程序中逻辑的地方。在Django中,视图可以是函数或基于类的。
Django 中的 MTV 架构是如何工作的呢?
- 请求处理流程:
当用户发起一个请求时,Django 的中间件(Middleware)首先处理这个请求,执行一系列的预处理操作。例如,中间件可能会处理安全性、会话管理等。
- URL 路由:
请求到达 Django 项目后,Django 使用 URLconf(URL 配置)来确定使用哪个视图处理这个请求。URLconf 是 URL 到视图函数的映射。
- 视图处理:
视图函数(或基于类的视图)被调用,负责处理业务逻辑。视图从模型中获取数据,可能进行一些处理,然后将数据传递给模板。
- 模板渲染:
视图将数据传递给模板,模板负责将数据渲染成最终的HTML响应。模板中包含了HTML代码和Django模板语言的标签,这些标签可以访问视图中提供的数据,以及执行一些逻辑。
- 响应返回:
渲染后的HTML响应被返回给用户的浏览器。如果在视图中有重定向或其他操作,相应的HTTP响应头会被设置。
- 中间件和其他处理:
响应返回给用户之前,中间件再次参与,执行一系列的后处理操作。例如,中间件可以添加安全头、压缩响应等。
如何在 Django 中创建一个新的应用程序?
1: 创建应用程序
在你的 Django 项目的根目录下,运行以下命令:
bashCopy code
python manage.py startapp myapp
这将在项目目录下创建一个名为 myapp 的新应用程序。你可以根据需要将 myapp 替换为你想要的应用程序名称。
2: 配置应用程序
打开 settings.py 文件,将新创建的应用程序添加到 INSTALLED_APPS 配置中:
pythonCopy code
# settings.py
INSTALLED_APPS = [
# ...
'myapp',
]
3: 编写模型
在 myapp 目录下的 models.py 文件中定义应用程序的模型。模型是应用程序中用于表示数据的核心组件。
pythonCopy code
# myapp/models.py
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
def __str__(self):
return self.name
4: 运行迁移
运行以下命令,创建并应用数据库迁移:
bashCopy code
python manage.py makemigrations
python manage.py migrate
5: 创建视图
在 myapp 目录下的 views.py 文件中创建应用程序的视图。
pythonCopy code
# myapp/views.py
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, this is the index view.")
6: 配置 URL
在 myapp 目录下创建一个名为 urls.py 的文件,并配置应用程序的 URL 模式。
pythonCopy code
# myapp/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
在项目的主 urls.py 文件中,包含应用程序的 URL 配置:
pythonCopy code
# project/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('myapp/', include('myapp.urls')),
]
7: 运行开发服务器
现在,运行以下命令启动开发服务器:
bashCopy code
python manage.py runserver
在浏览器中访问 http://127.0.0.1:8000/myapp/ ,你应该能够看到应用程序的视图。
以上步骤涵盖了在 Django 中创建一个简单应用程序的基本流程。根据实际需求,你可以在应用程序中添加模板、静态文件、表单等其他组件。
如何捕获 URL 中的参数和路径变量?
在 Django 中,你可以使用正则表达式来捕获 URL 中的参数和路径变量。这是通过在 urls.py
文件中定义 URL 模式时实现的。以下是一些示例:
捕获路径变量:
python
from django.urls import path
from .views import MyView
urlpatterns = [
path('articles/<int:article_id>/', MyView.as_view(), name='article_detail'),
]
在上面的例子中,<int:article_id>
捕获一个整数类型的路径变量,将其传递给视图函数。
捕获关键字参数:
python
from django.urls import path
from .views import MyView
urlpatterns = [
path('books/<str:genre>/', MyView.as_view(), name='books_by_genre'),
]
在上面的例子中,<str:genre>
捕获一个字符串类型的关键字参数,将其传递给视图函数。
捕获多个路径变量和关键字参数:
python
from django.urls import path
from .views import MyView
urlpatterns = [
path('articles/<int:year>/<int:month>/', MyView.as_view(), name='article_archive'),
]
在上面的例子中,<int:year>
和 <int:month>
捕获两个整数类型的路径变量,将它们传递给视图函数。
在类视图中处理捕获的参数:
在类视图中,你可以通过重写相应的方法来处理捕获的参数。例如,在 MyView
类中:
python
from django.views import View
from django.http import HttpResponse
class MyView(View):
def get(self, request, *args, **kwargs):
# 获取捕获的参数
article_id = kwargs.get('article_id')
genre = kwargs.get('genre')
# 处理逻辑
return HttpResponse(f"Article ID: {article_id}, Genre: {genre}")
在上面的例子中,get
方法中的 kwargs
包含了捕获的路径变量和关键字参数,你可以通过相应的键获取它们的值。
通过这种方式,你可以灵活地捕获和处理 URL 中的参数和路径变量,以满足你的业务需求。
什么是 Django 的 URL 映射?如何定义 URL 映射?
Django 的 URL 映射是指将用户请求的 URL 映射到相应的视图函数或处理类的过程。URL 映射是 Django Web 应用程序中定义 URL 结构的关键组件,它使得在 Django 中处理不同的页面或功能变得简单而灵活。
- 创建 Django 应用程序:
首先,确保已经创建了 Django 应用程序。可以使用以下命令创建应用程序:
bash
python manage.py startapp your_app_name
- 编辑应用程序的
**urls.py**
文件:
在应用程序目录下创建一个名为 urls.py
的文件,该文件用于定义应用程序的 URL 映射。
- 定义 URL 映射规则:
在 urls.py
文件中,导入 Django 的 path
或 re_path
函数,然后定义 URL 映射规则。例如:
python
from django.urls import path
from . import views
urlpatterns = [
path('home/', views.home, name='home'),
path('about/', views.about, name='about'),
]
在上面的例子中,当用户访问 yourdomain.com/home/
时,将调用 views.home
函数;访问 yourdomain.com/about/
时,将调用 views.about
函数。
- 将应用程序的 URL 配置包含到主项目中:
在主项目的 urls.py
文件中,使用 include
函数将应用程序的 URL 配置包含进来:
python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('your_app/', include('your_app_name.urls')),
]
在这个例子中,当用户访问 yourdomain.com/your_app/
时,Django 将使用应用程序中定义的 URL 映射规则来确定具体的视图。
- 命名 URL 映射(可选):
使用 name
参数为 URL 映射命名,这样可以在代码中使用 {% url 'name' %}
模板标签或 reverse
函数引用 URL。
通过以上步骤,成功定义了 Django 应用程序的 URL 映射,将用户的请求映射到相应的视图函数或处理类上。这种模块化的 URL 映射方式使得 Django 应用程序更易于维护和扩展。
请简述 Django 的路由系统是如何工作的。
Django 的路由系统主要通过 URLconf(URL 配置)来工作,其中 URLconf 是一个映射 URL 到视图函数或处理器的配置文件。以下是 Django 路由系统的工作流程:
- URL 配置文件(URLconf): Django 项目中的主
urls.py
文件充当 URLconf 的入口。在该文件中,你可以定义 URL 模式与对应的视图函数之间的映射。
python
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('home/', views.home, name='home'),
path('articles/<int:article_id>/', views.article_detail, name='article_detail'),
# ... 其他 URL 模式
]
- Include 其他 URLconf: 在主
urls.py
中,你可以使用include
函数引入其他应用程序的 URLconf,以便将不同部分的 URL 映射分开管理。
python
# urls.py
from django.urls import include, path
urlpatterns = [
path('app/', include('app.urls')),
# ... 其他 URL 模式
]
- URL 模式匹配: 当用户在浏览器中请求一个 URL 时,Django 的路由系统将按照定义的
urlpatterns
从上至下逐一匹配 URL 模式。 - 正则表达式匹配: URL 模式可以包含正则表达式,以便匹配不同格式的 URL。例如,
<int:article_id>
匹配一个整数类型的参数,并将其传递给视图函数。 - 调用匹配的视图函数: 一旦找到匹配的 URL 模式,Django 将调用与之对应的视图函数。视图函数接收请求对象,执行相应的业务逻辑,然后返回一个 HTTP 响应对象。
- 命名 URL: 在 URLconf 中可以使用
name
参数为每个 URL 模式命名。这样,视图函数可以通过该名称生成 URL,而不是直接硬编码 URL。
在视图函数或模板中,可以使用 reverse
或 {% url %}
模板标签来动态生成命名 URL。
python
# views.py
from django.urls import reverse
def my_view(request):
url = reverse('home')
# ...
什么是 Django 视图装饰器?可以举例几种常见的视图装饰器吗?
Django 视图装饰器是用于修改或扩展视图函数行为的装饰器,它们可以在视图函数被调用之前或之后执行一些操作。这些装饰器可以用于添加权限检查、缓存、登录验证等功能。
@login_required
:
确保用户在访问视图时已经登录。如果用户未登录,则将其重定向到登录页面。
python
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
# 视图逻辑
@permission_required
:
要求用户具有特定权限才能访问视图。
python
from django.contrib.auth.decorators import permission_required
@permission_required('myapp.can_view_data', raise_exception=True)
def my_view(request):
# 视图逻辑
@cache_page
:
将视图的输出缓存一段时间,以提高性能。
python
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 缓存 15 分钟
def my_view(request):
# 视图逻辑
@csrf_exempt
:
允许视图绕过 CSRF 保护。不推荐在生产环境中使用,除非你确切知道自己在做什么。
python
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def my_view(request):
# 视图逻辑
@require_POST
和@require_GET
:
要求视图只能处理 POST 或 GET 请求。
python
from django.views.decorators.http import require_POST, require_GET
@require_POST
def my_post_view(request):
# 处理 POST 请求的逻辑
@require_GET
def my_get_view(request):
# 处理 GET 请求的逻辑
@require_http_methods
:
要求视图只能处理指定的 HTTP 方法。
python
from django.views.decorators.http import require_http_methods
@require_http_methods(["GET", "POST"])
def my_view(request):
# 处理 GET 或 POST 请求的逻辑
什么是类视图(Class-Based Views)?可以提供一些常见的类视图示例吗?
类视图(Class-Based Views,CBVs)是 Django 中一种基于类的视图系统,它提供了一种更加面向对象的方法来编写视图。与函数视图相比,类视图使得组织和重用代码变得更加容易,并提供了更多的灵活性。
以下是一些常见的类视图示例:
1. 通用视图 - ListView:
python
from django.views.generic import ListView
from .models import MyModel
class MyModelListView(ListView):
model = MyModel
template_name = 'myapp/my_model_list.html'
context_object_name = 'my_model_list'
这个类视图使用 Django 的通用视图 ListView
,它自动渲染一个对象列表。
2. 通用视图 - DetailView:
python
from django.views.generic import DetailView
from .models import MyModel
class MyModelDetailView(DetailView):
model = MyModel
template_name = 'myapp/my_model_detail.html'
context_object_name = 'my_model'
这个类视图使用 DetailView
,用于渲染单个对象的详细信息。
3. 创建视图 - CreateView:
python
from django.views.generic.edit import CreateView
from .models import MyModel
from .forms import MyModelForm
class MyModelCreateView(CreateView):
model = MyModel
form_class = MyModelForm
template_name = 'myapp/my_model_form.html'
success_url = '/success/'
这个类视图使用 CreateView
,它用于处理创建对象的场景。
4. 更新视图 - UpdateView:
python
from django.views.generic.edit import UpdateView
from .models import MyModel
from .forms import MyModelForm
class MyModelUpdateView(UpdateView):
model = MyModel
form_class = MyModelForm
template_name = 'myapp/my_model_form.html'
success_url = '/success/'
这个类视图使用 UpdateView
,用于处理更新对象的场景。
5. 删除视图 - DeleteView:
python
from django.views.generic.edit import DeleteView
from .models import MyModel
from django.urls import reverse_lazy
class MyModelDeleteView(DeleteView):
model = MyModel
template_name = 'myapp/my_model_confirm_delete.html'
success_url = reverse_lazy('my_model_list')
这个类视图使用 DeleteView
,用于处理删除对象的场景。
什么是 Django 视图函数?如何定义一个视图函数?
Django 视图函数是处理用户请求并返回 HTTP 响应的 Python 函数。视图函数负责接收用户的输入、执行业务逻辑,并返回适当的 HTTP 响应,通常是一个渲染后的 HTML 页面。
- 导入必要的模块:
在你的 Django 应用程序中的 views.py
文件中,首先导入必要的模块。
python
from django.shortcuts import render
from django.http import HttpResponse
- 编写视图函数:
编写一个 Python 函数,该函数将处理用户请求和业务逻辑,并返回一个 HttpResponse 对象或使用 render
函数渲染一个模板。
python
def my_view(request):
# 业务逻辑
data = "Hello, Django!"
# 返回 HttpResponse
return HttpResponse(data)
# 或者使用 render 函数渲染模板
# return render(request, 'my_template.html', {'data': data})
- 配置 URL 映射:
在应用程序的 urls.py
文件中配置 URL 映射,将 URL 映射到刚才定义的视图函数。
python
from django.urls import path
from .views import my_view
urlpatterns = [
path('my-url/', my_view, name='my_view'),
]
- 启动开发服务器:
运行以下命令启动 Django 开发服务器。
bash
python manage.py runserver
- 访问视图:
打开浏览器,访问配置的 URL(例如,http://127.0.0.1:8000/my-url/
),查看视图的响应。
在 Django 中,如何定义一个视图函数?这个视图函数需要返回什么?
在 Django 中,定义一个视图函数是处理 HTTP 请求并返回 HTTP 响应的关键步骤。以下是定义一个简单视图函数的基本步骤:
- 导入必要的模块: 在你的应用的
views.py
文件中,首先导入必要的模块,包括 HttpResponse、render 等。
python
from django.http import HttpResponse
from django.shortcuts import render
- 定义视图函数: 创建一个函数,函数的参数通常包括一个
request
对象,该对象包含了当前的 HTTP 请求信息。在函数体内执行相应的逻辑。
python
def my_view(request):
# 视图逻辑
return HttpResponse("Hello, Django!")
或者,使用 render
函数返回一个渲染后的模板:
python
def my_view(request):
# 视图逻辑
return render(request, 'my_template.html', {'variable': 'value'})
- HTTP 响应: 视图函数通常需要返回一个 HTTP 响应对象。这可以是简单的文本响应、HTML 内容,也可以是渲染后的模板。
返回简单的文本响应:
python
from django.http import HttpResponse
def my_view(request):
return HttpResponse("Hello, Django!")
返回渲染后的模板:
python
from django.shortcuts import render
def my_view(request):
return render(request, 'my_template.html', {'variable': 'value'})
- URL 映射: 在你的应用的
urls.py
文件中,将视图函数与特定的 URL 路径进行映射。
python
from django.urls import path
from .views import my_view
urlpatterns = [
path('my-url/', my_view, name='my_view'),
]
如何从视图函数中渲染模板?
在 Django 中,你可以使用 render
函数从视图函数中渲染模板。render
函数简化了渲染过程,它接受请求对象、模板名称以及一个包含上下文数据的字典作为参数,并返回一个包含渲染内容的 HttpResponse
对象。
- 导入必要的模块:
python
from django.shortcuts import render
from django.http import HttpResponse
- 定义视图函数:
python
def my_view(request):
# 业务逻辑
data = "Hello, Django!"
# 使用 render 函数渲染模板,并传递上下文数据
return render(request, 'my_template.html', {'data': data})
- 创建模板:
在你的应用程序的 templates
目录下创建一个名为 my_template.html
的模板文件,用于渲染内容。
html
<!DOCTYPE html>
<html>
<head>
<title>My Template</title>
</head>
<body>
<h1>{{ data }}</h1>
</body>
</html>
- 配置 URL 映射:
在应用程序的 urls.py
文件中配置 URL 映射,将 URL 映射到刚才定义的视图函数。
python
from django.urls import path
from .views import my_view
urlpatterns = [
path('my-url/', my_view, name='my_view'),
]
- 启动开发服务器:
运行以下命令启动 Django 开发服务器。
bash
python manage.py runserver
- 访问视图:
打开浏览器,访问配置的 URL(例如,http://127.0.0.1:8000/my-url/
),查看视图的响应。
上述例子中,render
函数用于将 my_template.html
模板渲染,并将 data
数据传递给模板。模板中的 {``{ data }}
将显示视图函数中传递的数据。这是一个简单的示例,实际应用中,模板通常包含更多的动态内容和模板标签。
什么是 Django 模板?如何使用模板标签和过滤器?
Django 模板是一种基于标记语言的轻量级模板系统,用于将动态数据嵌入到 HTML 页面中。模板系统允许开发者通过使用模板标签和过滤器动态地生成页面内容,从而实现前后端的分离和更好的代码组织。
模板标签:
- 变量插值:
使用 {``{ variable }}
语法插入变量的值。
html
<p>{{ username }}</p>
- for 循环:
使用 {% for item in items %}
和 {% endfor %}
来遍历列表或查询集。
html
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
- if 语句:
使用 {% if condition %}
和 {% endif %}
来进行条件判断。
html
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}!</p>
{% else %}
<p>Please log in.</p>
{% endif %}
- include 包含:
使用 {% include 'partial_template.html' %}
将其他模板包含到当前模板中。
html
{% include 'header.html' %}
模板过滤器:
- safe 过滤器:
使用 |safe
来标记输出的内容为安全的,不进行 HTML 转义。
html
{{ content|safe }}
- date 过滤器:
使用 |date
来格式化日期。
html
{{ article.pub_date|date:'F j, Y' }}
- length 过滤器:
使用 |length
获取列表或字符串的长度。
html
{{ items|length }}
- default 过滤器:
使用 |default
设置变量的默认值。
html
{{ variable|default:"No value" }}
- slice 过滤器:
使用 |slice
对列表或字符串进行切片。
html
{{ text|slice:":50" }}
什么是 Django 模板标签库?可以提供一些自定义模板标签的示例吗?
Django 模板标签库(Template Tag Library)是一组在模板中使用的标签和过滤器,它们可以执行一些特定的逻辑或操作,使得在模板中的展示更加灵活。Django 提供了许多内置的模板标签和过滤器,同时你也可以创建自定义的模板标签库以满足特定的需求。
- 创建一个 Django 应用:
bash
python manage.py startapp myapp
- 在应用目录中创建
**templatetags**
目录:
bash
myapp/
├── __init__.py
├── templatetags/
│ ├── __init__.py
│ └── custom_tags.py
- 在
**custom_tags.py**
中定义自定义标签:
python
# myapp/templatetags/custom_tags.py
from django import template
register = template.Library()
@register.simple_tag
def hello_world():
return "Hello, World!"
在模板中,首先需要加载你的自定义标签库:
html
{% load custom_tags %}
然后就可以使用自定义标签了:
html
{% hello_world %}
这是一个简单的例子,以下是一个更复杂的示例:
python
# myapp/templatetags/custom_tags.py
from django import template
from myapp.models import MyModel
register = template.Library()
@register.inclusion_tag('myapp/my_model_list.html')
def show_my_model_list():
my_model_list = MyModel.objects.all()
return {'my_model_list': my_model_list}
html
<!-- myapp/my_model_list.html -->
<ul>
{% for my_model in my_model_list %}
<li>{{ my_model.name }}</li>
{% endfor %}
</ul>
html
<!-- template.html -->
{% load custom_tags %}
{% show_my_model_list %}
这个例子中,show_my_model_list
标签通过 inclusion_tag
返回一个包含 MyModel 列表的模板片段。在模板中使用这个标签可以方便地展示 MyModel 列表。通过自定义模板标签库,你可以在模板中添加更复杂的逻辑和重用可视化组件,使得模板更具可维护性和可重用性。
如何使用 Django 模板继承和包含(template inclusion)?
Django 模板继承和包含是两种在模板中组织和重用代码的强大机制。
模板继承(Template Inheritance):
模板继承允许你定义一个基础模板,并在其他模板中扩展或重写特定块,从而避免在每个页面中重复相同的 HTML 结构。以下是一个简单的例子:
基础模板 ( **base.html**
):
html
<!-- base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
<header>
<h1>{% block header %}My Website{% endblock %}</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
© 2023 My Website
</footer>
</body>
</html>
子模板 ( **child.html**
):
html
<!-- child.html -->
{% extends 'base.html' %}
{% block title %}Page Title{% endblock %}
{% block header %}Welcome to My Page{% endblock %}
{% block content %}
<p>This is the content of my page.</p>
{% endblock %}
在上述例子中,child.html
继承了 base.html
,并覆盖了基础模板中的标题、页眉和内容块。
模板包含(Template Inclusion):
模板包含允许你在一个模板中包含另一个模板的内容,使得你可以在多个地方重用相同的代码片段。以下是一个简单的例子:
包含的模板 ( **include_me.html**
):
html
<!-- include_me.html -->
<p>This is included content.</p>
主模板 ( **main_template.html**
):
html
<!-- main_template.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Main Template</title>
</head>
<body>
<header>
<h1>Welcome to My Website</h1>
</header>
<main>
{% include 'include_me.html' %}
</main>
<footer>
© 2023 My Website
</footer>
</body>
</html>
在上述例子中,main_template.html
主模板包含了 include_me.html
的内容。通过使用模板继承和包含,你可以更有效地组织和重用你的模板代码,提高代码的可维护性。
什么是 Django 表单?如何创建和处理表单?
Django 表单是一种用于处理 HTML 表单的强大工具,它允许开发者轻松创建表单、验证用户输入以及处理表单提交的数据。Django 表单通常用于用户交互,例如用户注册、登录、搜索等功能。
创建表单类:
- 导入必要的模块:
在你的 Django 应用程序中的 forms.py
文件中,首先导入必要的模块。
python
from django import forms
- 定义表单类:
创建一个继承自 forms.Form
的类,并在类中定义表单的字段。
python
class MyForm(forms.Form):
username = forms.CharField(label='Username', max_length=100)
email = forms.EmailField(label='Email')
password = forms.CharField(label='Password', widget=forms.PasswordInput)
在视图中处理表单:
- 导入表单类:
在处理表单的视图中导入刚才定义的表单类。
python
from .forms import MyForm
- 处理 GET 请求(显示表单):
在处理 GET 请求的视图中,创建一个表单实例并将其传递给模板。
python
def my_form_view(request):
form = MyForm()
return render(request, 'my_template.html', {'form': form})
- 处理 POST 请求(处理表单提交):
在处理 POST 请求的视图中,检查表单是否有效,如果有效则处理表单提交的数据。
python
def my_form_view(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
# 处理表单提交的数据
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
# 进行进一步的处理,如保存到数据库等
else:
form = MyForm()
return render(request, 'my_template.html', {'form': form})
在模板中显示表单:
- 渲染表单:
在模板中使用 {``{ form }}
或循环渲染表单的各个字段。
html
<form method="post" action="{% url 'my_form_view' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>