iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Django简介
  • 451
分享到

Django简介

简介Django 2023-01-30 22:01:35 451人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

MVC与MTV模型MVCWEB服务器开发领域里著名的mvc模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户

MVC与MTV模型

MVC

WEB服务器开发领域里著名的mvc模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图如下所示:

blob.png

mvc主要用于web框架,常用的开发语言,有java,php,node.js等等


MTV

Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,DjanGo的MTV分别是值:


M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。

T 代表模板 (Template):负责如何把页面展示给用户(html)。

V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。

除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:

blob.png


一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户


MVC和MTV模型的区别:

MVC:
    M : model (与数据库打交道)
    V :  views  (存放html文件)
    C : Controller(逻辑控制部分)        
MTV 
    M : model     (与数据库打交道)
    T : templates    (存放html文件)    
    V : views      (逻辑处理)    +
    路由控制层(分发哪一个路径由哪一个视图函数处理),它没有单独的分层。它作为URL分发器,将url请求分发给不同
    的view处理


Django的下载与基本命令

1、下载Django:

pip3 install django


2、创建一个django project

windows用户,以管理员身份打开一个cmd窗口。进入一个空目录,运行以下命令:

E:\python_script\django框架\day2>django-admin startproject mysite


当前目录下会生成mysite的工程,目录结构如下:

mysite/├── manage.py
└── mysite
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。

settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。

urls.py ----- 负责把URL模式映射到应用程序。


manage.py : 它是启动文件,它还是与Django交互的文件。比如:

python manage.py  runserver   : 运行项目

python manage.py  startapp    : 创建应用

如果运行项目时,不指定端口,默认监听本机的8000端口


在mysite目录下创建应用

#进入mysite目录
E:\Python_script\django框架\day2>cd mysite
#创建应用blog
E:\python_script\django框架\day2\mysite>python manage.py startapp blog


目录结构如下:

mysite/├── blog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── mysite
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

views.py---存放视图函数

models--与数据库打交道

还有一个目录templates,它是用来存放html文件的


从上面的目录结构可以看出,mysite目录下有一个blog。那么顶层的mysite,叫做 项目。底层的blog叫做应用

项目是必须包含应用的,项目可以包含多个应用。

mysite下的mysite,是全局文件,它有2个全局配置文件,一个是settings.py(项目配置文件),一个是urls.py(路由控制文件)


启动django项目

E:\python_script\django框架\day2\mysite>python manage.py runserver 127.0.0.1 8080
Performing system checks...

System check identified no issues (0 silenced).

You have 14 unapplied migration(s). Your project may not work properly until you apply the migrations for 
app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
June 21, 2018 - 19:33:29
Django version 2.0.6, using settings 'mysite.settings'
Starting development server at Http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.


这样django就启动起来了!访问:http://127.0.0.1:8080/时就可以看到  

blob.png


基于Django实现的一个简单示例

url控制器

修改mysite目录下的urls.py,增加index路径

注意:index后面不要加括号。直接views.index即可

必须导入blog应用的views模块,否则它找不到对应的视图函数

from django.contrib import adminfrom django.urls import pathfrom blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
]


视图

修改blog目录下的views.py,增加index视图函数

from django.shortcuts import render
import datetime

# Create your views here.

def index(request):
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime})

request,它是一个对象。存储了请求信息,比如请求路径,请求方式,GET数据,POST数据...等等。

必须要接收一个request参数


模板

新建文件夹templates,在此目录创建index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h4>当前时间:{{ ctime }}</h4>

</body>
</html>


修改mysite目录下的settings.py,指定模板目录为templates,修改部分如下

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]


访问网页,效果如下:

blob.png


django有一个好处,代码更改之后,它会自动加载代码。而不需要重启django项目,网页就能更新了!



增加登录页面

修改mysite目录下的urls.py,新增一个login

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('login/',views.login),
]


在templates目录下创建文件login.html

注意:form表单的标签名是form,不是from。from是Mysql的关键字,不要弄混淆了。否则点击提交按钮,是没有反应的

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="">
    <lable>用户名</lable><input type="text" name="user"/>
    <lable>用户名</lable><input type="passWord" name="pwd"/>
    <input type="submit">
</form>

</body>
</html>


修改blog目录下的views.py,增加login视图函数

from django.shortcuts import render
import datetime

# Create your views here.

def index(request):
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime})

def login(request):
    return render(request,"login.html")


访问登录页面,效果如下:

blob.png



为什么render能找到login.html文件呢?

因为setting.py文件里面定义了template路径。render方法,是用来渲染模板的,它会从TEMPLATES配置的路径中去寻找html文件。


如果修改DIRS里面的文件名,比如改为abc

