个人技术分享

  • 首页
  • 关于
  • 主题
  • 影视解析
  • 音乐
  • 归档
  • 留言
个人技术分享
  • 首页
  • 关于
  • 主题
  • 影视解析
  • 音乐
  • 归档
  • 留言
个人技术分享
刷新页面会随机【个人信息流样式】

28

文章

103

获赞

231

评论

7.7万+

浏览
世界那么大,我想去看看。但钱包那么小,哪也去不了。所以,珍惜当下,享受生活。
30岁 IP: 杭州 家里蹲大学
  • 首页
  • 关于
  • 主题
  • 影视解析
  • 音乐
  • 归档
  • 留言
hanhanjun888@163.com

个人技术分享

解决移动设备上的所有浏览器顶部都有地址栏,导致高度问题
解决此问题的最佳方法是什么。显然,移动设备上的所有浏览器顶部都有一个 UI(地址栏等)。这为视口增加了额外的高度,因此我使用 100vh 的网站缺少一个部分。 因此,我假设不同的浏览器具有不同大小的视口,我可以简单地执行类似 height: calc(100vh - 50px) 之类的操作,或者高度是多少,但它不会在所有移动浏览器上匹配,对吧?
//通常 100vh 高度将解释调整后的高度,这就是为什么当浏览器的地址栏向下滑动时有时您会看到移动页面变得时髦的原因。
//对于不考虑 vh 单元中的滑动条的浏览器:地址栏的高度在浏览器中不会保持不变,所以我建议不要附加 -50px .
//尝试使用 window.innerheight 属性设置页面的高度(使用 javascript)。
function adjustHeight() {
    // alert("宽度:"+window.innerWidth+"高度:"+ window.innerHeight)
    var vh = window.innerHeight;
    document.getElementById('messageContent').style.height = (vh - 50) + 'px'; // 假设地址栏高度大约为50px
}
window.addEventListener('resize', adjustHeight);
window.addEventListener('load', adjustHeight);

1年前
赞 评论
评论(0)

暂无数据

取消回复

hanhanjun888@163.com

个人技术分享

Python框架 Flask和Django - 区别
  • Django功能大而全,Flask只包含基本的配置 Django的一站式解决的思路,能让开发者不用在开发之前就在选择应用的基础设施上花费大量时间。Django有模板,表单,路由,认证,基本的数据库管理等等内建功能。与之相反,Flask只是一个内核,默认依赖于两个外部库: Jinja2 模板引擎和 Werkzeug WSGI 工具集,其他很多功能都是以扩展的形式进行嵌入使用。
  • Flask 比 Django 更灵活 用Flask来构建应用之前,选择组件的时候会给开发者带来更多的灵活性 ,可能有的应用场景不适合使用一个标准的ORM(Object-Relational Mapping 对象关联映射),或者需要与不同的工作流和模板系统交互。
  • Flask 在 Django 之后发布,现阶段有大量的插件和扩展满足不同需要 Django发布于2005年,Flask创始于2010年年中。

Warning: Undefined array key 1 in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/wx-excerpt.php on line 53

Warning: Undefined array key 1 in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/wx-excerpt.php on line 53

