zoukankan      html  css  js  c++  java
  • Django

    一、Django简介

      第一个开放源代码的WEB应用框架,由python写成,初次发布于2005年7月,并于2008年9月发布了第一个正式版本1.0。主要有两种模式:MVC和MTV

      MVC:

        概述:一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进 和个性化定制界面及用户交互的同时,不需

                             要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理 和输出功能在一个逻辑的图形化用户界面的结构中

        核心思想:解耦

        图解:

          

        编程模式:

          Model(模式)

            是应用程序中用于处理应用程序数据逻辑的部分

            通常模型对象负责在数据库中存取数据

          View(视图)

            是应用程序中处理数据显示的部分

            通常视图是依据模型数据创建的

          Controller(控制器)

            是应用程序中处理用户交互的部分

            通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据

        优点:

          降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的复用

      MTV:

        概述:本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同

        编程模式:

          Model(模型):负责业务对象与数据库的对象(ORM)

          Template(模版):负责如何把页面展示给用户

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

        注意:Django还有一个url分发器,它的作用是将一个个URL的页面请求 分发给不同的view处理,view再调用相应的Model和Template

    二、Django创建项目

      在合适位置创建一个文件夹

      打开黑屏终端进入到上一步创建的文件夹目录下

      输入命令:django-admin  startproject  project

      目录层级说明:

        manage.py:一个命令行工具,可以使我们用多种方式对Django项目进行交互

        project目录:

          __init__.py:一个空文件,它告诉python这个目录应该被看作一个python包

          settings.py:项目的配置文件

          urls.py:项目的URL声明

          wsgi.py:项目与WSGI兼容的Web服务器入口

    三、Django基本操作

      1、设计表结构:这个不同的项目设计的表结构不同,这里不详细说

      2、配置数据库

        启动数据库:net  start  mysql

        注意:Django默认使用的是SQLite数据库

        在settings.py文件中,通过DATABASES选项进行数据库配置

        配置MySQL:

          python3.x安装的是PyMySQL

          在__init__.py文件中写入两行代码 

            
    1 import pymysql
    2 pymysql.install_as_MySQLdb()
    View Code

          格式    

            
    1 DATABASES = {
    2     'default': {        'ENGINE''django.db.backends.mysql',
    3                             'NAME': "数据库名",     
    4                             'USER': '用户名',
    5                             'PASSWORD': '数据库密码',
    6                             'HOST': '数据库服务器IP',
    7                             'PORT': '端口',
    8     }
    9 }                
    View Code

      3、创建应用

        在一个项目中可以创建多个应用,每个应用进行一种业务处理

        打开黑屏终端进入上次创建文件夹下的project目录

        执行命令:python  manage.py  startapp myApp

        myApp目录说明:

          admin.py:站点配置

          models.py:模型

          views.py:视图

      4、激活应用

        在settings.py文件中,将myApp应用加入到INSTALLED_APPS选项中 

          
    1 INSTALLED_APPS = [
    2     'django.contrib.admin',
    3     'django.contrib.auth',
    4     'django.contrib.contenttypes',
    5     'django.contrib.sessions',
    6     'django.contrib.messages',
    7     'django.contrib.staticfiles',
    8     'myApp',
    9 ]
    View Code

      5、定义模型

        概述:有一个数据表,就对应有一个模型

        在models.py文件中定义模型

          引入from django.db  import  models

          模型类要继承models.Model类,代码如下

            
     1 from django.db import models
     2 
     3 # Create your models here.
     4 
     5 class Grades(models.Model):
     6     # 定义模型类
     7     gname = models.CharField(max_length=20)
     8     gdate = models.DateTimeField()
     9     ggirlnum = models.IntegerField()
    10     gboynum = models.IntegerField()
    11     isDelete = models.BooleanField(default=False)
    12     
    13 class Students(models.Model):
    14     sname = models.CharField(max_length=20)
    15     sgender = models.BooleanField(default=True)
    16     sage = models.IntegerField()
    17     scontend = models.CharField(max_length=20)
    18     isDelete = models.BooleanField(default=False)
    19     # 关联外键
    20     sgrade = models.ForeignKey('Grades')
    View Code

        说明:不需要定义主键,在生成时自动添加,并且值为自动增加

      6、在数据库中生成数据表

         生成迁移文件: 

            执行命令:python  manage.py  makemigrations

            在migrations目录下生成一个迁移文件,此时,数据库中还没有生成数据表

         执行迁移:

            执行命令:python  manage.py  migrate  相当于执行SQL语句创建数据表

      7、测试数据操作

        进入到python  shell:

          执行命令:python  manage.py shell

        引入包: 

          1 from  myApp.models  import Grades,Students                          
          2 from datetime import *                                                  
          3 from django.utils import timezone

        查询所有数据:

          语法:类名.objects.all()

          示例:Grades.objects.all()

        添加数据:

          本质:创建一个模型类的对象实例

           
    1 >>> grade1 = Grades()
    2 >>> grade1.gname = "python04"
    3 >>> grade1.gdate = datetime(year=2017,month=7,day=17)
    4 >>> grade1.ggirlnum = 3
    5 >>> grade1.gboynum = 70
    6 >>> grade1.save()
    View Code

        查看某个对象:

          语法:类名.objects.get(pk=2)

          示例:Grades.objects.get(pk=2)

        修改数据:

          语法:模型对象.属性 = 新值

          示例: 1 >>> grade2.gboynum = 60      2 >>> grade2.save() 

        删除数据:

          语法:模型对象.delete()

          示例:grade2.delete()

          注意:物理删除,数据库中的表里面的数据永久被删除

        关联对象:

           
    1 >>> grade1 = Grades.objects.get(pk=1)
    2 >>> stu = Students()
    3 >>> stu.sname = "薛艳梅"
    4 >>> stu.sgender = False
    5 >>> stu.sage = 20
    6 >>> stu.scontend = "我叫薛艳梅"
    7 >>> stu.sgrade = grade1
    8 >>> stu.save()
    View Code

          获得关联对象的集合:

            需求:获取python04班级的学生

            语法:对象名.关联的类名小写_set.all()

            示例:grade1.students_set.all()

          创建关联对象:

            stu3 = grade1.students_set.create(sname="曾志伟",sgender=True,scontend="我叫曾志伟",sage=45)

            注意:直接添加到数据库中

      8、启动服务器

        格式:python  manage.py  runserver  ip:port

          ip可以不写,不写的话代表本机ip

          端口号默认是8000

        说明: 这是一个纯python写的轻量级web服务器,仅仅在开发测试中使用

      9、Admin站点管理

        概述:内容发布(负责添加、修改删除内容)、公告访问

        配置admin应用:

          在settings.py文件中的INSTALLED_APPS中添加'django.contrib.admin',

          默认是已经添加的

        创建管理员用户:

          执行命令:python  manage.py  createsuperuser

          依次输入用户名、邮箱、密码

        汉化:

          修改settings.py文件

            LANGUAGE_CODE = 'zh-Hans'

            TIME_ZONE = 'Asia/Shanghai'

        管理数据表:

          修改admin.py文件

             
    1 from .models import Grades,Students
    2 admin.site.register(Grades)
    3 admin.site.register(Students)
    View Code

          自定义管理页面    

             
     1 from .models import Grades,Students
     2 # 注册
     3 class GradesAdmin(admin.ModelAdmin):
     4     # 列表页属性
     5     list_display = ['pk', 'gname', 'gdate', 'ggirlnum', 'gboynum', 'isDelete']
     6     list_filter = ['gname',]
     7     search_fields = ['gname']
     8     list_per_page = 5
     9     # 添加、修改页属性
    10     # fields = ['ggirlnum', 'gboynum', 'gname', 'gdate', 'isDelete']
    11     fieldsets = [
    12         ('num', {'fields':['ggirlnum', 'gboynum']}),
    13         ('base', {'fields':['gname', 'gdate', 'isDelete']})
    14     ]
    15 admin.site.register(Grades, GradesAdmin)
    View Code

          属性说明

            列表页属性   

                
    1 list_display        显示字段
    2 list_filter           过滤字段
    3 search_fields     搜索字段
    4 list_per_page    分页
    View Code

            添加、修改页属性

                
    1 fields        规定属性的先后顺序
    2 fieldsets    给属性分组
    3 注意:fields与fieldsets不能同时使用
    View Code

          关联对象

            需求:在创建一个班级时可以直接添加几个学生 

             
    1 class StudentsInfo(admin.TabularInline):  # StackedInline
    2     model = Students
    3     extra = 2
    4 class GradesAdmin(admin.ModelAdmin):
    5     inlines = [StudentsInfo]
    View Code

          布尔值显示问题  

             
     1 class StudentsAdmin(admin.ModelAdmin):
     2     def gender(self):
     3         if self.sgender:
     4             return ''
     5         else:
     6             return ''
     7     # 设置页面列的名称
     8     gender.short_description = "性别"
     9     list_display = ['pk', 'sname', 'sage', gender, 'scontend', 'sgrade', 'isDelete']
    10     list_per_page =  10
    11 admin.site.register(Students, StudentsAdmin)
    View Code

          执行动作位置  

             
     1 class StudentsAdmin(admin.ModelAdmin):
     2     def gender(self):
     3         if self.sgender:
     4             return ''
     5         else:
     6             return ''
     7     # 设置页面列的名称
     8     gender.short_description = "性别"
     9     list_display = ['pk', 'sname', 'sage', gender, 'scontend', 'sgrade', 'isDelete']
    10     list_per_page =  10
    11     # 执行动作的位置
    12     actions_on_top = False
    13     actions_on_bottom = True
    14 admin.site.register(Students, StudentsAdmin)
    View Code

        使用装饰器完成注册

           
     1 @admin.register(Students)
     2 class StudentsAdmin(admin.ModelAdmin):
     3     def gender(self):
     4         if self.sgender:
     5             return ''
     6         else:
     7             return ''
     8     # 设置页面列的名称
     9     gender.short_description = "性别"
    10     list_display = ['pk', 'sname', 'sage', gender, 'scontend', 'sgrade', 'isDelete']
    11     list_per_page =  10
    12     # 执行动作的位置
    13     actions_on_top = False
    14     actions_on_bottom = True
    15 # admin.site.register(Students, StudentsAdmin)
    View Code

      10、视图的基本使用

        概述:在django中视图对web请求进行回应,视图就是一个python函数,在views.py文件中定义

        定义视图:

           
    1 from django.http import HttpResponse
    2 def index(request):
    3     return HttpResponse("dylan is a good man")
    View Code

        配置URL:

          修改project目录下的urls.py文件

             
    1 from django.contrib import admin
    2 from django.conf.urls import url,include
    3 urlpatterns = [
    4     url(r'^admin/', admin.site.urls),
    5     url(r'^', include('myApp.urls')),
    6 ]
    View Code

          在myApp应用目录下创建一个urls.py文件

             
    1 from django.conf.urls import url
    2 from . import views
    3 urlpatterns = [
    4    url(r'^$', views.index)
    5 ]
    View Code

      11、模版的基本使用

        概述:模版是HTML页面,可以根据视图中传递过来的数据进行填充

        创建模版目录:创建templates目录,在目录下创建对应项目的模版目录(工程project/templates/myApp)

        配置模版路径:

          修改settings.py文件下的TEMPLATES,'DIRS': [os.path.join(BASE_DIR, 'templates')]

    四、Django模型

      概述:Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的调用API,可以根据不同的业务需求选择不同的数据库

      配置数据库:

        修改工程目录下的__init__.py文件

         1 import pymysql
         2 pymysql.install_as_MySQLdb()

        修改settings.py文件

         1 DATABASES = {
         2     'default': {
         3         'ENGINE': 'django.db.backends.mysql',  
         4         'NAME': "ying",    
         5         'USER': 'root',
         6         'PASSWORD': '123456',
         7         'HOST': 'localhost',
         8         'PORT': '3306',
         9     }
        10 }

      开发流程:

        配置数据库

        定义模型类:一个模型类都在数据库中对应一张数据表

        生成迁移文件

        执行迁移文件生成数据表

        使用模型类进行增、删、改、查(简称crud)操作

      ORM:

        概述:对象--关系--映射

        任务:

          根据对象的类型生成表结构

          将对象、列表的操作转换成SQL语句

          将SQL语句查询到的结果转换为对象、列表

        优点:极大的减轻了开发人员的工作量。不需要面对因数据库的变更而修改代码

         图解:

          

      定义模型:

        模型、属性、表、字段间的关系:

          一个模型类在数据库中对应一张表,在模型类中定义的属性,对应该模型对照表中的一个字段

        定义属性: 

          
    定义属性
    	概述
    		.django根据属性的类型确定以下信息
    			.当前选择的数据表支持字段的类型
    			.渲染管理表单时使用的默认html文件
    			.在管理站点最低限度的验证
    
    		.gjango会为表增加自动增长的主键列,每个模型只能有一个主键列,
    		如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
    
    		.属性命名限制
    			.遵循标识符规则 
    			.由于django的查询方式,不允许使用连续的下划线
    
    	库
    		.定义属性时,需要字段类型,字段类型被定义在django.db.models.fields
    		目录下,为了方便使用,被导入到django.db.models中
    
    		.使用方式
    			.导入from django.db. import models
    			.通过models.Field创建字段类型的对象,赋值给属性	
    
    	逻辑删除
    		.对于重要数据都要做逻辑删除,不做物理删除,实现方法是定义isDelete属性,
    		类型为BooleanField,默认值为False
    
    	字段类型
    		.AutoField
    			.一个根据实际ID自动增长的IntegerField,通常不指定如果不指定
    			一个主键字段将自动添加到模型中
    
    		.CharField(max_length=字符长度)
    			.字符串,默认的表单样式是TextInput
    
    		.TextField
    			.大文本字段,一般超过4000使用,默认的表单控件是Textarea
    
    		.IntegerField
    			.整数
    
    		.DecimalField(max_digits=None, decimal_places=None)
    			.使用python的Decimal实例表示的十进制浮点数
    			.参数说明
    				.DecimalField.max_digits
    					.位数总数
    				.DecimalField.decimal_places
    					.小数点后的数字位数	
    
    		.FloatField
    			.用python的float实例来表示的浮点数
    
    		.BooleanField
    			.true/false 字段,此字段的默认表单控制是CheckboxInput
    
    		.NullBooleanField
    			.支持null、true、false三种值
    
    		.DateField([auto_now=False, auto_now_add=False])
    			.使用python的datetime.date实例表示的日期
    			.参数说明
    				.DateField.auto_now
    					.每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"
    					的时间戳,它总是使用当前日期,默认为false
    				.DateField.auto_now_add
    					.当对象第一次被创建时自动设置为当前时间,用于创建的时间戳,它总是
    					使用当前日期,默认为false
    			.说明
    				.该字段 默认对应的表单控件是一个TextInput,在管理员站点添加了一个
    				JavaScript写的日历控件,和一个"Today"的快捷按钮,包含了一个额外的
    				invalid_date错误消息键
    			.注意
    				.auto_now_add, auto_now, and default这些设置是相互排斥的,他们之间的
    				任何组合将会发生错误的结果
    
    		.TimeField
    			.使用python的datetime.time实例表示的时间,参数同DateField 
    
    		.DateTimeField
    			.使用python的datetime.datetime实例表示的日期和时间,参数同DateField 
    
    		.FileField
    			.一个上传文件的字段
    
    		.ImageField
    			.继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
    
    	字段选项
    		.概述
    			.通过字段选项,可以实现对字段的约束
    			.在字段对象时通过关键字参数指定
    
    		.null
    			.如果为True,Django将空值NULL存储到数据库中,默认值是False
    
    		.blanke
    			.如果为True,则该字段允许为空白,默认值是False
    
    		.注意
    			.null是数据库范畴的概念,blank是表单验证范畴的概念
    
    		.db_column
    			.字段的名称,如果未指定,则使用属性的名称
    
    		.db_index
    			.若值为True,则在表中会为此字段创建索引
    
    		.default
    			.默认值
    
    		.primary_key
    			.若为True,则该字段会成为模型的主键字段
    
    		.unique
    			.如果为True,这个字段在表中必须有唯一值
    
    	关系
    		.分类
    			.ForeignKey:一对多,将字段定义在多的端中
    			.ManyToManyField:多对多,将字段定义在两端中
    			.OneToOneField:一对一,将字段定义在任意一端中
    
    		.用一访问多
    			.格式
    				.对象.模型类小写_set
    			.示例
    				grade.students_set
    
    		.用一访问一
    			.格式
    				.对象.模型类小写
    			.示例
    				.grade.students
    
    		.访问id
    			.格式
    				.对象.属性_id
    			.示例
    				.student.sgrade_id
    View Code

        创建模型类:

          
     1 class Students(models.Model):
     2     # 定义一个类方法创建对象,cls代表了Students类
     3     @classmethod
     4     def createStudent(cls, name, age, gender, contend, grade, lastT, createT, isD=False):
     5         stu = cls(sname=name, sage=age, sgender=gender, scontend=contend, sgrade=grade, lastTime=lastT,creatTime=createT, isDelete=isD)
     6         return stu
     7     # 自定义模型管理器
     8     # 当自定义模型管理器时,objects就不存在了
     9     stuObj = models.Manager()
    10     stuObj2 = StudentsManager()
    View Code

        元选项:

          在模型类中定义Meta类,用于设置元信息

          定义数据表名,推荐使用小写字母,如果不写,数据表名默认为项目名小写_类名小写

             
    1 class Meta:
    2     db_table="students"
    3     ordering=['id']
    View Code

          对象的默认排序字段,获取对象的列表时使用 

             
    1 ordering=['id']    升序
    2 ordering=['-id']   降序
    View Code

            注意:排序会增加数据库的开销

        指定一个主键,创建表时就不会自动生成id

      模型成员:

        类属性:

          objects是Manager类型的一个对象,作用是与数据库进行交互,当定义模型类时没有指定管理器,则Django为模型创建一个名为objects的管理器

        自定义管理器:

          stuObj = models.Manager()

          当为模型指定模型管理器,Django就不再为模型类生成objects模型管理器

        自定义管理器Manager类:

          模型管理器是Django的模型与数据库进行交互的接口,一个模型可以有多个模型管理器

          作用:

            向管理器类中添加额外的方法

            修改管理器返回的原始查询集(重写get_queryset()方法)

          代码示例:

             
    1 class StudentsManager(models.Manager):
    2     def get_queryset(self):
    3         return super(StudentsManager,self).get_queryset().filter(isDelete=False)
    4 
    5 class Students(models.Model):
    6     # 自定义模型管理器
    7     # 当自定义模型管理器时,objects就不存在了
    8     stuObj = models.Manager()
    9     stuObj2 = StudentsManager()
    View Code

        创建对象:

          目的:向数据库中添加数据

          当创建对象时,Django不会对数据库进行读写操作,当调用save()方法时才与数据库交互,将对象保存到数据库表中

          注意:__init__()方法已经在父类models.Model中使用,在自定义的模型中无法使用

          方法:

            在模型类中增加一个类方法

               
    1 class Students(models.Model):
    2     # 定义一个类方法创建对象,cls代表了Students类
    3     @classmethod
    4     def createStudent(cls, name, age, gender, contend, grade, lastT, createT, isD=False):
    5         stu = cls(sname=name, sage=age, sgender=gender, scontend=contend, sgrade=grade, lastTime=lastT,creatTime=createT, isDelete=isD)
    6         return stu
    View Code

            在定义管理器中添加一个方法

                
     1 class StudentsManager(models.Manager):
     2     def get_queryset(self):
     3         return super(StudentsManager,self).get_queryset().filter(isDelete=False)
     4     # 在管理器中添加一个方法
     5     def createStudent(self, name, age, gender, contend, grade, lastT, createT, isD=False):
     6         stu = self.model()
     7         stu.sname = name
     8         stu.sage = age
     9         stu.sgender = gender
    10         stu.scontend = contend
    11         stu.sgrade = grade
    12         stu.lastTime = lastT
    13         stu.creatTime = createT
    14         stu.isDelete = isD
    15         return stu
    View Code

      模型查询:

        概述:  

          查询集:表示从数据库中获取的对象集合

          查询集可以有多个过滤器

          过滤器就是一个函数,基于所给的参数限制查询集结果

          从sql角度来说,查询集和select语句等价,过滤器就像where条件

        查询集:

          在管理器上调用过滤器方法返回查询集

          查询集经过过滤器筛选后产生新的查询集,所以可以写成链式调用

          惰性执行:创建查询集不会带来任何数据的访问,直到调用数据时,才会访问数据

          直接访问数据的情况:迭代、序列化、与if合用

          返回查询集的方法称为过滤器

             
    1 all():返回查询集中的所有数据
    2 filter():返回符合条件的数据
    3     filter(键=值)
    4     filter(键=值,键=值)
    5     filter(键=值).filter(键=值)
    6 exclude():过滤掉符合条件的数据
    7 order_by():排序
    8 values():一条数据就是一个对象(字典),返回一个列表
    View Code

          返回单个数据

             
    1 get():返回一个满足条件的对象
    2     注意:如果没有找到符合条件的对象,会引发"模型类.DoesNotExist"异常;如果找到多个对象,会引发"模型类.MultipleObjectsReturned"异常
    3 count():返回当前查询集中的对象个数
    4 first():返回当前查询集中的第一个对象
    5 last():返回当前查询集中的最后一个对象
    6 exists():判断查询集中是否有数据,如果有数据返回True,否则返回False
    7             
    View Code

          限制查询集:查询集返回列表,可以使用下标的方法进行限制,等同于sql中的limit语句

            studentsList = Students.stuObj2.all()[0:5]

            注意:下表不能是负数

          查询集的缓存:

            概述:每个查询集都包含一个缓存,来最小化的对数据库访问;在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存。django会将查询出来                                         的数据做一个缓存,  并返回查询结果,以后的查询直接使用查询集的缓存

          字段查询:

            概述:实现了sql中的where语句,作为方法filter()、exclude()、get()的参数

            语法:属性名称__比较运算符=值

            外键:属性名_id

            转义:like语句中使用%是为了匹配占位。匹配数据中的%(where like "\%")

            比较运算符:

              exact:判断,大小写敏感
              contains:是否包含,大小写敏感
              startswith:以value开头,大小写敏感
              endswith:以value结尾,大小写敏感
              以上四个在前面加上 i,就表示不区分大小写iexact、icontains、istartswith、iendswith
              isnull、isnotnull:是否为空
              in:是否包含在范围内
              gt、gte、lt、lte:大于、大于等于、小于、小于等于
              year、month 、day、week_day、hour、minute、second
              跨关联查询:
                  处理join查询:
                      语法:模型类名_属性名_比较运算符
              查询快捷:pk(代表的是主键)

            聚合函数:

              使用aggregate()函数返回聚合函数的值,还有Avg()、Count()、Max()、Min()、Sum()

            F对象:可以使用模型的A属性与B属性进行比较

                
    1 from django.db.models import F
    2 def grades(request):
    3     g = Grades.objects.filter(ggirlnum__gt=F('gboynum'))
    4     print(g)
    5     return HttpResponse("************")
    6 
    7 支持F对象的算术运算:
    8     g = Grades.objects.filter(ggirlnum__gt=F('gboynum')+20)
    View Code

            Q对象:

              概述:过滤器的方法中的关键字参数,条件为And模式

              需求:进行or查询

              解决:使用Q对象 

                  
    1 from django.db.models import Q
    2 studentsList = Students.stuObj2.filter(Q(pk__lt=3) | Q(sage__gt=50))
    3 studentsList = Students.stuObj2.filter(Q(pk__lt=3)) #只有一个Q对象,就是用于匹配的
    4 studentsList = Students.stuObj2.filter(~Q(pk__lt=3)) #取反
    View Code    
  • 相关阅读:
    SOUI开发者论坛
    第二十五篇:在SOUI中做事件分发处理
    第二十四篇:导出SOUI对象到LUA脚本
    第二十三篇:在SOUI中使用LUA脚本开发界面
    第四章:为妹子镶上璀璨的珠宝
    第三章:为妹子重塑婀娜身段
    第二章:美丽的幻想灰飞烟灭
    第一章:描绘妹子的靓影
    拥抱ARM妹子 序章!ARM妹子~~ 哥我来啦!
    一个比较方便的关闭进程函数
  • 原文地址:https://www.cnblogs.com/ccmldl/p/9606388.html
Copyright © 2011-2022 走看看