'DIRS': [os.path.join(BASE_DIR, 'abc')],


访问页面,会报错

blob.png



修改urls.py,增加auth路径,用来做验证的

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('login/',views.login),
    path('auth/',views.auth),
]


修改login.html文件,改为post请求

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/auth/" method="post">
    <lable>用户名</lable><input type="text" name="user"/>
    <lable>用户名</lable><input type="password" name="pwd"/>
    <input type="submit">
</form>

</body>
</html>


修改views.py文件,增加auth视图函数

from django.shortcuts import render,HttpResponse
import datetime

# Create your views here.

def index(request):
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime})

def login(request):
    return render(request,"login.html")

def auth(request):
    print(request.path)  # 路径
    print(request.method)  # 请求方式
    print(request.GET)  # GET数据
    print(request.POST)  # POST数据
    return HttpResponse("OK")


访问登录页面,输入数据,点击提交

blob.png



页面输出403,被CSRF拦截了

blob.png


CSRF:跨站请求伪造,常缩写为CSRF或者XSRF,是一种对网站的恶意利用。

后面会讲到,如何避免CSRF。这里先注释掉,修改settings.py里面的MIDDLEWARE 配置项,关闭CSRF

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]



访问方式

访问方式有2种,GET和POST

在地址栏中,只有GET请求。

在form表单中,有GET和POST。它是根据method属性决定的!一般表单使用POST

再次访问url,输入表单信息,点击提交。

输出ok,表示正常。注意:这里还没有做登录认证,下面会讲到!

blob.png


查看cmd窗口输出信息:

/auth/
POST
<QueryDict: {}>
<QueryDict: {'user': ['xiao'], 'pwd': ['123']}>

可以看到:

路径:/auth/。请求方式: POST。GET数据为空。POST数据是一个字典


登录认证

正常网站,用户名和密码是保存在数据库中。由于还没有学到django连接数据库,所以这里将用户名和密码写死,模拟登录行为。

修改views.py,获取用户和密码,进行判断

from django.shortcuts import render,HttpResponse
import datetime

# Create your views here.

def index(request):
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime})

def login(request):
    return render(request,"login.html")

def auth(request):
    user = request.POST.get('user')  # 获取用户名
    pwd = request.POST.get('pwd') # 获取密码
    print(user,pwd)
    #判断用户名和密码
    if user == 'xiao' and pwd == '123':
        return HttpResponse("登录成功")  # 返回响应体给浏览器,显示"登录成功"文字
    else:
        return render(request,"login.html")  # 返回响应体-->login.html文件内容


重新访问登录页面,输入正确的用户名和密码

页面提示,成功

blob.png


访问过程分析

访问登录页面时,经历3个步骤

(1) http://127.0.0.1:8000/login/   get请求 无数据
(2) path('login/',views.login),    调用视图函数login(request)
(3) login                          执行视图函数,响应了一个login.html页面

解释:

1. 首先是用户在浏览器输入url:http://127.0.0.1:8000/login/

2. django接收到请求之后,根据URL控制器匹配视图函数

3. 执行视图函数login,响应请求给浏览器一个login.html页面


1.虽然form的action属性值为"/auth/",但是执行提交动作时,浏览器会查看action属性,如果为相对路径。那么会获取当前url的域名/IP加端口。和action属性拼接,得到完整的url,比如:http://127.0.0.1:8000/auth/。将表单数据以POST方式发送给此url。

注意:推荐使用这种写法。如果action写成完整的url(比如:http://127.0.0.1:8000/auth/),遇到服务器迁移时。那么涉及到的html文件,都需要更改,非常耗时耗力!

如果采用相对路径方式,那么不需要改动代码,它会自动拼接,完美解决这个问题。

比如写/auth/,会自动拼接为http://127.0.0.1:8000/auth/

如果action为"",也就是空,它会拼接当前的完整ur。

比如访问登录页面,那么action的属性值为 当前url,比如:http://127.0.0.1:8000/login/

2. django接收到请求之后,根据URL控制器匹配视图函数auth

3. 执行视图函数,如果用户名和密码正确,页面显示登录成功。否则,页面还是显示登录页面



将login和auth视图函数合并成1个

更改login.html,将action属性设置为空(参考上面的步骤1解释)

<form action="" method="post">


更改views.py,删除auth视图函数代码,修改login视图函数,完整代码如下

from django.shortcuts import render,HttpResponse
import datetime

# Create your views here.

def index(request):
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime})

def login(request):
    #判断请求是否为POST,必须为大写
    if request.method == "POST":
        user = request.POST.get('user')  # 获取用户名
        pwd = request.POST.get('pwd')  # 获取密码
        print(user, pwd)
        # 判断用户名和密码
        if user == 'xiao' and pwd == '123':
            return HttpResponse("登录成功")  # 返回响应体给浏览器,显示"登录成功"文字
        else:
            return render(request, "login.html")  # 返回响应体-->login.html文件内容

    return render(request,"login.html")  # 默认输出登录页面


