Django-6:django模型层ORM-2

16 篇文章 2 订阅

ORM-2

一、django测试文件

django中的应用目录里,会自带一个test.py的文件,可以供我们做一些测试脚本,不用书写前后端交互的形式来查看效果。

  • 缺点:不能立即使用,直接书写代码并执行会报错,需要先拷贝几行代码。

配置方法:

  • 一、前往manage.py中拷贝前四行代码

    # 将manage.py文件中的前四行,拷贝到test.py文件
    import os
    import sys
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoProject.settings")
    

    注意,这里的djangoProject以实际的项目命名为主,否则会报错,报错如下:

    ModuleNotFoundError: No module named ‘djangoProject’

  • 二、再补充两行

    # test.py文件
    import os
    # import sys 可以删掉,因为不需要这个模块就可以。
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoProject.settings")
        import django
        django.setup()
        
        # 测试脚本代码1
    	# 测试脚本代码2
       	.......
    

脚本代码,无论是写在应用下的tests.py,还是自己单独开设py文件,只要按照上面的两步走,配置完成之后都可以

二、ORM常用方法

汇总一览:

函数名说明
all()返回表中所有的数据,返回值为QuerySet对象
filter(条件)过滤查询,当没有条件时会和all一样,返回所有
get()过滤查询,不过与filter不同,返回值为数据对象,会报错不建议
first()QuerySet对象的方法,用于获取内部第一个数据对象,反义词是last()
values()QuerySet对象的方法,可获取指定字段的数据,返回的数据格式为列表套字典的QuerySet对象
values_list()与values()类似,不过返回的是列表套元祖格式的QuerySet对象
distinct()对获取到的数据进行去重处理
order_by()需要结合values()使用,可用于将获取到的数据对象,按照指定字段,从小到大或者大到小排列。
reverse()针对order_by()的排序进行反转
count()结合filter()使用,可以统计符合条件的个数
exclude()除了…以外

一、all()

  • 作用:返回表中所有的数据,返回值为QuerySet对象

    res = models.User.objects.all()
    '''
    输出结果示例:<QuerySet [<User: User object>, <User: User object>, <User: User object>, .....]>
    '''
    

二、filter()

  • 作用:过滤查询,也可以全部查询,返回值为QuerySet对象

    res1 = models.User.objects.filter()
    res2 = models.User.objects.filter(pk=1)  #主键值为1的数据
    '''
    输出结果示例:
    	<QuerySet [<User: User object>, <User: User object>, <User: User object>, .....]>
    	<QuerySet [<User: User object>]>
    '''
    

三、get()

  • 作用:过滤查询,与filter不同的是,get获取的直接就是数据对象,不需要再使用first()来从QuerySet对象中获取。

    ​ 但是该方法一旦查询不到就会报错,不建议使用,建议使用filter,因为当没查询到时,QuerySet对象会为空,但不会报错。

