当前位置: 首页 > news >正文

深圳公司有哪些东莞关键词优化外包

深圳公司有哪些,东莞关键词优化外包,做动态在网站需要学什么,梧州论坛 红豆社区一、Django 项目单元 集成测试准备 #x1f447;依赖安装#xff08;给项目装 “测试小帮手”#x1f37c;#xff09;pdm add -d black isort flake8 pytest pytest-django pytest-coverage #x1f449; 这行命令像在给项目 “采购” 测试工具#xff1a;black …一、Django 项目单元 集成测试准备 依赖安装给项目装 “测试小帮手” pdm add -d black isort flake8 pytest pytest-django pytest-coverage 这行命令像在给项目 “采购” 测试工具black ✨ 自动格式化代码让代码整齐得像排好队的小士兵isort  帮你把 import 语句整理得明明白白flake8  像代码 “小侦探”揪出语法和风格问题pytest  单元测试 “大主角”跑测试用例超好用pytest-django  让 pytest 能和 Django 好好 “交朋友”测试 Django 项目pytest-coverage  看看测试覆盖了多少代码心里有底 配置文件给工具们定 “小规矩”1. .flake8flake8 的 “小手册” [flake8] exclude venv # 告诉 flake8 别去碰 venv 文件夹 extend-ignore E501 # 放宽点啦忽略行太长的报错E501 2. pytest.inipytest 的 “剧本” [pytest] DJANGO_SETTINGS_MODULE Tesla.settings # 告诉 pytest 用哪个 Django 配置⚙️ python_files tests.py test_*.py # 哪些文件算测试文件呀找 tests.py 和 test_开头的 测试用例给项目 “模拟闯关”根据我们的业务逻辑代码进行分析~ 1. 注册功能 允许匿名访问 游客也能注册URLhttp://127.0.0.1:8000/accounts/register GET返回 HTML 页面像打开注册 “小窗口”️POST提交 JSON 数据还要验证用户名不能为空 ❌空用户名像没名字的小幽灵不行密码不能为空 ❌没密码咋保护自己两次密码得一样 不然自己都记混啦密码长度≥6 位 太短不安全呀用户名不能重复 不能撞名呀都对的话返回 “注册成功” 2. 登录功能 允许匿名访问 游客也能登录页逛逛URLhttp://127.0.0.1:8000/accounts/login/ GET返回登录 HTML 页面 ️POST提交表单还要验证用户名不能为空 ❌没用户名咋找账号密码不能为空 ❌没密码进不去呀用户名、密码得对 ✅不然进错家门啦 3. 提交反馈 不允许匿名访问 得登录才能反馈URLhttp://127.0.0.1:8000/beifan/submit GET返回 HTML 页面 ️POST提交 JSON 数据还要验证数据能存到数据库里 ️像把信放进邮箱数据和用户关联上 谁发的反馈要记好同一用户不能重复发 别刷屏呀4. 反馈结果 允许匿名访问 谁都能看看结果URLhttp://127.0.0.1:8000/beifan/result 不管 GET/POST都返回 HTML 页面 ️看看反馈结果啥样二、HttpResponse数据结构角度HttpResponse类定义了一系列属性和方法来管理响应相关的数据。属性方面content以字节串形式存储响应的主体内容比如返回的 HTML 页面内容、JSON 数据经过编码后的字节串等。例如返回一个简单 HTML 页面这个 HTML 文本内容最终会编码后存到content中。status_code记录 HTTP 响应状态码像常见的200请求成功、404页面未找到、500服务器内部错误等通过这个属性可以让客户端快速知晓请求处理的结果状态。headers是一个类似字典的数据结构用来存放 HTTP 响应头信息比如Content - Type指定响应内容的类型像text/html表示 HTML 页面application/json表示 JSON 数据、Content - Length响应内容的长度等。方法方面它提供了一些方法来操作响应数据比如__setitem__方法可以像操作字典一样response[key] value用于设置响应头信息。 面向对象角度HttpResponse类遵循面向对象编程范式通过封装、继承和多态等特性来实现对 HTTP 响应的管理和扩展封装把与 HTTP 响应相关的各种信息内容、状态码、响应头和操作设置响应头、获取内容等封装在一个类中提供了统一且便捷的接口来处理响应。比如在视图函数中只需要创建HttpResponse实例并设置相关属性就能轻松构建一个完整的 HTTP 响应。继承Django 提供了一些HttpResponse的子类如HttpResponseRedirect用于重定向默认状态码为302、JsonResponse专门用于返回 JSON 数据自动设置Content - Type为application/json  。这些子类继承了HttpResponse的基本属性和方法并根据自身功能需求进行了扩展和定制。多态在 Django 的视图函数返回机制中无论是返回HttpResponse对象还是它的子类对象都遵循统一的规则都被视为合法的响应返回值这体现了多态性。视图函数根据业务逻辑的不同灵活返回不同类型的响应对象而 Django 的请求处理机制都能正确处理并发送给客户端。 Web 开发流程角度在 Django 应用处理 HTTP 请求的流程中HttpResponse是请求处理结果的最终承载者当客户端发起一个 HTTP 请求到 Django 服务器Django 会根据 URL 配置找到对应的视图函数进行处理。视图函数在处理完业务逻辑如查询数据库、进行数据计算等后需要构建一个响应返回给客户端此时就会创建HttpResponse对象或者它的子类对象将处理结果填充到响应对象的相关属性中如设置响应内容、状态码、响应头。最后Django 的请求处理机制会将这个HttpResponse对象转换为符合 HTTP 协议规范的格式通过网络发送给客户端客户端再根据响应信息进行相应的展示或处理如浏览器渲染 HTML 页面、解析 JSON 数据等 。总之HttpResponse类是 Django 构建和管理 HTTP 响应的核心组件通过数据结构、面向对象编程以及在 Web 开发流程中的关键作用实现了从服务器端到客户端的响应信息传递。三、测试HTTP请求 先测试一个简单的登录视图的get请求返回一个html页面 from django.test.client import Clientimport pytestpytest.fixture def client() - Client:return Client()def test_register_get(client: Client):resp: HttpResponse client.get(/accounts/register)assert resp.status_code 200html resp.content.decode()assert html in htmlassert 用户名 in htmlassert 密码 in htmlassert 确认密码 in html 1. 引入工具from django.test.client import Client 作用从 Django 测试工具里把「发 HTTP 请求的小助手 Client」请进来为啥 Django 专门给咱准备了 Client 类用来模拟浏览器发请求比如 GET、POST测试咱的视图函数 / 接口。就像给代码一个 “虚拟小浏览器”不用真的开浏览器也能测试网页 / 接口响不响应 2. fixture 魔法pytest.fixture  def client() - Client: pytest.fixture def client() - Client: return Client() 作用用 pytest 的 fixture创建一个可复用的 “发请求工具”叫 client为啥这么写pytest.fixture 是 pytest 的 “魔法标记”标记后这个 client 函数就变成了一个 “工具工厂”其他测试函数要用的时候直接当参数传进去就行return Client()每次调用 client都会新建一个 Client 实例也就是新的 “虚拟小浏览器”保证测试之间互不干扰 3. 测试用例def test_register_get(client: Client): 作用定义一个测试用例名字叫 test_register_get专门测试注册页面的 GET 请求为啥参数是 client: Client 因为上面用 pytest.fixture 标记了 clientpytest 会自动把 Client 实例传进来供这个测试用例使用相当于 “自动给你递上小浏览器不用自己手动创建啦” 4. 发请求resp: HttpResponse client.get(/accounts/register) 作用用 client虚拟小浏览器发一个 GET 请求 到 /accounts/register注册页面的 URL然后把服务器返回的响应存到 resp 里为啥这么写 模拟用户在浏览器里输入 http://.../accounts/register 访问注册页的行为。client.get(...) 就是帮我们发 GET 请求的 “快捷方式”不用真的启动浏览器 5. 断言状态码assert resp.status_code 200 作用检查服务器返回的状态码是不是 200200 代表 “请求成功”网页正常返回啦为啥要断言 测试的核心如果状态码不是 200比如 404 找不到页面、500 服务器报错说明注册页面可能有问题测试就会 “失败”提醒咱去修 6. 解析响应内容html resp.content.decode() 作用把响应的二进制内容resp.content转换成字符串decode() 解码方便后面检查页面里有没有我们要的内容为啥要解码网络编程发送和接收网络数据包的HttpResponse是字节流二进制数据。 resp.content 存的是二进制数据像 bhtml...转成字符串html后才能用字符串的方法比如 in 关键字检查内容 7. 检查页面内容一堆 assert assert html in html assert 用户名 in html assert 密码 in html assert 确认密码 in html 作用确认返回的 HTML 里包含 “html”“用户名”“密码”“确认密码” 这些关键字为啥要检查 保证注册页面的 HTML 里确实有这些表单字段用户名、密码输入框。如果哪天代码不小心把这些字段删了测试就会失败提醒咱 “注册页面不对啦” 四、测试DB数据库   user fixture —— 提前造个 “测试用户” pytest.fixture() def user(_django_db_helper): new_user User.objects.create_user( usernametest_user, emailtest_userqq.com, passwordtest_user_pass, ) return new_user 逐行拆解pytest.fixture()pytest 的 “魔法标记”标记后user 就变成一个可复用的 “工具函数”其他测试用例要用时直接传参即可作用提前帮你在数据库里造一个测试用户不用每次测试都手动创建啦def user(_django_db_helper):_django_db_helper 是 pytest-django 提供的 “数据库小助手”会自动帮你初始化、清理数据库保证测试间互不干扰函数名 user 是你给这个 “造用户工具” 起的名字方便其他测试用例调用new_user User.objects.create_user(...)调用 Django 的 create_user 方法在数据库里实际创建一个用户用户名、邮箱、密码都是测试用的假数据相当于“嘿数据库 帮我塞一条用户数据测试时要用”return new_user把刚创建的用户对象返回其他测试用例如果用了这个 user fixture就能直接拿到这个 “测试用户” 啦  参数化测试 —— 批量测 “注册场景”这部分是用 pytest.mark.parametrize 批量测试不同注册情况用户名空、密码不一致、注册成功等超高效 pytest.mark.parametrize( data, code, msg, [ ({username: }, -1, username 不能为空), # 用户名空 ({password_confirm: 2}, -2, 两次密码输入不一致), # 密码不一致 ({username: test_user_beifan}, 0, 注册成功), # 注册成功 ] ) def test_register_post(user, client, data, code, msg): # 发 POST 请求测试注册 resp client.post( /accounts/register, datadata, content_typeapplication/json ) # 解析响应 html resp.content.decode() resp_json json.loads(html) # 断言响应是否符合预期 assert resp_json[code] code assert resp_json[msg] msg 这里的data有简化省略了其他的键值对 逐行拆解pytest.mark.parametrize(data, code, msg, [...])pytest 的 “参数化魔法”括号里的 data, code, msg 是 “参数名”后面的列表是 “参数值组合”。作用批量生成测试用例列表里每一个元组都会对应一条测试用例 比如第 1 组data 是 {username: }用户名空预期 code-1msgusername 不能为空第 2 组data 是 {password_confirm: 2}密码不一致预期 code-2msg两次密码输入不一致第 3 组data 是 {username: test_user_beifan}合法数据预期 code0msg注册成功def test_register_post(user, client, data, code, msg):测试用例函数参数里user就是图 1 里的 user fixture会自动传入 “测试用户”如果需要的话clientDjango 测试客户端图 1 里讲过的 “虚拟小浏览器”data, code, msg来自 pytest.mark.parametrize 的参数每组数据都会跑一次测试resp client.post(...)用 client虚拟小浏览器发一个 POST 请求 到 /accounts/register注册接口还带了 data请求体和 content_typeapplication/json告诉服务器我发的是 JSON 数据哟html resp.content.decode() → resp_json json.loads(html)把响应的二进制内容resp.content解码成字符串html再转成 JSONresp_json方便断言assert resp_json[code] code → assert resp_json[msg] msg检查响应的 code 和 msg 是否符合预期 比如用户名空时code 应该是 -1msg 是 username 不能为空注册成功时code 是 0msg 是 注册成功  数据库断言 —— 注册成功后用户真的 “入库” 了吗这部分是测试 “注册成功后数据库用户数量是否变化”保证代码真的把用户数据存到数据库啦 def test_register_post(user, client, data, code, msg): # 1. 发请求前先查数据库用户数量 user_list list(User.objects.all()) user_count len(user_list) assert user_count 1 # 假设测试前只有 1 个用户图 1 里的 test_user # 2. 发 POST 请求测试注册 resp client.post(...) # 和之前一样发请求、解析响应 # 3. 断言响应是否符合预期code、msg assert resp_json[code] code assert resp_json[msg] msg # 4. 如果注册成功code 0再查数据库用户数量 if code 0: user_list list(User.objects.all()) user_count len(user_list) assert user_count 2 # 注册成功后应该新增 1 个用户 → 总数 2 逐行拆解user_list list(User.objects.all()) → user_count len(user_list)发请求前先查数据库里的所有用户数一下有多少个user_count。假设测试环境里一开始只有图 1 里创建的 test_user所以 user_count 1。assert user_count 1确保测试前数据库状态 “干净”只有 1 个测试用户避免其他数据干扰测试结果if code 0:code 0 代表 “注册成功”这时需要再查数据库确认用户真的新增了user_list list(User.objects.all()) → user_count len(user_list)发请求后再次查数据库用户数量。assert user_count 2注册成功的话用户数量应该从 1 变成 2原来的 test_user  新注册的用户。相当于“嘿数据库 注册成功后用户是不是真的存进来啦数量对不对呀”  整体流程总结造用户用 pytest.fixture 提前在数据库造一个 test_user当 “测试种子”。批量测注册用 pytest.mark.parametrize 批量测试各种注册场景用户名空、密码错、注册成功。发请求用 client.post 模拟浏览器发注册请求看服务器咋响应。断言响应检查返回的 code 和 msg 是否符合预期比如注册成功时 code0。数据库校验注册成功后再查数据库用户数量确保真的新增了用户user 固件也就是说意义在于数据库的初始化管理 和 验证是否用户名重复1. ️ 帮数据库 “热热身”user fixture 里的 User.objects.create_user(...) 一执行就像给数据库发了条消息“喂 准备好啦要开始测试咯” Django 会因此自动完成数据库连接、创建测试表等一系列准备工作避免测试时出现 “数据库还没启动” 的尴尬错误 就像玩游戏前先加载地图不然点 “开始” 会卡住呀 2. 提供 “参照物” 方便验证比如测试 “用户名不能重复” 时user 就像一个 “标杆用户”它的用户名是 test_user已经存在于数据库里先建一个user数据,所以后面的断言是1-2当你用同样的用户名 test_user 去注册时就能验证系统会不会报错 “用户名已存在”如果没有这个 “参照物”数据库空空如也根本测不出 “重复注册” 的逻辑对不对呀所以哪怕 user 没在代码里被直接 “点名”它也是测试里的 “幕后功臣”既让数据库准备好工作又提供了关键的 “对比数据”保证各种注册场景都能被准确测试到 Django 测试中通过 user fixture 自动完成数据库连接的过程  第一步pytest-django 的 “数据库开关”user fixture 里有 User.objects.create_user(...) 这行代码 —— 它要往数据库里写数据这就像给 pytest-django 递了一张 “需要数据库” 的门票。pytest-django 看到这张 “门票” 后会自动触发一个核心机制启用数据库连接。 如果测试里完全用不到数据库操作pytest-django 会默认 “关闭” 数据库让测试跑得更快 ️ 第二步创建 “临时测试数据库”为了不污染你的真实数据库比如开发环境的 db.sqlite3pytest-django 会偷偷做一件事 自动创建一个全新的临时数据库名字通常是 test_你的数据库名比如 test_myproject。这个临时数据库就像一个 “一次性舞台”结构和你的真实数据库一模一样表、字段都照着抄但里面的数据是干净的专门给测试用测试结束后会自动删除不会留下任何痕迹  第三步自动连接到临时数据库Django 的核心配置里有 DATABASES 选项在 settings.py 里比如 DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, # 真实数据库 } } 当 pytest-django 检测到需要数据库时会自动 “替换” 这个配置 把 NAME 改成临时数据库的路径比如 test_db.sqlite3然后调用 Django 内置的 connection 模块建立和这个临时数据库的连接。这一步就像 你本来要去 “正式餐厅”真实数据库但测试时被悄悄引导到了 “隔壁的临时分店”临时数据库地址变了但进门的方式连接方式完全一样  第四步自动执行数据库迁移连接好临时数据库后pytest-django 还会自动做一件事 运行所有 migrations数据迁移文件确保临时数据库的表结构和你的项目代码完全同步。就像 临时舞台搭好了但还得按设计图migrations 文件摆好桌椅数据表演员测试数据才能上场  总结user fixture 触发的 “全自动流程”user fixture 里的 User.objects.create_user() 触发 “需要数据库” 的信号pytest-django 接收到信号创建临时数据库自动修改数据库配置连接到临时数据库自动运行迁移确保表结构正确执行 create_user往临时数据库里写入测试用户数据整个过程完全自动不需要你手动写 connect() 或 create_database() 之类的代码 就像点外卖时平台自动帮你完成 “找餐厅、下单、配送”你只需要等着吃写测试就行啦  为什么resp client.post(...) 就能把提交的data放到数据库里呢 第一步client.post(...) 是 “发件人”️ 第二步Django 路由 “指路” 第三步视图函数 “处理包裹”register_view 视图函数会打开包裹data做一系列操作检查数据比如看看用户名是不是空的、密码够不够长就像快递员检查包裹是否违禁品创建用户如果数据没问题就会调用 User.objects.create_user(...)Django 的 ORM 方法把 data 里的用户名、密码等信息 “翻译” 成数据库能懂的语言SQL 语句。 第四步ORM 当 “翻译官”把数据存进数据库Django 的 ORM对象关系映射是个超厉害的 “翻译官”你写的 User.objects.create_user(username小明)它会自动翻译成 SQL 语句INSERT INTO auth_user (username, password) VALUES (小明, 加密后的密码)然后通过之前 user fixture 已经建好的数据库连接把这条 SQL 发给临时数据库执行。数据库收到指令后就会在 auth_user 表用户表里新增一行记录 —— 你的 data 就这样成功 “住进” 数据库啦 那没有user这个固件了 直接resp client.post(...) 能不能连接上数据库哈哈这个问题就像在问“如果没有提前打开厨房门能直接炒菜吗” 答案是 ——大部分情况会失败用超萌的例子解释假设 user fixture 是 “提前打开厨房门的人”而 client.post(...) 是 “炒菜的动作”  情况 1如果你的 post 请求需要操作数据库比如注册用户这时候必须先有 “可用的厨房”数据库连接否则炒不了菜没有 user fixturepytest-django 可能会 “偷懒” 不初始化数据库因为没收到 “需要数据库” 的信号。当 client.post(...) 触发视图函数去写数据库时会发现 “厨房门没开”数据库没连接直接报错DatabaseError 或 “表不存在” 之类的错误就像没开煤气就想炒菜锅是冷的根本炒不熟呀  情况 2如果你的 post 请求完全不碰数据库比如只是返回固定文本比如视图函数只是返回 {code:0}不读写数据库那就算没有 user fixtureclient.post(...) 也能正常运行这就像 “凉拌菜”不需要开火数据库直接拌一拌就能吃  关键结论client.post(...) 本身不会主动触发数据库连接它只是发请求的 “快递员”。 是否能连接数据库取决于测试中有没有其他触发数据库初始化的操作比如 user fixture 里的 User.objects.create_user。如果你的 post 请求需要操作数据库最好还是带上 user fixture 或其他 “数据库触发器”比如 django_db fixture确保 “厨房门是开着的” 哦  可是resp client.post(...) 的后端视图处理不是有创建User.objects.create_user的代码吗 为啥不能执行到这里的时候开始初始化数据库这个问题超棒就像在问“既然炒菜时会用到煤气为啥不能在炒菜时再开煤气呢” 这里藏着一个 “先后顺序” 的小秘密   核心原因“煤气”数据库连接必须在 “点火”执行代码前打开Django 测试中数据库初始化连接、创建临时表等是 **“提前准备工作”必须在任何数据库操作代码比如 User.objects.create_user执行之前 ** 完成。而 client.post(...) 触发的视图函数里的 create_user属于 “测试过程中才会执行的代码”—— 就像 “点火炒菜” 这个动作必须在 “煤气已经打开” 之后才能进行。  具体流程对比有 user fixture 时测试开始前user fixture 先执行 User.objects.create_user → 触发数据库初始化开煤气测试进行中client.post(...) 触发视图函数 → 执行 create_user点火炒菜→ 顺利执行煤气已开没有 user fixture 时测试开始前没有任何数据库操作 → pytest-django 认为 “不需要数据库”→ 不初始化没开煤气测试进行中client.post(...) 触发视图函数 → 执行 create_user想点火炒菜→ 发现 “煤气没开”数据库未初始化→ 报错 ️ pytest-django 的 “小规矩”pytest-django 有个 “懒加载” 原则只有在测试开始前检测到 “明确需要数据库” 的信号比如 fixture 里有数据库操作才会提前初始化数据库。而视图函数里的 create_user 是 “测试运行到一半才执行的代码”这时候再想初始化数据库已经太晚了 —— 就像炒菜炒到一半才发现没开煤气火根本点不着呀  解决办法给测试 “明确开煤气”如果不想用 user fixture也可以用 pytest-django 提供的 django_db fixture直接告诉 pytest“我要用到数据库麻烦提前准备好哦” # 不用 user fixture改用 django_db fixture def test_register_post(client, django_db, data, code, msg): resp client.post(/accounts/register, datadata) # 此时数据库已提前初始化 # ... 后续断言 ... django_db 就像一个 “备用煤气开关”专门负责在测试前打开数据库连接可是不做单元测试 我只做开发的话视图User.objects.create_user前也没有什么启动数据库的操作啊在实际开发中情况和测试环境完全不同就像 “家里做饭” 和 “野外露营做饭” 的区别 —— 家里的煤气灶是长期打开、随时可用的而露营时需要提前手动生火  开发环境中数据库连接是 “自动提前就绪” 的在开发阶段当你启动 Django 项目比如 python manage.py runserver时Django 会自动完成一系列 “初始化工作”其中就包括数据库连接的建立根本不需要你手动写代码 “启动数据库”。具体来说Django 会读取 settings.py 里的数据库配置DATABASES 字典比如数据库类型MySQL/PostgreSQL、地址、用户名密码等。启动时自动创建数据库连接池保持和数据库的 “长期通话” 状态。检查数据库表结构如果用了 migrate 迁移确保表已经存在。这就像你家里的煤气灶只要插上电、打开总开关随时拧旋钮就能点火 ——数据库连接在项目启动时就已经 “待命” 了。  所以视图里的 User.objects.create_user 能直接执行当用户在浏览器里提交表单或者你用 Postman 发请求触发视图函数里的 User.objects.create_user 时Django 已经通过启动时建立的数据库连接把 ORM 代码create_user翻译成 SQL。直接通过现成的连接发给数据库执行根本不需要 “临时启动数据库”。这和测试环境的区别在于开发环境项目启动时强制初始化数据库连接因为 runserver 命令默认需要数据库支持。测试环境pytest为了效率默认不初始化数据库只有明确告诉它 “要用数据库”比如用 django_db fixture才会提前准备。  总结开发时 “无需手动启动” 的核心原因Django 的 runserver 命令在启动项目时会自动根据 settings.py 的配置完成数据库连接初始化相当于 “项目一启动数据库就处于‘开机待命’状态”。
http://www.pierceye.com/news/264880/