Warning: Undefined array key 1 in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/wx-excerpt.php on line 53
Python测试开发中Django和Flask框架 为了更好地阐述这个问题,我们把开发一个应用的过程进行类比,往往开发一个应用(web应用、系统应用)跟建造房子的过程一样,需要先打地基,搭好骨架,然后一块砖一块砖叠上去。 而开发一个应用呢? 同样也需要一个好的架构设计,数据库建模,然后一个模块一个模块使用代码实现。 如果开发一个软件应用不使用框架,和我们建房子时,每一块砖、每一根钢筋都需要自己生产出来本质上是一样的。 显而易见,如果在建造房子之前,每一块砖头、每一种建材,都需要我们自己去生产的话,建造房子的效率是极低的,甚至可能一辈子也无法把房子建造好。 在开发应用系统时,使用框架可以带来如下好处: **1、**大大提升开发效率; **2、**让应用开发更加规范、拓展性更强; **3、**让程序员把更多的精力放在业务逻辑的实现上,而不是重复、而复杂的基础环境上(比如web服务器、底层实现等); 二、为什么使用Django和Flask框架?   1、在Python编程语言的世界里,功能最强大、最流行的两个框架。 2、不仅在web后端开发、微服务开发,同时在ERP系统开发、API接口开发等领域,这两个框架应用非常广泛。 三、Django和Flask的区别 ◆ 形象类比 如果Django类似于精装修的房子,自带豪华家具、非常齐全功能强大的家电,什么都有了,拎包入住即可,十分方便。 而Flask类似于毛坯房,自己想把房子装修成什么样自己找材料,买家具自己装。 材料和家具种类非常丰富,并且都是现成免费的,直接拿过去用即可。 ◆ 在体量上的区别 Flask:小巧、灵活,让程序员自己决定定制哪些功能,非常适用于小型网站。 对于普通的工人来说将毛坯房装修为城市综合体还是很麻烦的,使用Flask来开发大型网站也一样,开发的难度较大,代码架构需要自己设计,开发成本取决于开发者的能力和经验。 Django:大而全,功能极其强大,是Python web框架的先驱,用户多,第三方库极其丰富。 非常适合企业级网站的开发,但是对于小型的微服务来说,总有“杀鸡焉有宰牛刀”的感觉,体量较大,非常臃肿,定制化程度没有Flask高,也没有Flask那么灵活。 ◆ 实例 使用Flask来完成: 第一步,安装Flask,pip install flask 第二步,创建my_first_app.py文件,添加如下代码 完成最简单的Hello World功能,Flask只需要7行代码,非常简单、方便。 使用Django来完成: 第一步,安装Django,pip install django 第二步,创建工程项目目录,django-admin startprojectmyproject 第三步,创建子应用,python manage.py startappmyapp 第四步,在myapp应用所在目录中的views.py文件中,添加如下代码。 第五步,在myapp应用所在目录中创建urls.py路由文件,并添加如下代码 第六步,在主路由文件中添加路由。 从上面的操作步骤可知,实现同样的一个功能,往往Flask较为简单,代码较少,而Django所涉及到的流程较多,工程项目结构清晰,在大型项目中具有优势。 如果你想搞懂Python web开发WSGI协议原理以及实现过程、或者你想灵活定制组件,完全DIY你的应用、想实现微服务。那么建议你选择Flask。 如果你关注产品的最终交付、想快速开发一个大的应用系统(比如新闻类网站、商城、ERP等)。那么建议你选择Django,你想得到的功能它都有,想不到的功能它也有。 五、如何才能学好框架 1、需要先学习框架的基础知识、基本实现原理 2、结合项目实践,提升编码能力和业务逻辑的理解 3、翻看框架源码,深入理解源码精髓(进阶) Flask: 1:轻量级web框架,只有一个内核,默认依赖两个外部库:Jinja2 模板引擎和 Werkzeug WSGI 工具集,自由,灵活,可扩展性强,开发者可以根据需求自己造轮子\ 2:适用于做小型网站以及web服务的API,开发大型网站无压力,架构需自行设计\ 3:与关系型数据库结合不弱于Django,而与非关系型数据库的结合远远优于Django\ \ Django: 1:重量级web框架,功能齐全,提供一站式解决的思路,能让开发者不用在选择应用上花费大量时间\ 2:自带ORM(Object-Relational Mapping 对象关联映射)和模板引擎,支持JinJa等非官方模板引擎,灵活度不高\ 3:自带ORM使Django和关系型数据库耦合度过高,如果要使用非关系型数据库,需要使用第三方库\ 4:自带数据库管理app\ 5:成熟、稳定、开发效率高、相对于Flask,Django的整体封闭性比较好,适合做企业级网站的开发\ 6:python web框架的先驱,第三方库丰富\ 7:上手容易,开发文档详细、完善、资料丰富\ --------------------- (1)Flask Flask确实很“轻”,不愧是Micro Framework,从Django转向Flask的开发者一定会如此感慨,除非二者均为深入使用过\ Flask自由、灵活,可扩展性强,第三方库的选择面广,开发时可以结合自己最喜欢用的轮子,也能结合最流行最强大的Python库\ 入门简单,即便没有多少web开发经验,也能很快做出网站\ 非常适用于小型网站\ 非常适用于开发web服务的API\ 开发大型网站无压力,但代码架构需要自己设计,开发成本取决于开发者的能力和经验\ 各方面性能均等于或优于Django\ Django自带的或第三方的好评如潮的功能,Flask上总会找到与之类似第三方库\ Flask灵活开发,Python高手基本都会喜欢Flask,但对Django却可能褒贬不一\ Flask与关系型数据库的配合使用不弱于Django,而其与NoSQL数据库的配合远远优于Django\ Flask比Django更加Pythonic,与Python的philosophy更加吻合\ (2)Django Django太重了,除了web框架,自带ORM和模板引擎,灵活和自由度不够高\ Django能开发小应用,但总会有“杀鸡焉用牛刀”的感觉\ Django的自带ORM非常优秀,综合评价略高于SQLAlchemy\ Django自带的模板引擎简单好用,但其强大程度和综合评价略低于Jinja\ Django自带ORM也使Django与关系型数据库耦合度过高,如果想使用MongoDB等NoSQL数据,需要选取合适的第三方库,且总感觉Django+SQL才是天生一对的搭配,Django+NoSQL砍掉了Django的半壁江山\ Django目前支持Jinja等非官方模板引擎\ Django自带的数据库管理app好评如潮\ Django非常适合企业级网站的开发:快速、靠谱、稳定\ Django成熟、稳定、完善,但相比于Flask,Django的整体生态相对封闭\ Django是Python web框架的先驱,用户多,第三方库最丰富,最好的Python库,如果不能直接用到Django中,也一定能找到与之对应的移植\ Django上手也比较容易,开发文档详细、完善,相关资料丰富

 

 

 

 