res1 = models.User.objects.get(pk=1
  print(res1.username)
  res2 = models.User.objects.get(pk=100)
  '''
  输出结果示例:
  	User object
  	数据对象中字段名为username的值
  	报错:User matching query does not exist.   翻译:用户匹配查询不存在。
  '''

四、first()与last()

  • 作用:获取QuerySet对象中第一和倒数第一的元素(数据对象)

    res = models.User.objects.filter(pk=1).first()
    '''
    输出结果示例:User object
    '''
    

五、values()与values_list()

  • 作用:QuerySet对象(列表套数据对象)调用后,可以获取指定字段的数据。

    • values,返回的是列表套字典格式的QuerySet对象。
    • values_list,返回的是列表套元祖的QuerySet对象。
res1 = models.User.objects.values('username','age')  #获取这两个字段的数据。
print(res1)

res2 = models.User.objects.values_list('username', 'age')
print(res2)
'''
输出结果示例:
<QuerySet [{'username': '盖伦', 'age': 38}, {'username': '嘉文四世', 'age': 39}....]>
<QuerySet [('盖伦', 38), ('嘉文四世', 39), ('赵信', 59), ....]>
'''
1.values,返回的是列表套字典格式的QuerySet对象。
2.values_list,返回的是列表套元祖的QuerySet对象。

六、distinct()

  • 作用:返回去重之后的数据,但是去重的要求,必须是两个一模一样的数据才可以去重,如果带有主键值,那么肯定数据做不到一模一样。

    ​ 所以可以结合values来“过滤”掉主键的数据,只获取其他的。

    res = models.User.objects.values('password').distinct()  
    # 对查询到的所有字段为password的数据,进行去重
    #(并不会对数据库进行任何修改,只是获取查询的结果去重而已。)
    
    '''
    输出结果示例:
    <QuerySet [{'password': 123}, {'password': 123456}, {'password': 123321},......]>
    '''
    

**七、order_by() **

  • 作用:将获取到的数据对象,按照指定字段从小到大或者从大到小排列,因为需要指定字段排列,所以需要用到values

    res = models.User.objects.values('age').order_by('age')  # 获取每个数据对象的age字段数据,并按照
    print(res)
    '''
    输出结果示例:<QuerySet [{'age': 26}, {'age': 27}, {'age': 38}, {'age': 39}, .....]>
    '''
    

    默认从小到大排列,如果需要从大到小,只需要将order_by的参数添加一个“-”即可,代码示例如下:

    res = models.User.objects.values('age').order_by('-age')
    print(res)
    '''
    输出结果示例:<QuerySet [.....,{'age': 38}, {'age': 27}, {'age': 26}]>
    '''
    

八、reverse()

  • 作用:针对order_by的排序进行反转

    res = models.User.objects.values('age').order_by('-age').reverse() # 等同于order_by('age'),从大到小。
    

九、count()

  • 作用:计数,可用于统计符合条件的个数。

    res = models.Book.objects.filter(price__gt = 500).count()
    print(res)
    '''
    代码:统计书籍列表中,价格大于500的个数。
    输出结果示例: 4
    '''
    

十、exclude()

  • 作用:除了…以外

    models.User.objects.exclude(username='zhangsan')
    '''
    输出结果示例:<QuerySet [<User: User object>, <User: User object>, ......]>
    '''
    

2.1 附:查看内部sql语句

作用:

  • 在执行测试脚本时,可以看到实际SQL语句是那些,在数据库查询优化章节,会需要使用到。

方式一

  • queryset对象,可以 .query 查看内部的sql语句。
res = models.User.objects.filter(password=123).values('pk','username')
print(res.query)

'''
    控制台输出:
    SELECT `app01_user`.`id`, `app01_user`.`username` FROM `app01_user` WHERE `app01_user`.`password` = 123
'''

方式二

  • 配置文件配置,最终可实现所有sql都能直接查询,不需要再 .query
# settings.py文件
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

三、双下划线查询

汇总预览:

名称作用
__gt大于
__lt小于
__gte大于等于
__lte小于等于
__in=[值1,值2,值3…]值为列表中的其中之一(or的关系)
__range=[值1,值2]值为range的区间内(不过这里的range是首尾都要)
__contains=‘值’查询里面含有“值”的数据,注意:区分大小写
__icontains=‘值’查询里面含有“值”的数据,忽略大小写
__startswith=‘值’查询出名字以“值”为开头的数据(区分大小写)
__endswith=‘值’查询出名字以“值”为结尾的数据(区分大小写)

示例:

1.年龄大于35岁的数据
	res = models.User.objects.filter(age__gt=35)

2.年龄小于35岁的数据
	res = models.User.objects.filter(age__lt=35)

3.大于等于 
	res = models.User.objects.filter(age__gte=32)
    
4.小于等于
	res = models.User.objects.filter(age__lte=32)


5.年龄是18 或者 32 或者40
	res = models.User.objects.filter(age__in=[18,32,40])


6.年龄在1840岁之间的,首尾都要
	res = models.User.objects.filter(age__range=[18,40])


7.查询出名字里面含有s的数据  模糊查询(区分大小写)
	res = models.User.objects.filter(name__contains='s')

8.查询出名字里面含有p的数据 (忽略大小写)
	res = models.User.objects.filter(name__icontains='p')

9.查询出名字以j开头的数据(区分大小写)
	res = models.User.objects.filter(name__startswith='j')

10.查询出名字以j结尾的数据(区分大小写)
	res1 = models.User.objects.filter(name__endswith='j')

扩展

  • 当需要获取日期字段的数据时,可以使用__month和__year来获取月份和年份

    当该字段为日期时,可利用__month和__year来获取年月份。
    # 查询出注册时间是 2020   1月
    # res = models.User.objects.filter(register_time__month='1')
    # res = models.User.objects.filter(register_time__year='2020')
    

四、外键增删改

本章节主要介绍,如何利用外键,来给表中增删改查内容。

章节的准备代码:

'''
以下为models文件,构造表的字段、外键等。
'''
class Book(models.Model):
    title = models.CharField(max_length=32,verbose_name='title')
    price = models.DecimalField(max_digits=8,decimal_places=2,verbose_name='price')
    # 书与出版社是一对多关系
    publish = models.ForeignKey(to='Publish')
    # 与作者呈多对多关系
    authors = models.ManyToManyField(to='Author')

class Publish(models.Model):
    name = models.CharField(max_length=32,verbose_name='name')
    addr = models.CharField(max_length=42,verbose_name='addr')


class Author(models.Model):
    name = models.CharField(max_length=10,verbose_name='name')
    # 与书呈多对多关系
    # 与作者信息呈一对一关系
    author_info = models.OneToOneField(to='AuthorInfo')

class AuthorInfo(models.Model):
    hometown = models.CharField(max_length=42,verbose_name='hometown')
    introduction = models.CharField(max_length=70,verbose_name='introduction')

以测试脚本文件为例,给数据库中的表增加数据。

'''
以下为test.py文件
'''
	# book书籍表中添加数据
    models.Book.objects.create(title='《水浒传》',price=79.9)
    models.Book.objects.create(title='《红楼梦》',price=64.9)
    models.Book.objects.create(title='《西游记》',price=57.8)

    # publish出版社表中添加数据
    models.Publish.objects.create(name='《人民文学出版社》',addr='北京市朝阳门内大街166号')
    models.Publish.objects.create(name='《作家出版社》',addr='北京市朝阳区农展馆南里10号')
    models.Publish.objects.create(name='《北京图书馆出版社出版》',addr='北京市西城区文津街7号')

    # author作者表中添加数据
    models.Author.objects.create(name='施耐庵')
    models.Author.objects.create(name='罗贯中')
    models.Author.objects.create(name='曹雪芹')
    models.Author.objects.create(name='高鹗')
    models.Author.objects.create(name='吴承恩')

    # authorinfo作者详情表中添加数据
    models.AuthorInfo.objects.create(hometown='江苏',introduction='施耐庵(1296年—1370年),名耳,明代文学家。')
    models.AuthorInfo.objects.create(hometown='山西',introduction='罗贯中(约1330年-约1400年),太原人,号湖海散人,元末明初小说家。')
    models.AuthorInfo.objects.create(hometown='辽宁',introduction='曹雪芹(约1715年5月28日—约1763年2月12日),名霑,字梦阮,号雪芹,又号芹溪、芹圃,中国古典名著《红楼梦》的作者,')
    models.AuthorInfo.objects.create(hometown='辽宁',introduction='高鹗(1758年—约1815年),字云士,号秋甫,别号兰墅、行一、红楼外史。中国古典小说《红楼梦》出版史、传播史上首个刻印本、全璧本——程高本的两位主要编辑者、整理者、出版者之一。')
    models.AuthorInfo.objects.create(hometown='江苏',introduction='吴承恩(约1500年—1582年),字汝忠,号射阳居士,又称射阳山人,南直隶淮安府山阳县河下(今江苏淮安)人,祖籍安东。明代文学家。')

此时,我们的表里面以及有了一些基本的内容了,但是并没有真正的建立关联,最明显的,外键字段都是空。

所以后续的8.1和8.2章节,将介绍如何针对一对多多对多这两种情况,来给表中增添数据。

4.1 一对多 外键增删改

一对多的关系,也就是上面代码中的book表与publish表之间的关系,所以本小结主要针对这两个表进行操作。

一对一和一对多,都是一样的。

前言:

虚拟字段

  • 一本章节的代码为例

    class Book(models.Model):
        '''略'''
        publish = models.ForeignKey(to='Publish')
        authors = models.ManyToManyField(to='Author')
    
  
publish字段与authors字段,都是<font color='MediumPurple1'>虚拟外键字段</font>
  

  
  因为publish字段,会被ORM补全后缀,变成**publish_id**,所以<font color='MediumPurple1'>publish_id</font>才是真实的外键字段,这个<font color='MediumPurple1'>publish</font>就变成了不存在的字段。
  
  而authors字段更不存在,因为ORM会给多对多关系的两张表重新生成一个表,专门用来记录对应关系的,所以<font color='MediumPurple1'>authors 和 publish</font>都是<font color='MediumPurple1'>虚拟外键字段</font>

注:至于说publish和authors字段到底是叫做外键字段还是虚拟外键字段,这个不重要,本章节以及后续的正反向、子查询、连表查询这样可以搞明白怎么回事就好,个人是喜欢叫做虚拟外键字段。

一、增加

在添加书籍时,添加上外键的对应关系。

  • 第一种方法,利用数据库中实际字段publish_id ,赋值的方式添加数据,完成绑定。

    models.Book.objects.create(title='《水浒传》',price=49.9,publish_id=1)
    models.Book.objects.create(title='《红楼梦》',price=49.9,publish_id=2)
    models.Book.objects.create(title='《西游记》',price=49.9,publish_id=3)
    
  • 第二种方法,利用在models.py中书写的虚拟字段publish ,赋值一个出版社对象即可完成绑定。

    publish_obj = models.Publish.objects.filter(pk=1).first()  # 先拿到需要绑定的出版社对象。
    models.Book.objects.create(title='《测试》',price=999.99,publish=publish_obj) # 利用虚拟字段绑定。
    

二、删

删除本条数据,同时会解除其绑定关系(级联删除)

  • models.Publish.objects.filter(pk=1).delete()  # 级联删除
    

三、修改

  • 第一种方法:

    调用update函数,将publish_id这个实际字段赋值上出版社表数据的主键值。

    # 将主键值为1的书,与出版社表,主键值2的数据,进行绑定。
    models.Book.objects.filter(pk=1).update(publish_id=2)
    
  • 第二种方法:

    同样是调用update函数,但使用的是publish这个虚拟字段,随后赋值的就不是主键值,而是出版社对象。

    # 先获取出版社对象
    publish_obj = models.Publish.objects.filter(pk=1).first()
    
    # 利用update函数来给外键字段重新赋值。 
    models.Book.objects.filter(pk=1).update(publish=publish_obj)
    

四、查

  • filter()、all()、values()、values_list() 都是查,此处略。

4.2 多对多 外键增删改查

多对多的增删改查其实就是对那第三张虚拟表进行操作。

一、增

  • 第一种方法,通过**add(主键)**的方式。

    # 获取图书数据对象
    book_obj = models.Book.objects.filter(pk=1).first()
    
    # 图书对象 .虚拟字段  
    book_obj.authors  # 打印控制台会输出 app_01.Author.None
    
    book_obj.authors.add(1)  # 书籍id为1的书籍,添加绑定一个主键为1的作者。
    book_obj.authors.add(2,3) # 由于是多对多的关系,所以可以一次绑定多个
    '''
    .authors类似于已经到了第三张关系表了
    	book_obj.authors.add(4,5)
    	表示该书籍对象,与作者表主键值为4和5的数据,进行绑定
    '''
    

    这里的 authors为虚拟字段,不要和 author作者表混淆

  • 第二种方法,通过**add(对象)**的方式。

    author_obj1 = models.Author.objects.filter(pk=2).first()
    author_obj2 = models.Author.objects.filter(pk=3).first()
    
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.add(author_obj1,author_obj2)
    """
    add给第三张关系表添加数据
    	括号内既可以传数字也可以传对象,并且都支持多个。
    """
    
  • 代码示例:

    # 给书籍主键值2的数据,绑定author表主键值为3和4的数据。
    models.Book.objects.filter(pk=2).first().authors.add(3,4)
    
    # 给书籍主键值3的数据,绑定author表主键值为5的数据。
    models.Book.objects.filter(pk=3).first().authors.add(5)
    

二、删

  • 第一种方法,直接remove

    # 解除主键为5的书籍 与主键为5的作者  两者的关系清除
    # 也就是第三章表,即book_authors表
    models.Book.objects.filter(pk=4).first().authors.remove(5)
    
  • 第二种方法,remove传入对象。

    author_obj = models.Author.objects.filter(pk=5).first()
    models.Book.objects.filter(pk=4).first().authors.remove(author_obj)
    """
        remove
            括号内既可以传数字也可以传对象 并且都支持多个
    """
    

三、改

  • 函数名 set() ,不过在修改时,set的参数必须是个可迭代对象

    author_obj = models.Author.objects.filter(pk=5).first()
    author_obj2 = models.Author.objects.filter(pk=1).first()
    
    # 主键值为4的书籍,与作者表中主键为5和1的进行数据绑定。
    models.Book.objects.filter(pk=4).first().authors.set([author_obj,author_obj2])
    '''
    先获取作者对象,随后将指定书籍的作者进行重新赋值。
    '''
    

四、清空

  • 作用:清空在第三张关系表中某个书籍与作者的绑定关系

    # 先获取需要清空作者的书籍
    book_obj = models.Book.objects.filter(pk=1).first()
    # 在第三张关系表中清空某个书籍与作者的绑定关系
    book_obj.authors.clear()
    

五、多表查询

在8章节中,我们将多张表的数据通过外键进行的关联,关联之后要如何通过绑定的关系去跨表查询呢,

5.1 正反向查询的概念

正向查询:

  • 外键字段在哪个表,那么通过这个表查询就是正向

反向查询:

  • 外籍字段在对面,那么通过该表查对面就是反向

一对一和多对多正反向的判断也是如此

正向查询
反向查询
book表
外键字段book表
publish表
publish表
外键字段book表
book表

正反向查询的区别:查询时格式不一样:

  • 正向查询按照 .字段名小写(虚拟外键字段)
  • 反向查询按照 .表名小写._set

5.2 子查询

子查询:基于对象的跨表查询

一、需求:查询书籍主键为1的出版社、

分析:

  • 通过书查询出版社,即book --> publish,因为主键在book,所以本次查询为正向查询
  • 正向查询只需要**.字段名小写(虚拟字段)**即可。

代码示例:

  • book_obj.publish改行代码中的 publish 虚拟字段名而非表名。
book_obj = models.Book.objects.filter(pk=1).first()
res = book_obj.publish  
print(res)	# Publish object

print(res.name)  #输出对应出版社的名称
print(res.addr)  #地址

'''
先获取主键值为1的数据对象,随后通过这个书籍的数据对象,.publish虚拟外键字段,即可拿到本书与之关联的publish出版社数据对象。
有了数据对象之后 .字段名,也就是.name 就可以拿到对应出版社的名称。
'''

注意:

  • 不管是正向查询还是反向查询,只要数据对象不止一条时,都需要加上 .all()方法

    如:通过书籍查询作者,这种情况下,就需要用all()

    book_obj = models.Book.objects.filter(pk=1).first()
    print(book_obj.bind_authors.all())
    '''
    <QuerySet [<Author: Author object>, <Author: Author object>]>
    '''
    

    如何可以快速判断出是否需要加all方法:

    当看到返回值为 应用名..None 时,那么就需要加all()
    
    	如:app_01.Book.None
    

二、需求:查询出版社主键为2的所有书籍

分析:

  • 通过出版社查询书籍,主键在书籍表,那么就是反向查询
  • 反向查询需要按照表名小写._set

代码示例:

# 出版社对象
publish_obj = models.Publish.objects.filter(pk=2).first()  

# 出版社主键为2,所对应的书籍queryset对象
book_query = publish_obj.book_set.all()  


for book_obj in book_query:
    print(book_obj.title) # 拿到数据对象之后.title属性,即可获取图书的名称。
  • publish_obj.book_set.all()这里的book 表名

    因为一个出版社所出版的图书肯定不止一本,所以数据会有很多,需要再加上all()

三、需求:通过书籍,拿到作者简介

主键在book表,所以book表——虚拟字段——>author表,是正向查询。

此时再通过,author表——虚拟字段——>authorinfo表,查询对应书籍作者的详细信息,这段也是正向查询,因为主键在author表这边。

'''
查询book表中,主键值为3这本书的作者。
'''
# 书籍数据对象
book_obj = models.Book.objects.filter(pk=3).first()
# 案例为了节约篇幅,所以在该书的众多作者中,只选取QuerySet对象中的第一位作者数据对象
author_obj = book_obj.authors.all().first()

authorInfo_obj = author_obj.author_info  # 从作者表再跳到作者信息表中,获取对应作者信息对象。
print(authorInfo_obj.introduction)  # 打印对应字段的数据
  • book_obj.authors.all().first(),这里的authors虚拟字段名
  • author_obj.author_info,这里的author_info虚拟字段名

注意不要和表名混淆,做测试时可以将models.py中,建立表关系的时候,都把虚拟字段改成bind_publish、fk_publsh、fk_author等,这样可以更好的区分。

三、需求:通过作者名称,拿到该作者写的所有书籍名称

主键在book,所以通过作者对象进行查找,是反向查询

author_obj = models.Author.objects.filter(name='施耐庵').first()
book_query = author_obj.book_set.all()
# 此时book_query为queryset对象,里面的每个数据对象就是作者'施耐庵'所写的书。

9.3 联表查询

联表查询: 基于双下划线的跨表查询

代码示例:

一、找到《水浒传》这本书的作者和作者简介

res = models.Book.objects.filter(title='《水浒传》').values('authors__name','authors__author_info__introduction')
print(res)
print(type(res.first()))
'''
返回结果:
    <QuerySet [{'authors__name': '施耐庵', 'authors__author_info__introduction': '简介'}, 
    {'authors__name': '罗贯中', 'authors__author_info__introduction': '简介'}]>
    
    <class 'dict'>
'''

注意:

  • authors__name这里的authors可不是表名,而是虚拟字段,后面的__name为连表查询,查询的字段名为name。

    所以该行代码其实就是先通过authors虚拟字段,进入到第三章虚拟表,然后查询到对应author作者表的name字段。

  • authors__author_info__introduction这一行,同样是利用__双下划线后跟外键名(虚拟字段)实现跨表查询,以及查询表内字段值。

  • 另外,返回的结果虽然同样是QuerySet对象,但是里面不再是数据对象,而是字典格式

二、找到作者吴承恩,所出版的书和作者的简介

res = models.Author.objects.filter(name='吴承恩').values('book__title','author_info__introduction')
print(res)
# 输出结果示例:
# <QuerySet [{'book__title': '《西游记》', 'bind_author_info__hometown': '江苏'}]>
  • 通过作者查书,因为是反向查询,所以直接表名小写开头,在查询作者详情表时,为正向查询,以外键字段(虚拟字段)开头。

练习:

# 通过作者故乡,查到作者(一对一,反向)
    res = models.AuthorInfo.objects.values('author__name').filter(hometown='江苏')
    print(res)
    
# 通过作者查书(多对多,反向)
    res = models.Author.objects.filter(name='曹雪芹').values('book__title')
    print(res)
    
# 通过书查作者(多对多,正向)
    res = models.Book.objects.filter(title='《红楼梦》').values('authors__name')
    print(res)
    
# 通过书查出版社(一对多,正向)
    res = models.Book.objects.filter(title='《西游记》').values('publish__name')
    print(res)
    
# 通过出版社查书(一对多,反向)
    res = models.Publish.objects.filter(name='《北京图书馆出版社出版》').values('book__title')
    print(res)

基于对象和双下划线跨表查询的不同之处:

  • 子查询(基于对象的跨表查询),最后可以拿到的是数据对象,有了对象可以通过调用方法,来获取该对象的其他数据。

    <QuerySet [<Book: Book object>]>
    
  • 联表查询(基于双下划线的跨表查询),最后可以拿到的是字典

    <QuerySet [{'publish__name': '《人民文学出版社》'}]>
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿煜酱~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值