面是一个使用Django框架搭建自动化测试平台的基本教程。我们将创建一个简单的自动化测试平台,它能够接收用户的测试用例提交、执行这些测试用例,并返回测试结果。
确保你已经安装了Python。然后,在命令行中安装Django:
Bash
深色版本
1pip install django
创建一个新的Django项目:
Bash
深色版本
1django-admin startproject test_platform
2cd test_platform
创建一个名为tests的应用:
Bash
深色版本
1python manage.py startapp tests
编辑test_platform/urls.py文件,将新的应用添加到URL配置中:
Python
深色版本
1from django.contrib import admin
2from django.urls import path, include
3
4urlpatterns=[
5 path('admin/', admin.site.urls),
6 path('', include('tests.urls')),
7]
在tests应用中创建urls.py文件:
Python
深色版本
1from django.urls import path
2from . import views
3
4urlpatterns=[
5 path('', views.index, name='index'),
6 path('submit_test/', views.submit_test, name='submit_test'),
7 path('results/<int:test_id>/', views.results, name='results'),
8]
在tests/views.py文件中编写视图函数:
Python
深色版本
1from django.shortcuts import render, redirect, get_object_or_404
2from .forms import TestForm
3from .models import Test
4from django.http import HttpResponse
5from django.core.files.storage import FileSystemStorage
6
7def index(request):
8 return render(request, 'tests/index.html')
9
10def submit_test(request):
11 if request.method=='POST':
12 form=TestForm(request.POST, request.FILES)
13 if form.is_valid():
14 test=form.save()
15 # 在这里可以调用脚本来执行测试
16 return redirect('results', test_id=test.id)
17 else:
18 form=TestForm()
19 return render(request, 'tests/submit_test.html', {'form': form})
20
21def results(request, test_id):
22 test=get_object_or_404(Test, pk=test_id)
23 # 从数据库或其他地方获取测试结果
24 return render(request, 'tests/results.html', {'test': test})
在tests/models.py文件中定义模型:
Python
深色版本
1from django.db import models
2
3class Test(models.Model):
4 name=models.CharField(max_length=200)
5 description=models.TextField()
6 file=models.FileField(upload_to='uploads/')
7 created_at=models.DateTimeField(auto_now_add=True)
8
9 def __str__(self):
10 return self.name
在tests/forms.py文件中定义表单:
Python
深色版本
1from django import forms
2from .models import Test
3
4class TestForm(forms.ModelForm):
5 class Meta:
6 model=Test
7 fields=['name', 'description', 'file']
在tests/templates/tests目录下创建模板文件:
例如,submit_test.html可以这样创建:
Html
深色版本
1{% extends 'base.html' %}
2
3{% block content %}
4<h1>Submit a New Test</h1>
5<form method="post" enctype="multipart/form-data">
6 {% csrf_token %}
7 {{ form.as_p }}
8 <button type="submit">Submit Test</button>
9</form>
10{% endblock %}
运行以下命令创建数据库表:
Bash
深色版本
1python manage.py makemigrations
2python manage.py migrate
在项目目录下创建static和media文件夹。然后在settings.py中添加以下设置:
Python
深色版本
1STATIC_URL='/static/'
2MEDIA_URL='/media/'
3MEDIA_ROOT=os.path.join(BASE_DIR, 'media')
启动开发服务器:
Bash
深色版本
1python manage.py runserver
在视图函数submit_test中,你可以添加代码来执行自动化测试脚本。这通常涉及读取用户上传的文件,解析测试用例,并使用如unittest或pytest这样的测试框架来运行测试。
例如,你可以在submit_test函数中添加如下代码来执行测试脚本:
Python
深色版本
1import subprocess
2
3def execute_test_script(file_path):
4 # 假设测试脚本是一个可执行的Python脚本
5 try:
6 output=subprocess.check_output(['python', file_path], stderr=subprocess.STDOUT)
7 # 将输出保存到数据库或返回给用户
8 return output.decode('utf-8')
9 except subprocess.CalledProcessError as e:
10 # 处理错误情况
11 return e.output.decode('utf-8')
一旦完成开发和测试,你可以考虑将应用部署到生产环境。可以选择使用如Heroku、Docker、AWS等服务进行部署。
以上是从零开始使用Django框架搭建自动化测试平台的基本步骤。你可以根据实际需求进一步完善功能,例如增加用户认证、测试报告生成、邮件通知等功能。希望这份指南对你有所帮助!
一篇:Python之Django系列-创建第一个应用-5
我们接着上一篇开始,这一篇我们主要会讲到投票视图以及最终投票结果视图,我们先修改上一篇有说到的polls/templates/polls/detail.html页面,让用户跳转到这个界面时可以选择任意一项进行投票,修改后最终代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>问题详情页</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="投票">
</form>
</body>
</html>
代码讲解
polls/urls.py
这个页面修改成功后,目前数据库中的django_question表和django_choice表的数据截图如下:
django_question(问题表)
django_choice(投票记录表)
我们启动服务,打开浏览器http://127.0.0.1:8000/polls/1/,可以看到简单的投票页面
投票详情页面
当polls/templates/polls/detail.html页面完善后,打开页面看到上图,但是我们点投票的时候并没有做视图相关的业务处理,我们看看detail.html中submit提交的接口为{% url 'polls:vote' question.id %}这个翻译过来假如question.id=1那么这个地址就是/polls/1/vote,但是我们vote视图处理目前还是如下代码
def vote(request, question_id):
return HttpResponse("进行投票 %s." % question_id)
并没有实现投票的业务逻辑,现在我们稍微来改造下这个方法如下
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Question, Choice
# ...为了让文章篇幅更短,此处省略其他方法
def vote(request, question_id):
question=get_object_or_404(Question, pk=question_id)
try:
selected_choice=question.choice_set.get(pk=request.POST['choice'])
except(KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {'question': question, 'error_message': '你没有选择一个选项'})
else:
selected_choice.votes +=1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
代码讲解
404
说到这里,我们就还需要编辑重定向后的视图以及界面,重定向后的视图编码为
更改前:
#问题结果页
def results(request, question_id):
return HttpResponse("查看问题的结果 %s." % question_id)
更改后:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Question, Choice
# ...为了让文章篇幅更短,此处省略其他方法
def results(request, question_id):
question=get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
我们还需要新增polls/templates/polls/results.html界面,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>投票结果</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' question.id %}">再次投票?</a>
</body>
</html>
编辑完成后,现在我们打开地址:http://127.0.0.1:8000/polls/1/ 选择任意一个选项,点击"投票"按钮,就会展示如下结果:
点击再次投票,再跳转到投票详情页面,反复执行,将会看到投票数的变化
在使用通用视图之前,我们先了解下通用视图的定义,通用意思是重复用,避免重复造轮子,通用视图旨在将常见的模式抽象化,可以使你在编写应用时甚至不需要编写Python代码。
既然说是通用视图,那么我们先来改造视图,先直接贴出最终代码:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.views import generic
from .models import Question, Choice
# Create your views here.
class IndexView(generic.ListView):
template_name='polls/index.html'
context_object_name='latest_question_list'
def get_queryset(self):
return Question.objects.order_by("-pub_date")[:5]
class DetailView(generic.DetailView):
model=Question
template_name='polls/detail.html'
class ResultsView(generic.DetailView):
model=Question
template_name='polls/results.html'
def vote(request, question_id):
question=get_object_or_404(Question, pk=question_id)
try:
selected_choice=question.choice_set.get(pk=request.POST['choice'])
except(KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {'question': question, 'error_message': '你没有选择一个选项'})
else:
selected_choice.votes +=1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
我们会看到index(),detail(),results()方法已经都被删除,而新增的有类IndexView,DetailView,ResultsView,下面我们来讲讲这些变化的地方
新增类IndexView继承generic.ListView,其中属性template_name,context_object_name都进行重写,默认情况下ListView会生成模板<app_name>/<model_name>_list.html,app_name则是我们URLconf(polls/urls.py文件)中的变量,mode_name则是Question,那么默认的模板名字则是"polls/question_list.html",而我们重写template_name值,则会直接拿重写后的值也就是"polls/index.html",而context_object_name我们需要重写则是因为我们html模板需要用到该属性,以免报错
DetailView和ResultsView我就挑DetailView描述下,两个实现原理其实都差不多,这个需要结合改造后的URLconf(polls/url.py)来讲,URLconf改造如下:
改造前:
from django.urls import path
from . import views
app_name='polls'
urlpatterns=[
path('', views.index, name='index'),#问题列表页
path('<int:question_id>/', views.detail, name='detail'),#问题详情页
path('<int:question_id>/results/', views.results, name='results'),#问题结果页
path('<int:question_id>/vote/', views.vote, name='vote'),#投票处理器
]
改造后:
from django.urls import path
from . import views
app_name='polls'
urlpatterns=[
path('', views.IndexView.as_view(), name='index'),#问题列表页
path('<int:pk>/', views.DetailView.as_view(), name='detail'),#问题详情页
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),#问题结果页
path('<int:question_id>/vote/', views.vote, name='vote'),#投票处理器
]
其中列表页,详情页,结果页都已经更改,question_id更改为pk,而这个pk则代表数据库表的主键ID,当我们访问详情页(DetailView)时,传入主键ID,模板就能渲染相关数据,而DetailView的父类generic.DetailView默认的模板地址生成为<app_name>/<model_name>_detail.html,那么就可能变成"polls/question_detail.html",但是该模板页面我们并没有开发,所以我们重写了model以及template_name属性,最终会生成为"polls/detail.html"
现在让我们重新打开http://127.0.0.1:8000/polls/1/看看通用视图是否生效吧
下一篇:Python之Django系列-创建第一个应用-7
构建功能完备且用户体验良好的Web应用时,表单验证是一个不可或缺的部分。本文将深入探讨如何使用 Flask 框架集成的 flask-wtf 库实现网页表单验证,并提供详细的代码示例以助您快速掌握这一实用技能。
flask-wtf 是 Flask 用于处理 Web 表单的一个扩展库,它基于 wtforms 库,提供了便捷的方式来创建和验证 HTML 表单。通过 Flask-wtf,您可以轻松定义表单字段、编写验证规则并处理提交的数据。
首先确保已安装 flask-wtf:
pip install Flask-WTF
在 Flask 应用中引入并初始化 flask-wtf:
from flask import Flask
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, EqualTo
app=Flask(__name__)
app.config['SECRET_KEY']='your-secret-key' # 设置一个安全密钥用于表单验证
下面是一个用户注册表单的示例,包含用户名、密码以及确认密码字段,其中包含了数据必填性、长度限制以及密码匹配等验证规则:
class RegistrationForm(FlaskForm):
username=StringField('用户名', validators=[DataRequired(), Length(min=2, max=20)])
password=PasswordField('密码', validators=[DataRequired()])
confirm_password=PasswordField('确认密码',
validators=[DataRequired(), EqualTo('password', message='两次密码不一致')])
submit=SubmitField('Sign Up')
在视图函数中,我们可以实例化表单对象,渲染表单至模板,并处理表单提交后的验证结果:
@app.route('/register', methods=['GET', 'POST'])
def register():
form=RegistrationForm()
if form.validate_on_submit(): # 验证表单数据
# 这里是处理有效表单数据的逻辑,例如保存到数据库
flash('用户注册成功!', 'success')
return redirect(url_for('index'))
return render_template('register.html', title='Register', form=form)
在 Jinja2 模板文件(如 templates/register.html)中,我们可以渲染表单:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>用户注册</h1>
<form method="POST" action="{{ url_for('register') }}">
{{ form.csrf_token }} <!-- 添加CSRF令牌 -->
<div>
{{ form.username.label }}<br>
{{ form.username(size=20) }}
</div>
<div>
{{ form.password.label }}<br>
{{ form.password() }}
</div>
<div>
{{ form.confirm_password.label }}<br>
{{ form.confirm_password() }}
</div>
<div>
{{ form.submit() }}
</div>
</form>
</body>
</html>
通过以上步骤,我们成功地在 Flask 应用中使用了 flask-wtf 实现了一个具有验证功能的用户注册表单。
当表单验证失败时(form.validate_on_submit()返回False),flask-wtf会将验证错误信息存储在表单对象中。我们可以在模板中遍历这些错误并显示给用户:
<!-- 在templates/register.html中添加错误信息显示 -->
{% for field, errors in form.errors.items() %}
{% for error in errors %}
<p style="color: red;">{{ form[field].label }}: {{ error }}</p>
{% endfor %}
{% endfor %}
在某些情况下,您可能需要为特定字段或验证器提供自定义错误消息。这可以通过在定义表单类时直接指定验证器的message参数来实现:
from wtforms import ValidationError
class RegistrationForm(FlaskForm):
# ...
def validate_username(self, username_field):
if User.query.filter_by(username=username_field.data).first():
raise ValidationError('Username already exists. Please choose another one.')
通过flask-wtf,我们可以高效且规范地管理Web应用中的表单验证和数据处理流程。结合wtforms强大的验证器库,您可以根据需求创建各种复杂度的表单,并确保用户的输入满足预设的业务规则。
实践是检验真理的唯一标准,鼓励各位读者在实际项目开发中尝试运用flask-wtf进行表单验证,不断优化和完善代码逻辑,从而提升Python Web开发的能力和效率。
关注我,手把手带你快速入门Python Web编程!
*请认真填写需求信息,我们会在24小时内与您取得联系。