相关文章:

  • 到国外建网站自己做的视频发什么网站吗
  • 高校网站平台建设快速网站排名
  • seo技术 如何优化网站内部结构用ps做网站方法
  • vi设计公司网站python做网站好处
  • 北京专业网站建设服务商枣庄建设工程管理局网站
  • 百度移动网站提交深圳做网站的好公司
  • 十大在线编程网站旅游营销型网站
  • 微转app是用网站做的吗win10运行wordpress
  • 微网站建设哪里便宜网站做的跟别人的一样可以吗
  • 合肥优化网站福州网站设计
  • 企业网站制作前期需要什么资料网站 月15g流量够用吗
  • 网络营销网站建设ppt环艺做网站
  • 手机建设银行官方网站网站开发要点
  • 做简历的网站有随州网站建设学校
  • 深圳建设网站企业青白江做网站的公司
  • dm网站制作软件无忧网站建设
  • 如何在自己的网站上做歌单王建设医生网站
  • 科技+杭州+网站建设做效果图的网站有哪些
  • 引流推广网站平台wordpress页面发布失败
  • 南京哪家网站建设好网站开发需要注意的
  • 一个综合网站上线多少钱wordpress粘贴word
  • 承接电商网站建设新手做自己的网站
  • 网页版视频网站建设需要多少钱四川鸿业建设集团公司网站
  • h5网站实例wordpress改造mip
  • 完整的网络营销推广方案包括优化营商环境心得体会个人
  • 商洛市住房和城乡建设局网站建免费网站
  • 做网站要多少的服务器网站设计的步骤
  • 网站关键词怎么做上首页wordpress 架构原理
  • 厦门专业网站建设代理国外在线crm系统suitecrm
  • 哪个网站可以领手工活在家做wordpress heroku