修改urls.py,删除auth路径

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('login/',views.login),
]


重新访问登录页面,输入正确的用户和密码,点击提交。页面输出:

blob.png

视图函数,必须返回一个HttpResponse对象。HttpResponse是一个对象,对象里面,放字符串

HttpResponse会自动将字符串转换为字节

django要求视图函数,必须返回一个HttpResponse对象。



模拟render操作

修改login函数,else部分是重点

def login(request):
    #判断请求是否为POST,必须为大写
    if request.method == "POST":
        user = request.POST.get('user')  # 获取用户名
        pwd = request.POST.get('pwd')  # 获取密码
        print(user, pwd)
        # 判断用户名和密码
        if user == 'xiao' and pwd == '123':
            return HttpResponse("登录成功")  # 返回响应体给浏览器,显示"登录成功"文字
        else:
            from mysite import settings  # 导入settings模块
            import os
            # 拼接login.html的绝对路径
            path = os.path.join(settings.BASE_DIR,"templates","login.html")
            with open(path,encoding="utf-8") as f:
                data = f.read()  # 读取文件所有内容
            print("data",data+'aaaaa')
            #返回给浏览器并加上一段话
            return HttpResponse(data+'用户名和密码错误')
            # return render(request, "login.html")  # 返回响应体-->login.html文件内容

    return render(request,"login.html")  # 默认输出登录页面


访问url: http://127.0.0.1:8000/login/

输入一个错误的密码,点击提交

blob.png

总结:

对于Django而言,一次请求必须返回一个HttpResponse(字符串)

request对象,存放了请求路径,请求方式,请求数据,比如GET和POST

所以对于视图函数而言,最关心的部分就是request和HttpResponse

一次请求,必有一次响应。如果没有响应,就会报错



在视图函数中,render是渲染的意思。那么它是如何工作的呢?

1 按着settings-TEMPLATES-DIRS路径找指定文件
2 读取文件所有字符串
3 渲染: 检查字符串中是否有{{变量}}    ,
    if 没有找到:
        HttpResponse(文件字符串)
    else
        找到 {{变量}},用render第三个参数中的对应值进行相应替换(如果没有找到对应值,{{变量}}替换为空)
        HttpResponse(替换后的文件字符串)

渲染的过程,是在后端完成的。不是前端完成的。

看html代码,就知道了。浏览器根本不认识{{变量}},它只能识别html,CSSjs

注意:如果模板里面,写了{{变量}} 。但是render没传,那么页面中{{变量}} 会被替换为空。

如果模板里面,写了{{ }} 。变量名没写,那么页面报错


思考:如何点击时间的时候,变成红色?

需要引入jquery来做,修改index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/Jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<h4>当前时间: <span>{{ ctime }}</span></h4>
<script type="application/javascript">
    $(function(){
        $('.time').click(function () {
            $(this).css("color","red")
        })
    });
</script>
</body>
</html>


在根目录,创建static目录,它是专门存放静态文件的。

将js文件进去。项目目录结构如下

mysite/
├── blog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── static
│   └── jquery.min.js
└── templates
    ├── index.html
    └── login.html


修改settings.py,最后一行添加,注意:STATIC_URL和它是成对使用的

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"static"),
)

STATIC_URL参数,表示别名。

STATICFILES_DIRS表示物理路径。

STATIC_URL代指STATICFILES_DIRS定义的路径。


修改index.html,更改src属性

<script src="/static/jquery.min.js"></script>


重新访问页面,再次点击,就会变红

blob.png


--结束END--

本文标题: Django简介