1. 目录结构         参考:https://blog.csdn.net/yang9520/article/details/79740374   

  1. 中文文档(http://docs.jinkan.org/docs/flask/)
一般情况下,Django很系统、统一。Flask项目目录风格不同一,即使用上了蓝图。

2. 数据库迁移

Flask要用第三方extensions,而Django自带,这个很方便。

3. 模块化

Flask是用蓝图。Django可以自动生成python manage.py startapp <app_name>,并在Django的项目的settings那个INSTALLED_APPS字典里注册一下就好。

4. 命令行

Django的命令行初始更多功能,例如migrate。但Flask自定义命令很简单。\ 启动方面,Flask有两种,一种是通过manage.py帮助脚本去运行,另一种是export环境变量,用flask run来运行,官方文档建议后面这种,1.02版本还新增了一个环境变量FLASK_ENV。因为Flask依赖5个包,其中一个是click,所以可以自定义CMD。
@app.cli.command()
def hello():
    click.echo('Hello, xxx!')

flask hello

5. 新建模型方面差不多。

它们都是继承ORM的Model。建模之后都是要加入到数据库中,就是做一个数据库迁移操作。\ Flask是传入想要创建的字段类型到model.Column,而Django有明显的类给你使用,例如models.charField。

6. 反向获取URL

urlpatterns = [ path('', views.post_list, name='post_list') ] 这个name,相当于Flask的endpoint。意思都是通过反向这个名字,reverse(name)去获得URL。
// 在模板中
<a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1>     //Django
{% url_for('") %}  // Flask

7. 路由

Django的路由和view functions是分开写的:urls.py, views.py。而Flask是都写在views.py中,view function和url写在一起(以装饰器的形式app.route)。\ 因为Django是MTV模式。其实和MVC模式差不多。大致上是Controller变成了views.py和urls.py。 Flask命令行中使用flask routes可以查看URL与view function的映射关系。代码中使用app.url_map可以查看。

8. 中间件使用

Django在settings.py里设置,\ Flask要初始化中间件实例,然后传入app(Flask)实例。

9. Request对象

Django中,每个view function或者CBV中都要写一个request参数。而Flask的view function则不用,因为
from flask import request

# 这个request是对每个请求独立的,就像g变量。值得研究底层原理(Flask通过本地线程( thread local) 技术将请求对象在特定
的线程和请求中全局可访问)

10. 限制http请求方法

Flask
@app.route('/hello', methods=['GET', 'POST'])
def hello():
return '<h1>Hello, Flask!</h1>'
Django
from django.views.decorators.http import require_http_methods
@require_http_methods(['GET','POST'])
def login(request):
    pass

11. 钩子函数

Flask,加钩子装饰器
@app.before_request
def do_something():
    pass # 这里的代码会在每个请求处理前执行
Django,通过中间件

框架之间的差别

  • Django功能大而全,Flask只包含基本的配置 Django的一站式解决的思路,能让开发者不用在开发之前就在选择应用的基础设施上花费大量时间。Django有模板,表单,路由,认证,基本的数据库管理等等内建功能。与之相反,Flask只是一个内核,默认依赖于两个外部库: Jinja2 模板引擎和 Werkzeug WSGI 工具集,其他很多功能都是以扩展的形式进行嵌入使用。
  • Flask 比 Django 更灵活 用Flask来构建应用之前,选择组件的时候会给开发者带来更多的灵活性 ,可能有的应用场景不适合使用一个标准的ORM(Object-Relational Mapping 对象关联映射),或者需要与不同的工作流和模板系统交互。
  • Flask 在 Django 之后发布,现阶段有大量的插件和扩展满足不同需要 Django发布于2005年,Flask创始于2010年年中。

入门引导

Flask的Hello World应用的代码是最简单的,只用在一个Python文件里码7行代码就够了。
from flask import Flask 
app = Flask(__name__) 

@app.route("/")
def hello(): 
    return "Hello World!" 

if __name__ == "__main__":
    app.run()
  上面代码就已经是一个简单的 web 应用,从上面的 Hello World 应用的特点来看,一个没什么Python web开发经验的人就可以很快的上手开始撸代码。

项目区别

Django 创建项目和创建应用
django-admin startproject hello_django 
django-admin startapp howdy
  其目录结构:  默认情况下,Django项目和应用创建好了之后,只包含空的模型和模板文件,而Flask创建项目之后,目录里面没有任何文件,需要我们手动创建,是没有像Django一样组件分离,而对于需要把组件分离开的项目,Flask有blueprints。例如,你可以这样构建你的应用,将与用户有关的功能放在user.py里,把与销售相关的功能放在ecommerce.py里。 Django把一个项目分成各自独立的应用,而Flask认为一个项目应该是一个包含一些视图和模型的单个应用。当然我们也可以在Flask里复制出像Django那样的项目结构。

模版

Django的模版大家都很熟悉,我们举一个简单的例子
<!-- view.html -->
<div class="top-bar row">
  <div class="col-md-10">
  <!-- more top bar things go here -->
  </div>
  {% if user %}
  <div class="col-md-2 whoami">
    You are logged in as {{ user.fullname }}
  </div>
  {% endif %}
</div>
{% for widget in inventory %}
    <li><a href="/widget/{{ widget.slug }}/">{{ widget.displayname }}</a></li>
{% endfor %}
  Flask默认使用一个受Django启发而发展起来的名为Jinja2的模板,其实,所有上面的Django模板的例子在Jinja2里也是好使的。

模版简单对比

<!-- Django -->
<div class="categories">Categories: {{ post.categories|join:", " }}</div>

<!-- Jinja -->
<div class="categories">Categories: {{ post.categories|join(", ") }}</div>
  在Jinja的模板语言里,可以把任何数量的参数传给过滤器,因为Jinja像调用一个Python函数的方式来看待它,用圆括号来封装参数。Django使用冒号来分隔过滤器名和参数,这样就只能传递一个参数了。
  • Flask的Jinja模版 for-else-endfor
{% for item in inventory %}
    <div class="display-item">{{ item.render() }}</div>
{% else %}
    <div class="display-warn">
    <h3>No items found</h3>
    <p>Try another search, maybe?</p>
    </div>
{% endfor %}
  • Django模版 for-empty-endfor
{% for item in inventory %}
    <div class="display-item">{{ item.render }}</div>
{% empty %}
    <div class="display-warn">
    <h3>No items found</h3>
    <p>Try another search, maybe?</p>
    </div>
{% endfor %}
  除了上述的语法区别,Flask还提供了很多特有的上下文变量(url_for,get_flashed_messages()等) ---------------------------------------------------------------------------------- Flask框架主要的特点是轻巧,简介,扩展性强;核心就是 Werkzeug(路由模块) ,模板引擎则使用 Jinja2 。

Flask内置的6种转换器:

‘path’  ‘string’  ‘any’  ‘int’  ‘float’  ‘uuid’ Josn 和xml 的区别:首先他们都是用来数据交互的,其次josn 更加轻量些   Flask中有两种上下文,请求上下文和应用上下文。 上下文:相当于一个容器,他保存了Flask程序运行过程中的一些信息。    

请求上下文(request context)

request和session都属于请求上下文对象。 request:封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。 (通俗来说:Request主要用来获取客户端发送过来的一些参数)   session:用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。 (通俗来说:Session主要用来实现一些用户的会话信息)    

应用上下文(application context)

current_app和g都属于应用上下文对象。 current_app:表示当前运行程序文件的程序实例。我们可以通过current_app.name打印出当前应用程序实例的名字。 (通俗来说:Current_app代表当前程序运行实例,只要程序没有暂停终止,他会一直存在, 可以帮助我们记录项目日志) g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量。比如:我们可以获取一些临时请求的用户信息。 (通俗来说:g对象和request和session比较像,请求过程中帮助我们创建,请求结束后销毁,是起到一个临时存储的作用)
  • 当调用app = Flask(_name_)的时候,创建了程序应用对象app;
  • request 在每次http请求发生时,WSGI server调用Flask.call();然后在Flask内部创建的request对象;
  • app的生命周期大于request和g,一个app存活期间,可能发生多次http请求,所以就会有多个request和g。
  • 最终传入视图函数,通过return、redirect或render_template生成response对象,返回给客户端。
区别: 请求上下文:保存了客户端和服务器交互的数据。 应用上下文:在flask程序运行过程中,保存的一些配置信息,比如程序文件名、数据库的连接、用户信息等。 (应用上下文生命周期比请求上下文的生命周期长)    

请求钩子

在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:在请求开始时,建立数据库连接;在请求结束时,指定数据的交互格式。为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。 请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子: before_first_request:在处理第一个请求前运行。 before_request:在每次请求前运行。 after_request:如果没有未处理的异常抛出,在每次请求后运行。 teardown_request:在每次请求后运行,即使有未处理的异常抛出。
1年前
赞 评论
评论(0)

暂无数据

取消回复

hanhanjun888@163.com

个人技术分享

PHP To Go 转型手记

前言

作为一名PHP程序员,我感到荣幸。但在时代不断的变迁中,要具备足够的知识才可生存。 那就从Go语言学起把。 希望看到本篇文章的你可以对Go有一个基本的认识。本系列文章与我自己学习Go语言的方式去描述。以PHP代码与Go代码的对比加以区分理解。

变量

PHP
// 初始化变量
$domain = "www.hankin.cn";
// 批量赋值
$domain = $domain1 = $domain2 = "www.hankin.cn";
Go
// 初始化变量
var domain string = "www.hankin.cn"
// 批量赋值
var domain,domain1,domain2 string = "www.hankin.cn"
// 批量声明赋值
var username,age,local = "zhangsan",13,"BeiJing"
var(
    username="zhangsan"
    age = 13
    local = "BeiJing"
)

常量

PHP
define("FOO","something");
GO
// 单独声明
const FOO [string]= something
// 批量声明
const (
    USERNAME = "zhangsan"
    AGE      = 30
)

打印

PHP
// 基本输出
echo "www.hankin.cn";
// 格式化输出
printf("my blog %s","www.hankin.cn");
GO
// 基本输出
fmt.Println("www.hankin.cn")
// 格式化输出
fmt.Printf("my blog %s","www.hankin.cn")

函数

PHP
// 基本声明
function printString(string $string){
    echo $string;
}
// 带返回值
function printString(string $string) : string{
    return $string;
}
GO
// 基本声明
func printString(s string){
    fmt.Println(s)
}
// 带返回值
func printString(s string) string{
    return s
}

加载

PHP
namespace Action
use Action
GO
package Action
import "action"

数组

PHP
// 初始化
$arr = []
$arr = array()
// 初始化赋值
$arr = [1,2,3]
// 多维数组
$arr = [][]
// 获取值
echo $arr[1]
// 获取数组总数
echo length($arr)
// 获取数组区间
$a=array("red","green","blue","yellow","brown");
print_r(array_slice($a,1,2));
// 设置key=>value
$arr = ["username"=>"zhangsan","age"=>13]
// 删除指定下标
unset($arr[0])
GO 数组 & 切片 (切片是数组的一个View,就例如MySQL的视图一样)
// 初始化
var arr [5]int
// 初始化赋值
arr := [5]int{1, 2, 3, 4, 5}
// 无需声明数组个数
arr := [...]int{1, 2, 3, 4, 5, 6, 7}
// 多维数组
var arr [4][5]bool
// 获取值
fmt.Println(arr[1])
// 获取数组总数
fmt.Println(len(arr))
// 获取数组区间 显而易见,Go对数组的操作更便利直观
a := [...]string{"red","green","blue","yellow","brown"}
fmt.Println(a[1:2])
// 设置key=>value 这里需要使用Map
m := map[string]string{
    "username": "zhangsan",
    "age" : "13"
}
// 删除指定下标 Go没有删除数组下标的系统方法
arr := arr[1:]
// 删除中间位置的下标 可通过合并的方式去除指定下标
arr := append(arr[:3],arr[4:])

循环结构

PHP
// 基本结构
for($i=0;$i<10;$i++){
    echo $i;
}
// 死循环
for($i=0;$i<10;$i++){
    echo $i;
    $i--
}
// 获取key,value
foreach($arr as $key=>$value){
    echo $key,$value
}
GO
// 基本结构
for i := 0; i < 10; i++ {
    fmt.Println(i)
}
// 死循环 可见Go写死循环非常方便
for {
    fmt.Println("")
}
// 获取key,value
for k, v := range arr {
    fmt.Println(k, v)
}

控制结构

PHP
// if
if(true){

}
// switch
switch(true){
    case true:
        echo true;
        break;
}
GO
// if
if true {

}
// switch Go语言的Switch的Case不需要break
switch true {
    case true:
        fmt.Println(true)
}

类

PHP
// 声明一个类
class City{}
GO
// 声明一个结构体 这里并非混淆公众,是因为Go本身没有类的概念,只是其声明及操作方法与类概念相似
type City struct{}

声明类

PHP
class User{}
GO
type User struct{}

成员变量

PHP
class User{
    public $name;
    public $age;
}
GO
type User struct {
    username string
    age      int
}

变量修饰

PHP
class User{
    public $name;
    private $age;
}
GO
// 没有看错,Go中没有保护(protected),变量名首字母大写为public,小写为private
type User struct {
    Username string
    Age      int
}

成员方法

PHP
class User{
    public $name;
    public $age;

    function setName(){

    }

    function getName(){

    }
}
GO
type User struct {
    username string
    age      int
}

func (u User) setName(name string) bool {
    u.username = name

    return true
}

func (u User) getName() string {
    return u.username
}

实例化-初始化

PHP
// php 没有构造方法的话,新建对象无需传参数
new User();
GO
// go 内结构体声明的变量是可选参数,既可传可不传,go既没有类概念,所以也没有构造方法。
User{"zhangsan",15}

实例化-调用

PHP
$user = new User();
$user->getName();
GO
u := User{"zhangsan",15}
fmt.Println(u.getName())

这里使用Laravel与Beego(基于Go开发的MVC框架)来演示

PHP(Laravel)
// 通过composer直接安装,简单易用
composer global require "laravel/installer"
// 创建一个项目
laravel new blog
GO(Beego)
// go自身就有包管理
go get github.com/astaxie/beego
// 创建项目也非常简单
bee api blog

目录结构

PHP(Laravel)
// laravel 的结构这里就不再阐述
| - app
| - bootstrap
| - config
| - database
| - public
| - resources
| - routes
| - storage
| - tests
| - vendor
GO(Beego)
// 显而易见,beego并没有laravel那样过度设计(虽然过度设计并非指目录,
// 但以看目录就知道beego真的没有太多东西)
blog
├── conf
│   └── app.conf
├── controllers
│   └── object.go
│   └── user.go
├── docs
│   └── doc.go
├── main.go
├── models
│   └── object.go
│   └── user.go
├── routers
│   └── router.go
└── tests
    └── default_test.go

路由

PHP(Laravel)
Route::get('/user', 'UserController@index');
GO(Beego)
// 与laravel的使用方式差不多
// 这里为了统一,路由直接绑定控制器方法只有下列这种
// beego 还提供了注解方式 , 详情见 https://beego.me/docs/mvc/controller/router.md
beego.Router("/user",&UserController{},"get:index")

模型 (Model)

PHP(Laravel)
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 与模型关联的数据表。
     *
     * @var string
     */
    protected $table = 'user';
}
GO(Beego)
// Beego通过结构体名称作为表名,并且orm操作的所有字段都必须提前声明
package models

import (
    "github.com/astaxie/beego/orm"
)
type User struct {
    Id       int    `json:"id"`
    Tel      string `json:"tel"`
    Password string `json:"password"`
    Status   string `json:"status"`
}

func init() {
    orm.RegisterModel(new(User))
}

控制器

PHP(Laravel)
<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 显示给定用户的概要文件
     *
     * @param  int  $id
     * @return Response
     */
    public function index($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}
GO(Beego)
package controllers

import (
    "github.com/astaxie/beego"
    "github.com/astaxie/beego/orm"
)

// 这里相当于继承了父类 beegoController
type MemberController struct {
    beego.Controller
}


func (c *CityController) Index() {
    var results []orm.Params

    orm.NewOrm().QueryTable("member").
        Values(&results)

    c.Data["json"] = results
    c.ServeJSON()
}
1年前
赞 评论
评论(0)

暂无数据

取消回复

hanhanjun888@163.com

个人技术分享

真正的50行css代码实现响应式“瀑布流”布局
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
  <title>瀑布流</title>
  <style>
    :root {--color1: #a3d9a5;--color2: #f6b93b;--color3: #38ada9;--color4: #e55039;--color5: #1e3799;--color6: #6a89cc;--color7: #f8c291;--color8: #b71540;}
    .lists .item:nth-child(odd) {background-color: var(--color1);}
    .lists .item:nth-child(even) {background-color: var(--color2);}
    .lists .item:nth-child(3n) {background-color: var(--color3);}
    .lists .item:nth-child(4n) {background-color: var(--color4);}
    .lists .item:nth-child(5n) {background-color: var(--color5);}
    .lists .item:nth-child(6n) {background-color: var(--color6);}
    .lists .item:nth-child(7n) {background-color: var(--color7);}
    .lists .item:nth-child(8n) {background-color: var(--color8);}

    .lists {width: 1200px;margin: 0 auto;column-count: 4;column-gap: 10px;transition: column-count 0.3s ease-in-out;}
    .lists .item {height: 160px;margin-bottom: 10px;break-inside: avoid;color: #000000;text-align: center;font-size: 30px;transition: height 0.3s ease-in-out;}
    /* 更多的高度和选择器组合 */
    .lists .item:nth-child(3n+1) { height: 200px; }
    .lists .item:nth-child(4n+1) { height: 250px; }
    .lists .item:nth-child(5n+1) { height: 180px; }
    .lists .item:nth-child(6n+1) { height: 280px; }
    .lists .item:nth-child(7n+1) { height: 220px; }
    .lists .item:nth-child(8n+1) { height: 300px; }
    .lists .item:nth-child(9n+1) { height: 230px; }
    .lists .item:nth-child(10n+1) { height: 260px; }
    @media (max-width: 992px) {
      .lists {width: auto;padding: 10px;box-sizing: border-box;column-count: 3;column-gap: 10px;}
      .lists .item {break-inside: avoid;width: auto;text-align: center;margin-bottom: 10px;}
      /* 在较小屏幕下适应不同的高度 */
      .lists .item:nth-child(3n+1) { height: 220px; }
      .lists .item:nth-child(4n+1) { height: 180px; }
      .lists .item:nth-child(5n+1) { height: 250px; }
      .lists .item:nth-child(6n+1) { height: 200px; }
    }
    @media (max-width: 768px) {
      .lists {width: auto;padding: 10px;box-sizing: border-box;column-count: 2;column-gap: 10px;}
      .lists .item {break-inside: avoid;width: auto;height: 200px;line-height: 200px;text-align: center;margin-bottom: 10px;}
      .lists .item:nth-child(2n+1) {height: 240px;}
      .lists .item:nth-child(3n+1) {height: 320px;}
    }
  </style>
</head>
<body>
<div class="lists"><div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div><div class="item">9</div><div class="item">10</div><div class="item">11</div><div class="item">12</div><div class="item">13</div><div class="item">14</div><div class="item">15</div><div class="item">16</div>
</div>
</body>
</html>
1年前
赞 评论
评论(0)

暂无数据

取消回复

hanhanjun888@163.com

个人技术分享

微信公众号网页授权多域名解决方案(本地环境也可调用)
  • 实现微信授权域名中转实例
    • 微信授权回调域名(中转域名):www.test.com
    • 需要授权回调域名1:www.test1.com
    • 需要授权回调域名2:www.test2.com

一个公众号的域名授权数量是有限的,如果一个公众号需要绑定多个域名时怎么解决呢?这时候就需要用到域名中转

本地环境也可调用微信授权登录

  • 实现微信授权域名中转实例
    • 微信授权回调域名(中转域名):www.test.com
    • 需要授权回调域名1:www.test1.com
    • 需要授权回调域名2:www.test2.com

在中转域名网站 根目录下新建 wxLogin.php中编写发起授权代码

<?php
// +----------------------------------------------------------------------
// | 作者 hankin [ http://www.hankin.cn ]
// +----------------------------------------------------------------------
// | 版权所有 2024-06-27 13:06 hankin
// +----------------------------------------------------------------------
// | 官方网站: http://www.hankin.cn
// +----------------------------------------------------------------------
?>
<?php
$gzh_app_id = "公众号appid";//公众号appid
$gzh_app_secret = "公众号appsecret";//公众号appsecret
?>
<?php if(isset($_GET['redirectUrl']) && !empty($_GET['redirectUrl'])):?>
    <!--  获取跳转url地址  -->
    <script type="text/javascript">localStorage.setItem('redirectUrl','<?= $_GET['redirectUrl'];?>')</script>
<?php endif;?>

<?php if(isset($_GET['type']) && !empty($_GET['type'])):
    //发起授权
    $redirectUrl =  $_SERVER['REQUEST_SCHEME'] . '://'.  $_SERVER['SERVER_NAME'] . '/' . $_GET['type'] . '.php';
    //获取公众号授权拿到code
    $codeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$gzh_app_id."&redirect_uri=".urlencode($redirectUrl)."&response_type=code&scope=snsapi_userinfo&forcePopup=true&forceSnapShot=true&state=STATE#wechat_redirect";
    //header("location: ".$codeUrl);
    ?>
    <script type="text/javascript">
        //跳转code页面地址
        setTimeout(function(){
            window.location.href = '<?= $codeUrl;?>'
        },500)
    </script>
<?php endif;?>

<?php if(isset($_GET['code']) && !empty($_GET['code'])):
    //根据code获取微信用户信息
    $data = getSimpleUserInfo($_GET['code'], $gzh_app_id, $gzh_app_secret);
    ?>
    <?php
    //微信用户信息解析
    $ret['userinfo']['openid'] = $data['openid'] ?? '';//微信用户唯一标识 openid
    $ret['userinfo']['unionid'] = $data['unionid'] ?? '';//微信用户唯一标识 unionid
    $ret['userinfo']['nickname'] = $data['nickname']?? '';//微信用户昵称
    $ret['userinfo']['avatar'] = $data['headimgurl']?? '';//微信用户头像
    ?>
    <script type="text/javascript">
        //跳转回调地址
        window.location.href = localStorage.getItem('redirectUrl')+'?data=<?= urlencode(json_encode($ret));?>'
        //JSON.parse(decodeURIComponent(window.location.href.split('?data=')[1]))
    </script>
<?php endif;?>

<?php
function getSimpleUserInfo($code, $WECHAT_APPID, $WECHAT_APPSECRET)
{
    if (empty($code)) return array();
    //通过code换取网页授权access_token
    $access_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $WECHAT_APPID . '&secret=' . $WECHAT_APPSECRET . '&code=' . $code . '&grant_type=authorization_code';
    $access_token_json = https_request($access_token_url);
    $access_token_array = json_decode($access_token_json, true);

    $openid = isset($access_token_array['openid']) ? $access_token_array['openid'] : '';
    $access_token = isset($access_token_array['access_token']) ? $access_token_array['access_token'] : '';

    $userinfo_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN';
    $userinfo_json = https_request($userinfo_url);

    $userinfo_array = json_decode($userinfo_json, true);

    return $userinfo_array;
}

//请求接口
function https_request($url)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($curl);
    if (curl_errno($curl)) {
        return 'ERROR ' . curl_error($curl);
    }
    curl_close($curl);
    return $data;
}



/**
 * 生成AJAX结果
 * @param $resultCode
 * @param null $message
 * @param null $data
 * @return array
 */
function generateAjaxResult($resultCode, $message = NULL, $data = NULL)
{
    exit(json_encode([
        'code' => $resultCode,
        'msg' => $message,
        'result' => $data,
    ]));
}



/**
 * AJAX成功返回数据
 * @param null $data
 * @return array
 */
function ajaxSuccess($data = NULL,$message = NULL)
{
    $result = generateAjaxResult(
        200,
        $message,
        $data
    );

    return $result;
}



/**
 * AJAX错误返回数据
 * @param null $message
 * @param int $resultCode
 * @param null $data
 * @return array
 */
function ajaxError($message = NULL, $resultCode = 1000, $data = NULL)
{
    $result = generateAjaxResult(
        $resultCode,
        $message,
        $data
    );

    return $result;
}
?>
  • 根据如上方式就可以实现微信授权域名中转
  • 访问 www.test1.com 站点时只需访问 https://www.test.com/wxLogin.php?type=wxLogin&redirectUrl=当前前端页面地址
  • 访问 www.test2.com 站点时只需访问 https://www.test.com/wxLogin.php?type=wxLogin&redirectUrl=当前前端页面地址
1年前
赞 评论
评论(0)

暂无数据

取消回复

hanhanjun888@163.com

个人技术分享

API数据接口平台集合

TenAPI(免费):https://docs.tenapi.cn/
百度AI:http://ai.baidu.com/
微博:https://open.weibo.com/wiki/API
讯飞:https://www.xfyun.cn/
APISpace:https://www.apispace.com/
聚合:https://www.juhe.cn/
旷视人脸:https://www.faceplusplus.com.cn/
融云:https://www.rongcloud.cn/
京东云:https://wx.jdcloud.com/api
高德:https://lbs.amap.com/
腾讯云产品API中心:https://cloud.tencent.com/api
阿里API市场:https://market.aliyun.com/products/56956004/
百度:https://apis.baidu.com/

1年前
赞 评论
  •  : 请问一下,同款主题在哪里授权、下载?
评论(1)
  1.   1年前 说道:

    请问一下,同款主题在哪里授权、下载?

    1年前
    回复

取消回复

hanhanjun888@163.com

个人技术分享

“免费” 开通腾讯混元-元器 机器人 TOKEN真的有“一亿次”
<?php

//使用文档:https://docs.qq.com/doc/DTWxpclVNeFRUUlh3

//目前已接入文生图

//解析抖音去水印视频
1年前
赞 评论
评论(0)

暂无数据

取消回复

hanhanjun888@163.com

个人技术分享

x-sign 算法
def get_sign(Pm):
    #这里是加密需要的字段
    arg0 = Pm['appKey']
    arg1 = Pm['utdid'] + "&"
    arg1 = arg1 + Pm['uid']+ "&"
    arg1 = arg1 + Pm['reqbiz-ext']+ "&"
    arg1 = arg1 + Pm['appKey']+ "&"
    arg1 = arg1 + Pm['datamd5']+ "&"
    arg1 = arg1 + Pm['t']+ "&"
    arg1 = arg1 + Pm['api']+ "&"
    arg1 = arg1 + Pm['v']+ "&"
    arg1 = arg1 + Pm['sid']+ "&"
    arg1 = arg1 + Pm['ttid']+ "&"
    arg1 = arg1 + Pm['deviceId']+ "&"
    arg1 = arg1 + Pm['lat']+ "&"
    arg1 = arg1 + Pm['lng']+ "&"
    arg1 = arg1 + Pm['ext']+ "&"
    arg1 = arg1 + Pm['x-features']+ "&"
    arg1 = arg1 + Pm['routerId']+ "&"
    arg1 = arg1 + Pm['placeId']+ "&"
    arg1 = arg1 + Pm['openBiz']+ "&"
    arg1 = arg1 + Pm['miniAppKey']+ "&"
    arg1 = arg1 + Pm['reqAppKey']+ "&"
    arg1 = arg1 + Pm['act']+ "&"
    arg1 = arg1 + Pm['openBizData']
    arg2 = Pm['api']
    arg3 = "pageName="+ Pm['pageName'] + "&pageId=" + Pm['pageId']
    sign = xianyu.get70102(arg0,arg1,arg2,arg3)
    ret = eval(str(sign))
    Pm.update(ret)
    return ret
#在这里定义自己的字段
def build_Pm(api,v,data):
    Pm = {}
    Pm['x-app-ver'] = "7.1.60"
    Pm['utdid'] = "YIJLR2Y/7fgDAMOPtQCGzfRz"
    Pm['uid'] = ""#登录后才有
    Pm['reqbiz-ext'] = ""
    Pm['appKey'] = "21407387"
    Pm['datamd5'] = hashlib.md5(data.encode("utf-8")).hexdigest() if data != "" else ""
    Pm['t'] = str(int(time.time()))
    Pm['api'] = api
    Pm['v'] = v
    Pm['sid'] = ""#登录后才有
    Pm['ttid'] = "36137321407327@fleamarket_android_7.1.60"
    Pm['deviceId'] = "AlKfW_V2tm3mJ3AYHwUErKPkq41dPGN2vXWlskFJDb2s"
    Pm['lat'] = "0"
    Pm['lng'] = "0"
    Pm['ext'] = "openappkey=DEFAULT_AUTH"
    Pm['x-features'] = "27"
    Pm['routerId'] = ""
    Pm['placeId'] = ""
    Pm['openBiz'] = ""
    Pm['miniAppKey'] = ""
    Pm['reqAppKey'] = ""
    Pm['act'] = ""
    Pm['openBizData'] = ""
    Pm['pageName'] = ""
    Pm['pageId'] = ""
    Pm['x-sgext'] = ""
    Pm['x-umt'] = ""
    Pm['x-mini-wua'] = ""
    Pm['x-sign'] = ""
    Pm['x-pv'] = "6.3"
    Pm['x-bx-version'] = "6.5.24"
    Pm['User-Agent'] = "MTOPSDK/3.1.1.7+(Android;7.1.2;HUAWEI;VOG-AL00)"
    Pm['Cookie'] = ""
    Pm['f-refer'] = "mtop"
    sign = get_sign(Pm)
    return Pm
 
def xianyu_post(url,api,v,data,_headers = {}):
    Pm = build_Pm(api,v,data)
    headers = {
        "x-extdata": Pm['ext'],
        "x-features": Pm['x-features'],
        "x-sgext": quote_plus(Pm['x-sgext']),
        "umid": quote_plus(Pm['x-umt']),
        "User-Agent": quote_plus(Pm['User-Agent']),
        "x-ttid": quote_plus(Pm['ttid']),
        "content-type": "application/x-www-form-urlencoded;charset=UTF-8",
        "a-orange-q":"appKey="+Pm['appKey']+"&appVersion="+Pm['x-app-ver']+"&clientAppIndexVersion=1120210930160801265&clientVersionIndexVersion=0",
        "x-appkey": Pm['appKey'],
        "x-mini-wua": quote_plus(Pm['x-mini-wua']),
        "x-nq" : "WIFI",
        "x-nettype": "WIFI",
        "first_open" : "0",
        "x-c-traceid": Pm['ttid'] + Pm['t'] +"332000317813",
        "x-app-conf-v": "0",
        "x-pv": Pm['x-pv'],
        "x-bx-version": Pm['x-bx-version'],
        "x-t": Pm['t'],
        "x-app-ver": Pm['x-app-ver'],
        "f-refer": Pm['f-refer'],
        "Cookie" : Pm['Cookie'],
        "x-sid": Pm['sid'],
        "x-utdid": Pm['utdid'],
        "x-umt": quote_plus(Pm['x-umt']),
        "x-devid": Pm['deviceId'],
        "x-sign": quote_plus(Pm['x-sign']),
        "x-location": quote_plus("{0},{1}".format(Pm['lng'], Pm['lat'])),
        "x-page-name": Pm['pageName'],
        "x-page-url": quote_plus(Pm['pageId']),
        "x-uid": Pm['uid']
    }
    headers.update(_headers)
    url = url + "/" + api + "/" + v + "/"
    postdata = "data=" + quote_plus(data)
    ret = requests.post(url, data=postdata, headers=headers)
    return ret
url = "http://acs.m.taobao.com/gw"
api = "mtop.taobao.idle.local.flow.plat.container"
v = "1.0"
data = '{"productId":"2","unionKey":"online_local_concept_container"}'
ret =  xianyu_post(url,api,v,data)
print(ret.text)
2年前
赞 评论
  • 1个赞
评论(0)

暂无数据

取消回复

加载更多
个人技术分享
刷新页面会随机【个人信息流样式】

28

文章

103

获赞

231

评论

7.7万+

浏览
世界那么大,我想去看看。但钱包那么小,哪也去不了。所以,珍惜当下,享受生活。
30岁 IP: 杭州 家里蹲大学
  • 首页
  • 关于
  • 主题
  • 影视解析
  • 音乐
  • 归档
  • 留言
  • “免费” 开通腾讯混元-元器 机器人 TOKEN真的有“一亿次”1年前
  • wordpress 主题 hankin 新增登录注册、用户中心2年前
  • Mac 下 打开微信小程序目录2年前
  • 来一篇文章2年前
  • wordpress 解决 播放抖音资源视频报403 forbidden2年前

免费开源smarty_hankin v2.0重构版

wordpress版本:6.0+

PHP版本:7.0~8.0

gitee源码仓库地址:点击打开

github源码仓库地址:点击打开

最新源码地址:待更新

加QQ群入口:1018842166

WP开源主题 smarty_hankin

最近评论


    Warning: Trying to access array offset on value of type null in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/widget/widget-comments.php on line 32

    Warning: Trying to access array offset on value of type null in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/widget/widget-comments.php on line 32
  • […] 平台主题名称介绍价格地址WPpix综合性最好的主题298DemoWPpink完成度高朋友圈499DemoWPhankin还在完善的主题noDemoTypicefox完成度高FreeDemoTypListen完成度高FreeDemoTypNabo小鸟风格FreeDemoTypzyyo三栏自适应现代时尚FreeDemoTypFlip仿pix主题noDemoTyppengyou单栏主题noDemoTypfriends单栏主题noDemoTyplan tyLAN程序TY版本39DemoHalopixpix授权移植主题169DemoZblogpyq单栏朋友圈noDemoZblogMoments轻社交朋友圈298DemoHugomoments单栏朋友圈noDemo程序lan程序有朋友圈外观99DemoDiscuz! 朋友圈式手机版Discuz!的纯手机版朋友圈98Demo […] 抠脚大汉的摆烂人生 发布于1年前

  • Warning: Trying to access array offset on value of type null in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/widget/widget-comments.php on line 32

    Warning: Trying to access array offset on value of type null in /www/wwwroot/hankin.cn/wp-content/themes/hankin/inc/widget/widget-comments.php on line 32
  • […] Demo […] YanZi-朋友圈 发布于1年前
  • 请问一下,同款主题在哪里授权、下载?   发布于1年前
  • 真不错👍 唤( . )醒 发布于2年前
  • 确实挺不错的 断舍离 发布于2年前

扫码加QQ群:1018842166

微信打赏

支付宝打赏

友情链接: coder gzh DIYgod kam mango pix主题 wordpress 大学 wp2 主题喵 主题猫 元气秋刀鱼 创造狮 吾柯 大海看看 守望轩-宁静雅致的小轩馆 腾讯设计导航 若志奕鑫 风信子博客 更多链接

hankin Powered by WordPress 浙ICP备20002401号-1