本文链接: https://www.lsjlt.com/news/179157.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Django简介
    MVC与MTV模型MVCWeb服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户...
    99+
    2023-01-30
    简介 Django
  • Django的简介
    Django的MTV模式:   Model(模型):和数据库相关的.负责业务对象与数据库的对象(ORM)   Template(,模板):放所有的HTML文件           模板语法:目的是将变量(数据库内容)如何巧妙的镶嵌到HT...
    99+
    2023-01-30
    简介 Django
  • Django admin简单介绍
    生成同步数据库的脚本: python manage.py makemigrations 同步数据库: python manage.py migrate 创建后台用户 python manage.py createsuperuser 访...
    99+
    2023-01-31
    简单 Django admin
  • Django ajax 简单介绍
    AJAX Asynchronous Javascript And XML是 "异步Javascript和XML"。即使用 Javascript 语言与服务器进行异步交互,传输的数据为XML。 同步交互:客户端发出一个请求后,需要等待服务器...
    99+
    2023-01-31
    简单 Django ajax
  • Django框架的简介
    本篇内容主要讲解“Django框架的简介”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Django框架的简介”吧!Python这些年火得厉害,web框架也是应运而生。Django算是其中比较典型...
    99+
    2023-06-04
  • Django之模型---ORM简介
      ORM,是“对象-关系-映射”的简称,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动。 创建项...
    99+
    2023-01-30
    模型 简介 Django
  • MongoDB(一):NoSQL简介、MongoDB简介
    1. NoSQL简介 1.1 什么是NoSQL NoSQL(NoSQL= Not Only SQL),意即“不仅仅是SQL",是一项全新的数据库理念,泛指非关系型的数据库。 1.2 为什么需要NoSQL 随着互联网web2.0网站的兴起,非...
    99+
    2019-07-31
    MongoDB(一):NoSQL简介 MongoDB简介
  • Python~~简介介绍
    Python (英国发音:/paθn/ 美国发音:/paθɑn/), 是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于...
    99+
    2022-10-18
  • Nginx简介
    一、什么是Nginx Nginx是一个高性能的HTTP和反向代理Web服务器,同时也提供IMAP/POP3/SMTP服务。Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3/SMTP)代理服务器。Nginx...
    99+
    2023-10-11
    nginx 服务器 运维 Powered by 金山文档
  • IPv6简介
    IPv6仅仅只是“长”吗?IPv6的地址长什么样?平时我们是怎么使用IPv6的呢?编写网络程序的时候要怎么处理IPv6?且待本篇一一道来。 为什么需要IPv6 全球的IP地址由一个名字叫IANA(Internet Assigned Num...
    99+
    2023-01-31
    简介
  • python简介
    Python是一种开源的面向对象编程语言随着人工智能与大数据分析的火热,python也随之火热起来Python应用广泛,特别适用以下几个方面1.系统编程:提供API(Application Programming Interface,应用程...
    99+
    2023-01-30
    简介 python
  • DevOps简介
    DevOps 是一个完整的面向IT运维的工作流,以 IT 自动化以及持续集成(CI)、持续部署(CD)为基础,来优化程式开发、测试、系统运维等所有环节。     DevOps的概念 DevOps一词的来自于Development和Ope...
    99+
    2023-01-30
    简介 DevOps
  • Python 简介
    Python介绍与特点(自学python知识整理) Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计: Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于P...
    99+
    2023-01-31
    简介 Python
  • OpenCV简介
    OpenCV简介 OpenCV(开源计算机视觉库:http://opencv.org)是一个开源库,包含数百种计算机视觉算法。OpenCV 具有模块化结构,主要包括下列模块: 核心功能(core) - 定义基本数据结构的紧凑模块,包括密集多...
    99+
    2023-08-30
    opencv 人工智能 计算机视觉
  • Ajax简介
    一、Ajax简介 Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指⼀种创建交互式⽹⻚应⽤的⽹⻚开发技术。 Ajax 是⼀种⽤于创建快速动态⽹⻚的技术。 Aja...
    99+
    2023-09-02
    ajax javascript 服务器
  • argparse简介
    一、argparse简介 argparse 模块是 Python 内置的用于命令项选项与参数解析的模块,argparse 模块可以让人轻松编写用户友好的命令行接口,能够帮助程序员为模型定义参数。 ar...
    99+
    2023-09-01
    python
  • Elasticsearch简介
      疫情已经持续了好几个月了,作为程序员滴我们也帮不上什么忙,只有老老实实呆在家里或者出门一定戴口罩准守一些规则,不给国家添乱。不过最近疫情开始有所扭转,但是还是对国家经济,对企业业务造成了很大的影响,我也被停止了实习。接下来,可...
    99+
    2014-08-14
    Elasticsearch简介
  • Zookeeper简介
    1.1 什么是zookeeper Zookeeper是一个分布式的、开源的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Apache Hadoop的一个子项目,主要是用来解决分布式应用中经常遇到的一些数据...
    99+
    2017-07-20
    Zookeeper简介
  • Redis 简介
    Redis 特性     1.速度快       官方给出的数字是读写性能可以达到10万/秒,当然这也取决于机器的性能。大致归纳速度快的四点原因如下:             # Redis 的所有数据都是放在内存中的,这也是最主...
    99+
    2021-08-02
    Redis 简介
  • Cassandra 简介
    Cassandra是云原生和微服务化场景中最好的NoSQL数据库。我信了~  1. Cassandra是什么 高可用性和可扩展的分布式数据库 Apache Cassandra™是一个开源分布式数据,可提供当今最苛刻的应用程序所需...
    99+
    2015-01-20
    Cassandra 简介
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作