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

Django模型基础

文章目录

  • 一、models字段类型
    • 概述
    • 属性命名限制
    • 使用方式
    • 逻辑删除和物理删除
    • 常用字段类型
  • 二、常用字段参数
    • 常用字段选项(通过字段选项,可以实现对字段的约束)
  • 实践
      • 创建模型
      • 执行迁移命令 并 创建超级用户登录admin后台
      • 添加文件和图片字段
      • 定义模型字段和约束及在Admin后台管理系统的表单情况
  • 三、models基本操作
    • 3.1 增
      • 实践
        • 方式一
        • 方式二
        • 方式三
        • 方式四(不会报错)
      • 测试
      • 添加多条数据
    • 3.2 删
      • 删除多条数据
    • 3.3 修改数据
      • 修改多条数据
    • 3.4 查
      • get() 获取单条数据
      • all() 获取所有数据
      • first() 返回第一条数据
      • last() 返回最后一条数据
      • filter() 过滤
      • count(): 返当前查询集中的对象个数
      • exists():判断查询集中是否有数据
      • values(): 获取指定列的值
      • values_list():获取指定列的值
      • exclude() 排除,取反
      • 聚合
      • 排序
      • 分页功能
        • 手动分页
        • Django中的自动分页器
  • 四、Django模型进阶
    • 4.1 配置MySQL
      • 实践
        • 报错1:django.db.utils.NotSupportedError: MySQL 8 or later is required (found 5.7.26).
        • 报错2:RuntimeWarning: Got an error checking a consistent migration history performed for database connection 'default': (1045, "Access denied for user 'root'@'localhost' (using password: YES)")
    • 4.2 多模块关联关系
    • 4.3 Model连表结构
      • 4.3.1 一对多关联
      • 实践
        • 增加数据
        • 删除数据
        • 修改数据
        • 查询数据
          • 前三种查询
          • 第四种查询
      • 4.3.2 多对多关联
      • 实践
        • 添加数据
          • 写法一
          • 写法二
        • 修改数据
        • 删除数据
          • 删除电影
          • 删除用户
        • 查询
      • 4.3.3 一对一
        • 实践
          • 增删改
          • 查询


一、models字段类型

概述

django根据属性的类型确定以下信息

  • 当前选择的数据库支持字段的类型
  • 渲染管理表单时使用的默认html控件
  • 在管理站点最低限度的验证
    django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列。

属性命名限制

  • 遵循标识符规则
  • 由于django的查询方式,不允许使用连续的下划线,写一个下划线是可以的,写两个下划线_不可以
    定义属性时,需要字段类型,字段类型被定义在django.db.models.fields目录下,为了方便使用被导入到django.db.models中

使用方式

  • 导入from django.db import models
  • 通过models.Field 创建字段类型的对象,赋值给属性

逻辑删除和物理删除

对于重要数据都做逻辑删除,不做物理删除,实现方法是定义is_delete属性,类型为BooleanField,默认值为False
is_delete = models.BooleanField(default=False)

常用字段类型

  • AutoField

    • 一个根据实际ID自动增长的IntegerField,通常不指定,如果不指定,主键字段id将自动添加到模型中
  • CharField(max_length=字符长度)

    • 字符串,默认的表单样式是 Input
  • DecimalField(max_digits=None, decimal_places=None)

    • 使用python的Decimal实例表示的十进制浮点数
    • 参数说明
      • DecimalField.max_digits
        • 位数总数
      • DecimalField.decimal_places
        • 小数点后的数字位数
  • FloatField

    • 用Python的float实例来表示的浮点数
  • BooleanField

    • True/False 字段,此字段的默认表单控制是CheckboxInput
  • DateField( [auto_now=False, auto_now_add=False] )

    • 使用Python的datetime.date实例表示的日期
    • 参数说明
      • DateField.auto_now
        • 每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改”的时间戳,它总是使用当前日期, 默认为false
      • DateField.auto_now_add
        • 当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用创建时的日期默认为false
          注意: auto_now_add,auto_now,and default 这些设置是相互排斥的 , 他们之间的任何组合将会发生错误的结果
  • TimeField

    • 使用Python的datetime.time实例表示的时间,参数同DateField
  • DateTimeField

    • 使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
  • FileField

    • 一个上传文件的字段
  • ImageField

    • 继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image需要安装Pillow: "pip install Pillow"

二、常用字段参数

常用字段选项(通过字段选项,可以实现对字段的约束)

  1. null=True
    数据库中字段是否可以为空
  2. blank=True
    django的Admin 中添加数据时是否可允许空值

一般null=True & blank=True 搭配着用,出现null=True就用上blank=True

  1. primary_key = True
    主键,对AutoField设置主键后,就会代替原来的自增 id 列
  2. auto_now和 auto_now_add
    auto_now           自动创建 - - - 无论添加或修改,都是当前操作的时间
    auto_now_add   自动创建 - - - 永远是创建时的时间
  3. choices   (后台admin下拉菜单)
    USER_TYPE_LIST = (
       (1, “超级用户”),
       (2, ‘普通用户’),
    )
    user_type = models.IntegerField( choices=USER_TYPE_LIST, default=1, verbose_name=‘用户类型’)
  4. max_length 最大长度
  5. default 默认值
  6. verbose_name    Admin(后台显示的名称)中字段的显示名称
  7. name | db_column   数据库中的字段名称,在我做迁移的时候默认情况表当中的字段名称和写的属性名是一样的,如果想不一样就用name 或者 db_column 来指定
  8. unique=True   不允许重复
  9. db_index = True   数据库索引, 例如: 如果你想通过name查询的更快的话,给他设置为索引即可
  10. editable=True   在Admin里是否可编辑,不可编辑则不显示
  11. 设置表名
    class Meta:
      db_table = ‘person’

实践

新建一个项目Day03DjangoPro01
在这里插入图片描述

创建模型

App\models.py

from django.db import modelsclass UserModel(models.Model):# uid 它会成为主键,原来的id不会创建uid = models.AutoField(auto_created=True, primary_key=True)# CharField: 字符串类型      最大长度      unique唯一          db_index索引name = models.CharField(max_length=30, unique=True, db_index=True)# IntegerField: 整数类型, default默认值age = models.IntegerField(default=18)# BooleanField 类型sex = models.BooleanField(default=True)  # True男# TextField 大文本  null=True 可以为空  blank=True  在Admin管理页面可以为空info = models.TextField(null=True, blank=True)# FloatField 小数salary = models.FloatField(default=100000.456)# DecimalField 十进制小数  max_digits=9 总长度9 ,decimal_places=2 小数点后保留2位money = models.DecimalField(max_digits=9, decimal_places=2, default=0)# 日期birthday = models.DateField(default='2000-3-4')birthday2 = models.DateTimeField(auto_now=True)  # auto_now=True 每一次修改后都会自动修改该时间为最新的修改时间birthday3 = models.DateTimeField(auto_now_add=True)  # auto_now_add=True 第一次添加数据的时候的时间,以后不会修改

数据迁移

迁移的概念: 就是将模型映射到数据库的过程
生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

如果遇到 Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit and manually define a default value in models.py.
Select an option:

1)现在提供一次性默认值(将在所有现有行上设置此列的空值)
2)退出并在models.py中手动定义一个默认值。

这里是告诉你: 因为新添加了字段,原有数据因为没有这个新字段,那么1就是设置一次性默认值填入到之前的数据中;2 models.py中手动定义一个默认值default=。

Select an option: 输入1或者2 回车

创建超级用户
python manage.py createsuperuser
用户名 admin
密码 123456
弹出信息,你的密码太简单了太短了,至少八个字符,看你是否要使用,Y就是的使用


执行迁移命令 并 创建超级用户登录admin后台

App\admin.py

from django.contrib import adminfrom App.models import *# 后台管理系统的使用:
# 在这里注册对应的模型
admin.site.register(UserModel)

打开cmd

workon envdjango4
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser

访问admin后台: http://127.0.0.1:8000/admin/

在这里插入图片描述
在这里插入图片描述
添加一条数据,在数据库观察 birthday2 和 birthday3
在这里插入图片描述
在这里插入图片描述

修改刚刚添加的数据
在这里插入图片描述
可以看到 birthday2 发生了变化,birthday3 没有改变。

auto_now=True 每一次修改后都会自动修改该时间为最新的修改时间
auto_now_add=True 第一次添加数据的时候的时间,以后不会修改

添加文件和图片字段

App\models.py

# 既可以上传文件又可以上传图片
icon = models.FileField(null=True, blank=True, upload_to='static/uploads')  # upload_to 上传的地方

在这里插入图片描述
再重新生成迁移文件、执行迁移

python manage.py makemigrations
python manage.py migrate

执行完之后进入admin后台管理页面,点击添加
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


App\models.py

# 限制只能上传图片
icon2 = models.ImageField(null=True, blank=True, upload_to='static/uploads')

在这里插入图片描述
安装

# 1
python -m pip install Pillow
# 2
pip install Pillow
# 3 镜像
pip install pillow -i https://pypi.douban.com/simple

再重新生成迁移文件、执行迁移

python manage.py makemigrations
python manage.py migrate

执行完之后进入admin后台管理页面,点击添加

在这里插入图片描述

定义模型字段和约束及在Admin后台管理系统的表单情况

App\models.py

# 其他约束
choices = ((1, '青铜'), (2, '白银'), (3, '王者'))
# 保存到数据库当中的是前面的数字123,显示出来的是青铜白银王者,
#青铜白银王者在后台管理系统中会显示出来,实际上数据库存的是数字123
user_type = models.IntegerField(choices=choices, default=1,name='utype', verbose_name='用户类型')
user_type2 = models.IntegerField(default=1, editable=False,db_column='utype2', verbose_name='用户类型2')

再重新生成迁移文件、执行迁移

python manage.py makemigrations
python manage.py migrate

在这里插入图片描述

在这里插入图片描述
user_type在后台系统显示,user_type2不显示,是因为editable=False

三、models基本操作

一般的数据库操作流程:

  1. 创建数据库,设计表结构和字段
  2. 连接Mysql数据库,并编写数据访问层代码
  3. 业务逻辑层去调用数据访问层执行数据库操作

    Django通过Model操作数据库,不管你数据库的类型是MySql或者Sqlite,Django自动帮你生成相应数据库类型的SQL语句,所以不需要关注SQL语句和类型,对数据的操作Django帮我们自动完成。只要会写Model就可以了。
    django使用对象关系映射 (Object Relational Mapping,简称ORM) 框架去操控数据库。
    ORM(Object Relational Mapping) 对象关系映射,是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

3.1 增

# ORM:模型		<=>		表类结构	->		表结构对象		->		表的一条数据类属性	->		表的字段# models基本操作
# 增:1) 创建对象实例,然后调用save方法:obj = Author()obj.first_name = 'zhang'obj.last_name = 'san'obj.save()2)创建对象并初始化,再调用save方法:obj = Author(first_name='zhang',last_name='san')obj.save()3)使用create方法Author.objects.create(first_name='li',last_name='si')4)使用get_or_create方法,可以防止重复Author.objects.get_or_create(first_name='zhang', last_name='san')

实践

我们单独再创建一个模型吧

App\models.py

from django.db import models# 增删改查
class PersonModel(models.Model):name = models.CharField(max_length=30, unique=True)age = models.IntegerField(default=18)# 表名class Meta:db_table = 'person'

注意:我们的name设置的是unique唯一的, 后面实践会用到
生成迁移文件、执行迁移

python manage.py makemigrations
python manage.py migrate

在这里插入图片描述
就不写子路由了,根路由Day03DjangoPro01\urls.py

from django.contrib import admin
from django.urls import path
from App.views import *urlpatterns = [path('add/', add_person),  # 添加path('admin/', admin.site.urls),
]

方式一

App\views.py

from django.shortcuts import render, HttpResponsefrom App.models import *# 增加数据
def add_person(request):# 方式一try:p = PersonModel()p.name = '清风'p.age = 30p.save()  # 同步到数据库表中except Exception as e:return HttpResponse('add fail! 添加失败')return HttpResponse('add success! 添加成功')

方式二

App\views.py

def add_person(request):# 方式二try:p = PersonModel(name='微泫', age=26)p.save()  # 同步到数据库表中except Exception as e:return HttpResponse('add fail! 添加失败')return HttpResponse('add success! 添加成功')

方式三

App\views.py

def add_person(request):# 方式三try:PersonModel.objects.create(name='意境', age=26)except Exception as e:return HttpResponse('add fail! 添加失败')return HttpResponse('add success! 添加成功')

方式四(不会报错)

App\views.py

def add_person(request):# 方式四ret = PersonModel.objects.get_or_create(name='甘雨', age=26)print('ret: ', ret)# (<PersonModel: PersonModel object (3)>, False)  失败# (<PersonModel: PersonModel object (4)>, True) 成功print('type: ', type(ret))  # <class 'tuple'>print('Bool: ', ret[1])  # False 失败;True 成功if ret[1]:return HttpResponse('add success! 添加成功')return HttpResponse('add fail! 添加失败')

测试

http://127.0.0.1:8000/add/
第一次:
在这里插入图片描述

第二次:因为name我们设置的是唯一的,所以添加失败

在这里插入图片描述
在这里插入图片描述

添加多条数据

App\views.py

def add_person(request):# 添加多条数据for i in range(1, 10):PersonModel.objects.get_or_create(name=f'景{i}元', age=18 + i)return HttpResponse('add success! 添加成功')

http://127.0.0.1:8000/add/
在这里插入图片描述

3.2 删

使用Queryset的delete方法:# 删除指定条件的数据Author.objects.filter(first_name='zhang').delete()# 删除所有数据Author.objects.all().delete()注意: objects不能直接调用delete方法。使用模型对象的delete方法:obj = Author.objects.get(id=5)obj.delete()

根路由Day03DjangoPro01\urls.py

 path('del/', del_person),  # 删除

App\views.py

def del_person(request):# 删除数据# 1. 先找到要删除的数据# 2. 然后删除# 删除一条数据try:p = PersonModel.objects.first()  # 第一条数据p.delete()except Exception as e:return HttpResponse("删除失败!")return HttpResponse("删除成功!")

http://127.0.0.1:8000/del/
在这里插入图片描述

删除多条数据

def del_person(request):# 删除多条数据try:PersonModel.objects.filter(age__gt=23).delete()  # 条件年龄 age > 23 岁的except Exception as e:return HttpResponse("删除失败!")return HttpResponse("删除成功!")

3.3 修改数据

Author.objects,filter(last_name='dfdf').update(last_name='san')
模型没有定义update方法,直接给字段赋值,并调用save,能实现update的功能,比如:obj = Author.objects.get(id=3)obj.first_name ='zhang'obj.save()
save更新时会更新所有字段。如果只想更新某个字段,减少数据库操作,可以这么做:obj.first_name ='li'obj.save(update_fields=['first_name'])

Day03DjangoPro01\urls.py

path('update/', updete_person)

App\views.py

def updete_person(request):# 修改数据# 1. 先找到要修改的数据# 2. 然后修改try:# 修改一条数据p = PersonModel.objects.get(id=7)p.age = 110# p.save()  # 同步到数据库表中p.save(update_fields=['age'])  # 指定更新的字段,一定程度提高更新效率except Exception as e:return HttpResponse("修改失败!")return HttpResponse("修改成功!")

http://127.0.0.1:8000/update

在这里插入图片描述

修改多条数据

def updete_person(request):# 修改多条数据try:PersonModel.objects.all().update(age=66)except Exception as e:return HttpResponse("修改失败!")return HttpResponse("修改成功!")

PersonModel.objects.all() 是一个查询集

3.4 查

get(): 获取单条数据Author.objects.get(id=123)如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常如果找到多个,会引发模型类.MultipleObjectsReturned 异常
first():返回查询集(QuerySet)中的第一个对象
last():返回查询集中的最后一个对象
count():返当前查询集中的对象个数
exists():判断查询集中是否有数据,如果有数据返回True没有反之
a11():获取全部数据:Author.objects.al1()
values(): 获取指定列的值,可以传多个参数!返回包含字典的列表(保存了字段名和对应的值)Author.objects.all().values('password')
values_list():获取指定列的值,可以传多个参数!返回包含元组列表 (只保存值)Author.objects.al1().values_list('password')进阶操作:#获取个数Author.objects.filter(name='seven').count()Author.objects.filter(id__gt=1)# 获取id大于1的值# select * from Author where id > 1Author.objects.filter(id__gte=1)# 获取id大于或等于1的值# select * from Author where id >= 1Author.objects.filter(id__lt=10)# 获取id小于10的值# select * from Author where id < 10Author.objects.filter(id__lte=10)# 获取id小于或等于10的值# select * from Author where id <= 10Author.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值# select * from Author where id < 10 and id > 1Author.objects.filter(id__in=[11, 22, 33] ) # 获id在11、22、33中的数据# select * from Author where id in (11,22,33)Author.objects.exclude(id__in=[11, 22, 33]) # not in# select * from Author where id not in (11,22,33)Author.objects,filter(name__contains="ven") # contains (和数据库中like语法相同)# select * from Author where name like '%ven%'Author.objects.filter(name__icontains="ven") # icontains大小写不敏感Author.objects.filter(name__regex="^ven") # 正则匹配Author.objects.filter(name__iregex="^ven") # 正则匹配,忽略大小写Author.objects.filter(age__range=[10, 20])# 范围bettwen and 10-20# xx__startswith , xx__istartswith , xx__endswith, xx__iendswith:# 以什么开始,以什么结束,和上面一样带i的是大小写不敏感的,其实不带i的也忽略大小写Author.objects.filter(name='seven').order_by('id')# asc升序Author.objects.filter(name='seven').order_by('-id')# desc降序Author.objects.a11()[10:20] # 切片,取所有数据的10条到20条,分页的时候用的到#下标从0开始,不能为负数,可以实现分页#手动分页page 页码per_page 每页数量 =51(page=1):0-4 =>[0:5]2(page=2):5-9 =>[5:10]3(page=3):10-14 =>[10:15]4(page=4):15-19 =>[15:20]...每一页数据范围:(page-1)*per_page: page*per_page
#聚合使用aggregate()函数返回聚合函数的值Avg:平均值Count:数量Max:最大Min:最小Sum:求和from django.db.models import Count, Min, Max, SumAuthor.objects.aggregate(Max('age'))

注意双下划线__

Day03DjangoPro01\urls.py

path('get/', get_person),  # 查询

get() 获取单条数据

如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常
如果找到多个,会引发模型类.MultipleObjectsReturned 异常
App\views.py

# 查询数据
def get_person(request):# get(): 得到一个对象(一条数据)p = PersonModel.objects.get(id=8)print('*' * 52)print(p, type(p))print(p.name, p.age)print('*' * 52)return HttpResponse('查询成功')

http://127.0.0.1:8000/get/
在这里插入图片描述

加入我调用get() ‘’id=‘’不写会怎么样?

# p = PersonModel.objects.get(8) # 会报错

pk:primary key

p = PersonModel.objects.get(pk=8)  # pk:primary key

查询成功

注意1:get()只能返回一个对象, 不然会报错 MultipleObjectsReturned

p = PersonModel.objects.get(age=19)  # 数据库只有一个age=19,所以不会报错
p = PersonModel.objects.get(age=66)  # 数据库有很多age=66,所以报错 MultipleObjectsReturned

在这里插入图片描述

注意2:get() 查询结果不存在 DoesNotExist

 p = PersonModel.objects.get(age=1000)  # 数据库没有age=1000,所以报错 DoesNotExist

all() 获取所有数据

App\views.py

# 查询数据
def get_person(request):# 获取所有数据persons = PersonModel.objects.all()print(persons, type(persons))# QuerySet 查询集# 可以遍历查询集for p in persons:print(p.name, p.age)return HttpResponse('查询成功')
<QuerySet [<PersonModel: PersonModel object (7)>, <PersonModel: PersonModel object (8)>,<PersonModel: PersonModel object (9)>, <PersonModel: PersonModel object (10)>,<PersonModel: PersonModel object (11)>, <PersonModel: PersonModel object (16)>]> <class 'django.db.models.query.QuerySet'>
景1元 110
景2元 110
景3元 66
景4元 66
景5元 66
甘雨 19

类型:QuerySet 查询集

first() 返回第一条数据

返回queryset中匹配到的第一个对象,如果没有匹配到对象则为None,如果queryset没有定义排序,则按主键自动排序。

all[0]:
与 first() 不同,如果没有匹配到,会报IndexError错误。

App\views.py

def get_person(request):# 获取第一条数据p = PersonModel.objects.first()print(p.name, p.age)return HttpResponse('查询成功')

last() 返回最后一条数据

App\views.py

def get_person(request):# 获取最后一条数据p = PersonModel.objects.last()print(p.name, p.age)return HttpResponse('查询成功')

filter() 过滤

使用最多。类似数据库中的where语句
App\views.py

def get_person(request):persons = PersonModel.objects.filter()  # 默认没有条件, 得到所有数据persons = PersonModel.objects.filter(age__gt=100)  # age>100persons = PersonModel.objects.filter(age__gte=100)  # age>=100persons = PersonModel.objects.filter(age__lt=100)  # age<100persons = PersonModel.objects.filter(age__lte=100)  # age<=100persons = PersonModel.objects.filter(age=110)  # age=110print(persons.filter().filter())for p in persons:print('+++', p.name, p.age)return HttpResponse('查询成功')

就算只拿到一个数据,它也是一个查询集 QuerySet 。

查询集 QuerySet 可以继续去查询 filter ,内部会返回self ,所以它可以做链式调用。
在这里插入图片描述


count(): 返当前查询集中的对象个数

exists():判断查询集中是否有数据

App\views.py

def get_person(request):persons = PersonModel.objects.filter(age__gt=100)  # age>100for p in persons:print('+++', p.name, p.age)print(persons.exists())  # 查询集是否存在数据,如果存在则为True,否则为Falseprint(persons.count())  # 查询集中的数据个数return HttpResponse('查询成功')

values(): 获取指定列的值

可以传多个参数!返回包含字典的列表(保存了字段名和对应的值)

App\models.py

class PersonModel(models.Model):name = models.CharField(max_length=30, unique=True)age = models.IntegerField(default=18)# 表名class Meta:db_table = 'person'def __str__(self):return f'{self.name}-{self.age}'def __repr__(self):return f'{self.name}--{self.age}'

__str__方法大家应该都不陌生,它类似于Java当中的 toString 方法,可以根据我们的需要返回实例转化成字符串之后的结果。

__str__ 和 __repr__ 这两个函数都是将一个实例转成字符串。但是不同的是,两者的使用场景不同,其中__str__更加侧重展示。所以当我们print输出给用户或者使用str函数进行类型转化的时候,Python都会默认优先调用__str__函数。而__repr__更侧重于这个实例的报告,除了实例当中的内容之外,我们往往还会附上它的类相关的信息,因为这些内容是给开发者看的。所以当我们在交互式窗口输出的时候,它会优先调用__repr__。

App\views.py

def get_person(request):persons = PersonModel.objects.filter()  # 默认没有条件, 得到所有数据print("persons: ", persons)print("list(persons): ", list(persons))  # 将查询集强制转换成列表# values() :  列表套字典,包括字段和值print("persons.values(): ", persons.values())  # 列表套字典print("persons.values('name'): ", persons.values('name'))print("persons.values('name', 'age'): ", persons.values('name', 'age'))# values_list() : 列表套元组,只有值print("persons.values_list(): ", persons.values_list())print("persons.values_list('name', 'age'): ", persons.values_list('name', 'age'))  # 用法跟values一样return HttpResponse('查询成功')

结果:

persons:  <QuerySet [1--110,2--120,3--30,4--66,5--20, 甘雨--19]>
list(persons):  [1--110,2--120,3--30,4--66,5--20, 甘雨--19]
persons.values():  <QuerySet [{'id': 7, 'name': '景1元', 'age': 110}, {'id': 8, 'name': '景2元', 'age': 120}, {'id': 9, 'name': '景3元', 'age': 30}, {'id': 10, 'name': '景4元', 'age': 66}, {'id': 11, 'name': '景5元', 'age': 20}, {'id': 16, 'name': '甘雨', 'age': 19}]>
persons.values('name'):  <QuerySet [{'name': '景1元'}, {'name': '景2元'}, {'name': '景3元'}, {'name': '景4元'}, {'name': '景5元'}, {'name': '甘雨'}]>
persons.values('name', 'age'):  <QuerySet [{'name': '景1元', 'age': 110}, {'name': '景2元', 'age': 120}, {'name': '景3元', 'age': 30}, {'name': '景4元', 'age': 66}, {'name': '景5元', 'age': 20}, {'name': '甘雨', 'age': 19}]>
persons.values_list():  <QuerySet [(7, '景1元', 110), (8, '景2元', 120), (9, '景3元', 30), (10, '景4元', 66), (11, '景5元', 20), (16, '甘雨', 19)]>
persons.values_list('name', 'age'):  <QuerySet [('景1元', 110), ('景2元', 120), ('景3元', 30), ('景4元', 66), ('景5元', 20), ('甘雨', 19)]>

values_list():获取指定列的值

可以传多个参数!返回包含元组列表 (只保存值)


exclude() 排除,取反

App\views.py

def get_person(request):person = PersonModel.objects.filter(age__in=[20, 50, 30])  # inprint("person: ", person)person = PersonModel.objects.exclude(age__in=[20, 50, 30])  # not inprint("person: ", person)return HttpResponse('查询成功')

聚合

使用aggregate()函数返回聚合函数的值
    Avg:平均值
    Count:数量
    Max:最大
    Min:最小
    Sum:求和
from django.db.models import Count, Min, Max, Sum
PersonModel.objects.aggregate(Max(‘age’))
aggregate 是聚合的意思

App\views.py

from django.db.models import Count, Min, Max, Sum, Avg
def get_person(request):# 聚合函数result = PersonModel.objects.aggregate(Max('age'))  # 最大值print(result)  # {'age__max': 120}print(result['age__max'])  # 120return HttpResponse('查询成功')
def get_person(request):# 聚合函数result = PersonModel.objects.aggregate(Max('age'))  # 最大值 {'age__max': 120}result = PersonModel.objects.aggregate(Min('age'))  # 最小值 {'age__min': 19}result = PersonModel.objects.aggregate(Sum('age'))  # 求和 {'age__sum': 365}result = PersonModel.objects.aggregate(Avg('age'))  # 求平均 {'age__avg': 60.833333333333336}result = PersonModel.objects.aggregate(Count('age'))  # 统计个数 {'age__count': 6}print(result)return HttpResponse('查询成功')

排序

PersonModel.objects.all().order_by()
App\models.py

class PersonModel(models.Model):name = models.CharField(max_length=30, unique=True)age = models.IntegerField(default=18)# 表名class Meta:db_table = 'person'def __str__(self):return f'{self.id}-{self.name}-{self.age}'def __repr__(self):return f'{self.id}--{self.name}--{self.age}'

在这里插入图片描述
在这里插入图片描述

def get_person(request):# 聚合函数person = PersonModel.objects.all().order_by('age')  # 默认升序person = PersonModel.objects.all().order_by('age', 'id')  # 先age做升序,然后如果一样的用id来升序# 想要降序就加个负号-person = PersonModel.objects.all().order_by('age', '-id')  # 先age做升序,然后如果一样的用id来降序print(person)return HttpResponse('查询成功')

分页功能

手动分页

在这里插入图片描述

Day03DjangoPro01\urls.py

path('paginate/<int:page>/<int:per_page>/', paginate, name="paginate"),  # 分页功能

App\views.py

import math
# 分页功能
def paginate(request, page=1, per_page=10):# 页码:page=1# 每页数据数量:per_page=10'''思路:分页功能数据:[1,2,3,...,47]第几页   数据范围      下标范围        切片page=1, 1 ~ 10      0 ~ 9           [0:10]page=2, 11 ~ 20     10 ~ 19         [10:20]page=3, 21 ~ 30     20 ~ 29         [20:30]...page=n,                       [(n-1) * 10 : n * 10]page=page,                   [(page-1)*per_page : page*per_page]'''# 实现分页功能persons = PersonModel.objects.all()persons = persons[(page - 1) * per_page:page * per_page]# 求总页数total = PersonModel.objects.count()  # 总数据条数total_page = math.ceil(total / per_page)  # 总页数,可能是小数47/10,所以需要向上取整pages = range(1, total_page + 1)return render(request, "paginate.html", {"persons": persons,"pages": pages,"per_page": per_page})

templates\paginate.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>分页功能的实现</title><style>ul{list-style: none;padding: 0;}.btns{display: flex ;align-content: center;}.btns li{margin: 5px;}</style>
</head>
<body><h2>分页功能</h2><hr>页数:{{ per_page }}<ul class="btns">
{#        <li>#}
{#            <a href="{% url 'paginate' 1 10 %}"><button>1</button></a>#}
{#        </li>#}
{#         <li>#}
{#            <a href="{% url 'paginate' 2 10 %}"><button>2</button></a>#}
{#        </li>#}
{#         <li>#}
{#            <a href="{% url 'paginate' 3 10 %}"><button>3</button></a>#}
{#        </li>#}{% for page in pages %}<li><a href="{% url 'paginate' page per_page %}"><button>{{ page }}</button></a></li>{% endfor %}</ul><hr><ul>{% for person in persons %}<li>{{ person.name }} - {{ person.age }}</li>{% endfor %}</ul>
</body>
</html>

浏览器http://127.0.0.1:8000/paginate/1/10/

在这里插入图片描述

这就是最基本的分页功能啦!!!

Django中的自动分页器

Day03DjangoPro01\urls.py

path('paginate2/<int:page>/', paginate2, name="paginate2"),

App\views.py

# 分页器:自动分页
from django.core.paginator import Paginatordef paginate2(request, page=1):per_page = 10  # 每页数据数量all_data = PersonModel.objects.all()# 使用分页器paginator = Paginator(all_data, per_page)persons = paginator.page(page)  # 获取第page页的数据pages = paginator.page_range  # 页码的范围,可以遍历data = {"persons": persons,"pages": pages,"per_page": per_page}return render(request, "paginate2.html", data)

新建一个 templates\paginate2.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>分页器</title><style>ul{list-style: none;padding: 0;}.btns{display: flex ;align-content: center;}.btns li{margin: 5px;}</style>
</head>
<body><h2>分页器</h2><hr>页数:{{ per_page }}<ul class="btns">{% for page in pages %}<li><a href="{% url 'paginate2' page %}"><button>{{ page }}</button></a></li>{% endfor %}</ul><hr><ul>{% for person in persons %}<li>{{ person.name }} - {{ person.age }}</li>{% endfor %}</ul>
</body>
</html>

浏览器 http://127.0.0.1:8000/paginate2/1/
在这里插入图片描述

四、Django模型进阶

MYSQL和SQLite只是数据库不一样,配置不一样,其他的是一样的。

注意:我的 Django版本是4.2,MYSQL是8.0,Python 3.11.3

4.1 配置MySQL

1.安装mysql2.MySQL驱动使用mysqlclientpip install mysqlclient(如果上面的命令安装失败,则尝试使用国内豆瓣源安装:pip install -i https://pypi.douban.com/simple mysqlclient)(Linux Ubuntu下需要先安装:apt install libmysqld-dev再安装:apt install libmysqld-dev)3.在Django中配置和使用mysq1数据库
使用mysql数据库,settings中配置如下DATABASES={'default':{'ENGINE':'django.db.backends.mysql','NAME':'mydb','USER':'root','PASSWORD':'123456','HOST':'127.0.0.1','PORT':'3306',}}

实践

在这里插入图片描述

workon envdjango4
pip install mysqlclient

新建一个新的项目Day04DjangoPro01

在这里插入图片描述

DATABASES = {# MySQL 数据库配置'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'mydb',  # 数据库名字'USER': 'root',  # 数据库的用户名'PASSWORD': '123456',  # 用户名对应的密码'HOST': '127.0.0.1',  # 数据库的主机IP'PORT': '3306',  # 端口}# SQLite 数据库配置# 'default': {#     'ENGINE': 'django.db.backends.sqlite3',#     'NAME': BASE_DIR / 'db.sqlite3',# }
}

在这里插入图片描述

mysql -u root -p
输密码	我的是 123456
看一下数据库 show databases
创建新的数据库  create datadase 数据库名 charset=utf8;注意这个数据库要求是一个空的数据库
使用数据库use 数据库名show tables;

怎么安装MySQL这里就不写了, 我偷懒就直接用小P(phpstudy)吧。网盘链接:https://pan.baidu.com/s/1Hc_oHRem4pY3VSmqCrbCjw?pwd=6666
提取码:6666

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们知道Django项目里面它自带本身有很多迁移文件,我们是不是可以把内部的迁移文件生成到数据库里面去呀?
生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

在这里插入图片描述
在这里插入图片描述
然后就成功啦!!!

报错1:django.db.utils.NotSupportedError: MySQL 8 or later is required (found 5.7.26).

说是MYSQL兼容问题
解决办法:数据库更新到 8.0就好啦

报错2:RuntimeWarning: Got an error checking a consistent migration history performed for database connection ‘default’: (1045, “Access denied for user ‘root’@‘localhost’ (using password: YES)”)

用户密码错了,所以连接不上。

4.2 多模块关联关系

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多个模块关联关联分类- ForeignKey:一对多,将字段定义在多的端中- ManyToManyField: 多对多,将字段定义在两端的任意一端中- OneToOneField:一对一,将字段定义在任意一端中一对多关系,举例说明 (一对一, 多对多类似) :一个班级可以有多个学生,一个学生只能属于一个班级class Grade(models.Model):name = models.CharField(max_length=20)class Student(models.Model):name = models.CharField(max_length=20)grade = models.ForeignKey(Grade)对象的使用:正向 (在Student这边,有grade属性的这一边):获取学生所在班级(对象):stu.grade获取学生所在班级的属性:stu.grade.name反向(在Grade这边):获取班级的所有学生(获取Manager对象):grade.student_set获取班级的所有学生(获取QuerySet查询集): grade.student_set.all()filter(),get()等操作中的使用:正向(在Student这边,有grade属性的这一边)Student.objects.filter(属性__name='1'): Student.objects.filter(grade__name='1')反向(在Grade这边)Grade.objects.filter(类名小写__id=7): Grade.objects.filter(student__id=7)

xx_set 其实是一个管理器 ,类似于 objects ,通过它 .filter() 或者 .all() 就可以拿到所有查询到的结果(叫查询集)。

4.3 Model连表结构

一对多: models.ForeignKey(其他表)
多对多: models.ManyToManyField(其他表)
一对一: models.OneToOneField(其他表)
应用场景:一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)例如: 创建用户信息时候,需要选择一个用户类型[普通用户][金牌用户][铂金用户]多对多:在某表中创建一行数据时,有一个可以多选的下拉框。 (猫眼App,淘票票,格拉瓦电影)例如:创建用户信息,需要为用户指定多个爱好。一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)例如:有个身份证表,有个person表。每个人只能有一张身份证,一张身份证也只能对应一个人,这就是一对一关系。

4.3.1 一对多关联

一对多关系,即外键为什么要用一对多。先来看一个例子。有一个用户信息表,其中有个用户类型字段,存储用户的用户类型。如下:class UserInfo(models.Model):username = models.CharField(max_length=32)age = models.IntegerField()user_type = models.CharField(max_length=10)不使用外键时用户类型存储在每一行数据中。如使用外键则只需要存储关联表的id即可,能够节省大量的存储空间。同时使用外键有利于维持数据完整性和一致性.当然也有缺点,数据库设计变的更复杂了。每次做DELETE 或者UPDATE都必须考虑外键约束。刚才的例子使用外键的情况: 单独定义一个用户类型表:class UserType(models.Model):caption = models.CharField(max_length=32)class UserInfo(models.Model):user_type = models.ForeignKey('UserType')username = models.CharField(max_length=32)age = models.IntegerField()我们约定:正向操作: ForeignKey在UserInfo表里,如果根据UserInfo去操作就是正向操作。反向操作: ForeignKey不在UserType里,如果根据UserType去操作就是反向操作。一对多的关系的增删改查:正向操作:1)创建对象实例,然后调用save方法obj = UserInfo(name='li',age=44, user_type_id=2)obj.save()2)使用create方法UserInfo.objects.create(name='li',age=44,user_type_id=2)3)使用get_or_create方法,可以防止重复UserInfo.objects.get_or_create(name='li',age=55,user_type_id=2)4)使用字典dic = {'name':'zhangsan', 'age':18, 'user_type_id':3}UserInfo.objects.create(**dic)5)通过对象添加usertype = UserType.objects.get(id=1)UserInfo.objects.create(name='li',age=55,user_type=usertype)删和普通模式一样删除即可。如:UserInfo,objects.filter(id=1).delete()改和普通模式一样修改即可。如:UserInfo.objects.filter(id=2).update(user_type_id=4)查正向查找所有用户类型为钻石用户的用户,使用双下划线:users = UserInfo.objects,filter(user_type__caption__contains='钻石')# __contains是过滤条件 like '%钻石%'正向获取关联表中的属性可以直接使用点.语法,比如:获取users查询集中第一个用户的caption:users[0].user_type.caption反向操作:(一般使用正向增即可)通过usertype来创建userinfo1)通过userinfo_set的create方法#获取usertype实例ut = UserType.objects.get(id=2)#创建userinfout.userinfo_set.create(name='smith',age=33)删删除操作可以在定义外键关系的时候,通过on_delete参数来配置删除时做的操作。on_delete参数主要有以下几个可选值:models.CASCADE	默认值(Django1.11),表示级联删除,即删除UserType时,相关联的UserInfo也会被删除。models.PROTECT	保护模式, 阻止级联删除。如果UserType还有关联的User存在,那么他就阻止你不让你删除。删除的时候可能报错。models.SET_NULL 置空模式,设为null,null=True参数必须具备。删除UserType的时候不会将所关联的用户删掉,而是把关联的User外键的值置空models.SET_DEFAULT	置默认值	设为默认值,default参数必须具备。如果删除UserType,关联的User外键的值不置空,设置成指定的值models.SET(函数名)	删除的时候重新动态指向一个实体访问对应元素,可传函数models.DO_NOTHING 什么也不做。 (Django1.11)。外键不会动,但是这样关联的外键就是错误的。注意:修改on_delete参数之后需要重新同步数据库,如果使用的话。需要重新迁移!!!一般建议 PROTECT 或者 SET_NULL 或者 SET_DEFAULT改和普通模式一样,不会影响级联表查通过usertype对象来查用户类型为1的用户有哪些obj=UserType.objects.get(id=1)obj.userinfo_set.all()可以通过在定义foreignkey时指定related_name来修改默认的userinfo_set,比如指定related_name为infouser_type = models.ForeignKey('UserType', related_name='info')指定related_name之后,反向查的时候就变成了obj.info.all()获取用户类型为1且用户名为shuaige的用户obj.info.filter(username='shuaige')外键关系中,django自动给usertype加了一个叫做userinfo的属性。使用双下划线。可以通过userinfo提供的信息来查usertype (了解)user_type_obj = UserType.objects.get(userinfo__username='zs')

生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

实践

OneToMany\models.py

from django.db import models# 一对多 = 1:N
# 用户类型:用户 = 1:N
# 一种用户类型: 可以有多个用户
# 一个用户:只属于一个用户类型# 用户类型
class UserType(models.Model):name = models.CharField(max_length=30)# 用户
class User(models.Model):name = models.CharField(max_length=30)age = models.IntegerField(default=18)# 外键user_type = models.ForeignKey(UserType, on_delete=models.CASCADE)# models.CASCADE 级联删除,即删除UserType时,相关联的User也会被删除。

生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

在这里插入图片描述

注意:用户表(User)中我们代码写的是user_type,但是数据库写的是user_type_id,这个有区别,它的类型跟 用户类型(UserType) 的主键是一样的。我们在后面使用的时候,可以使用user_type也可以使用user_type_id,但其实得到user_type呢相当于得到上面UserType对象了 ,得到这个对象之后再去 .id .name是可以的。

在这里插入图片描述

增加数据

OneToMany\views.py

from django.shortcuts import render, HttpResponse
from OneToMany.models import *# 一对多关系# 添加数据
def add_user(request):# 给UserType添加数据user_types = ['青铜', '白银', '黄金', '钻石']for name in user_types:UserType.objects.create(name=name)return HttpResponse("添加成功")

根路由Day04DjangoPro01\urls.py

from django.contrib import admin
from django.urls import path
from OneToMany import views as onetomany_viewurlpatterns = [path('admin/', admin.site.urls),# onetomanypath('onetomany/adduser/', onetomany_view.add_user ),
]

运行python .\manage.py runserver

http://127.0.0.1:8000/onetomany/adduser/

在这里插入图片描述
添加完之后,代码注释了,现在写添加User表,OneToMany\views.py
第一种用 user_type_id= id

def add_user(request):# # 用完就注释# # 给UserType添加数据# user_types = ['青铜', '白银', '黄金', '钻石']# for name in user_types:#     UserType.objects.create(name=name)# 给User表添加数据for i in range(11, 30):User.objects.create(name=f'清风-{i}',age=i,user_type_id=i % 4 + 1)  # i % 4 + 1 = 1~4return HttpResponse("添加成功")

http://127.0.0.1:8000/onetomany/adduser/

在这里插入图片描述
第二种用 user_type= 用户类型的对象

def add_user(request):# # 用完就注释# # 给UserType添加数据# user_types = ['青铜', '白银', '黄金', '钻石']# for name in user_types:#     UserType.objects.create(name=name)# 给User表添加数据for i in range(11, 30):# User.objects.create(name=f'清风-{i}', age=i,#                     user_type_id=i % 4 + 1)  # i % 4 + 1 = 1~4User.objects.create(name=f'微泫-{i}', age=i + 100,user_type=UserType.objects.get(pk=i % 4 + 1))return HttpResponse("添加成功")

http://127.0.0.1:8000/onetomany/adduser/
在这里插入图片描述

删除数据

根路由Day04DjangoPro01\urls.py

path('onetomany/deluser/', onetomany_view.del_user),

OneToMany\views.py
删除用户数据

# 删除数据
def del_user(request):# 删除User数据User.objects.filter(id=6).delete()return HttpResponse('删除成功')

http://127.0.0.1:8000/onetomany/deluser/

删除UserType数据

def del_user(request):# 删除User数据# User.objects.filter(id=6).delete()# 删除UserType数据UserType.objects.filter(id=2).delete()return HttpResponse('删除成功')

http://127.0.0.1:8000/onetomany/deluser/

执行之后,可以观察到UserType表删除了id=2的数据,User表删除了外键user_type_id是2的数据。

因为前面Models设置了 models.CASCADE 表示级联删除,即删除UserType时,相关联的User也会被删除。

试试其他的模式

OneToMany\models.py

user_type = models.ForeignKey(UserType, on_delete=models.PROTECT)  # 保护模式

浏览器 http://127.0.0.1:8000/onetomany/deluser/
在这里插入图片描述

user_type = models.ForeignKey(UserType, on_delete=models.SET_NULL, null=True)  # 置空模式
user_type = models.ForeignKey(UserType, on_delete=models.SET_DEFAULT, default=1)  # 置默模式
def fn():return 4# 用户
class User(models.Model):name = models.CharField(max_length=30)age = models.IntegerField(default=18)# 外键# user_type = models.ForeignKey(UserType, on_delete=models.CASCADE)# models.CASCADE 级联删除,即删除UserType时,相关联的User也会被删除。# user_type = models.ForeignKey(UserType, on_delete=models.PROTECT)  # 保护模式# user_type = models.ForeignKey(UserType, on_delete=models.SET_NULL, null=True)  # 置空模式# user_type = models.ForeignKey(UserType, on_delete=models.SET_DEFAULT, default=1)  # 置默模式user_type = models.ForeignKey(UserType, on_delete=models.SET(fn))  # 删除的时候重新动态指向一个实体访问对应元素,可传函数

其实models.SET(函数名) 跟 models.SET_DEFAULT 差不多

user_type = models.ForeignKey(UserType, on_delete=models.DO_NOTHING)  # 什么都不做

测试完我们还是用 user_type = models.ForeignKey(UserType, on_delete=models.PROTECT) # 保护模式

生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

修改数据

和普通模式一样,不会影响级联表

根路由Day04DjangoPro01\urls.py

path('onetomany/updateuser/', onetomany_view.update_user),

OneToMany\views.py

# 修改数据
def update_user(request):# 修改UserTypeUserType.objects.filter(id=1).update(name="王者")return HttpResponse('修改成功')
def update_user(request):# 修改UserType# UserType.objects.filter(id=1).update(name="王者")# 修改UserUser.objects.filter(id=2).update(age=1000)return HttpResponse('修改成功')

http://127.0.0.1:8000/onetomany/updateuser/

查询数据

根路由Day04DjangoPro01\urls.py

path('onetomany/getuser/', onetomany_view.get_user),

正向查询:有属性的地方直接查询,写了外键的地方直接查就是正向查询,通过 用户User 查找他所对应的 用户类型UserType

反向查询:通过 用户类型UserType 查找 用户User


OneToMany\views.py
前三种查询

1、正向查询
2、反向查询
    UserType对象.user_set.all()
    主表对象.从表名_set.all()
3、在filter中
     User.objects.filter(UserType)
    相比于第2种_set , 从时间成本来考虑的话还是使用 filter 筛选效率更高一些。

# 查询数据
def get_user(request):# 1.正向查询:通过用户查找用户类型user = User.objects.get(id=2)print("用户:", user.name, user.age, user.user_type, user.user_type_id)# user.user_type => UserType对象print("用户所属的类型:", user.user_type.id, user.user_type.name)  # User所属UserType的所有数据print('-' * 60)# 2.反向查询:通过用户类型查找用户utype = UserType.objects.get(pk=1)print('UserType自己的属性', utype.id, utype.name)# user_set: 是内部自动生成的属性, 可以让你反向查询到所有用户User集合print(utype.user_set)  # OneToMany.User.None 你可以认为它是一个管理对象print(type(utype.user_set))  # RelatedManager 关联的管理器对象# <class 'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager'>print(utype.user_set.all())  # 所有数据的 查询集 QuerySetprint('+' * 60)# 3.在filter中还可以这么用# 比如:查找用户类型名称为'黄金'的所有用户users = User.objects.filter(user_type=UserType.objects.get(name='黄金'))  # 传入UserType对象users = User.objects.filter(user_type_id=4)  # 传入user_type_idusers = User.objects.filter(user_type__name='黄金')  # 传入UserType对象的name属性作为条件# filter(user_type__name='黄金') 加两个下划线__反向引用去查找print(users)return HttpResponse("查询成功")

第四种查询

4、related_name: 关联名称

related_name 是我们用于反向查找的内容。通常,为所有外键提供 related_name 是一个好习惯,而不是使用 Django 的默认相关名称。
related_name 默认是 小写外键的表名_set 或者也可以这么理解 子表的表名小写_set
主表 UserType表:表中有一个主键被其他表用来当外键的表。
从表(子表)User表:把另外一个表中的主键当做自己的外键的表。

    主表对象.从表名_set.all()
    主表对象.设置的related_name.all()

OneToMany\models.py

在这里插入图片描述

class User(models.Model):name = models.CharField(max_length=30)age = models.IntegerField(default=18)# 外键# related_name: 关联名称,设置反向查找的名称,原本 反向查找 使用的是user_set改为usersuser_type = models.ForeignKey(UserType, on_delete=models.PROTECT,related_name='users'  # 建议使用)

生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

OneToMany\views.py

def get_user(request):print('=' * 60)# 4.related_name: 关联名称utype = UserType.objects.get(pk=1)# print(utype.user_set.all())  # 会报错 AttributeError 'UserType' object has no attribute 'user_set'# 使用了related_name就不可以在使用带_set的属性print(utype.users.all())  # <QuerySet [<User: User object (2)>, ...] >return HttpResponse("查询成功")

执行完迁移之后,现在我们不能再用user_set了,使用就会报错AttributeError ‘UserType’ object has no attribute ‘user_set’。如果我们使用了related_name,原来的属性user_set就不能使用了。

使用了related_name就不可以在使用带_set的属性

在这里插入图片描述

4.3.2 多对多关联

在这里插入图片描述
多对多其实就是两个一对多,如果不在乎中间表 ,我们可以直接建两边的表,中间的不用管。

多对多关系针对多对多关系django会自动创建第三张表。也可以通过through参数指定第三张表。用户和组是典型的多对多关系:class Group(models.Model):name = models.CharField(max_length=20)def __str__(self):return self.nameclass User(models.Model):name = models.CharField(max_length=64)password = models.CharField(max_length=64)groups = models.ManyToManyField(Group)def __str__(self):return self.name操作::先分别创建user和group,再使用add关联u = User(name='aa', password='123')u.save()g = Group(name='g5')g.save()通过Manager对象使用add()方法u.groups.add(g) 或 g.user_set.add(u):和一对多类似,删除user或group会级联删除user_groups表中的关联数据改:和一对多类似,只修改当前表查:正向:查询id=2的用户所在的所有组groupu = User.objects.get(id=2)u.groups.al1()反向:查询id=1的组中包含的所有用户g = Group.objects.get(id=1)g.user_set.all()

实践

新建一个应用 叫 ManyToMany
python manage.py startapp ManyToMany
创建好之后一定要记得注册 Day04DjangoPro01\settings.py
在这里插入图片描述
ManyToMany\models.py

from django.db import models# 多对多
# 用户:电影 = N:M
# 一个用户可以收藏多部电影,一部电影可以被不同用户收藏# 电影
class Movie(models.Model):name = models.CharField(max_length=52)duration = models.IntegerField(default=90)  # 电影时长:默认90分钟# 用户
class User(models.Model):name = models.CharField(max_length=30)age = models.IntegerField(default=18)# 多对多关系movies = models.ManyToManyField(Movie)

生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate

在这里插入图片描述
可以看到创建了三个表。

添加数据

子路由不写了,直接写根路由上吧,Day04DjangoPro01\urls.py

在这里插入图片描述

写视图函数ManyToMany\views.py

from django.shortcuts import render, HttpResponse
from ManyToMany.models import *# 多对多# 增加数据
def add(request):# 添加User数据for i in range(1, 10):User.objects.create(name=f'张三{i}', age=i)# 添加Moviefor i in range(1, 10):Movie.objects.create(name=f'消失的她{i}', duration=100+i)return HttpResponse("添加成功")

http://127.0.0.1:8000/manytomany/add/

在这里插入图片描述
添加完这两个表之后,我们要添加中间表的数据

写法一

ManyToMany\views.py

def add(request):# 让 张三1 收藏 消失的她1user = User.objects.get(name='张三1')movie = Movie.objects.get(name='消失的她1')# 添加收藏user.movies.add(movie)  # 用户收藏电影return HttpResponse("添加成功")

浏览器 http://127.0.0.1:8000/manytomany/add/
可以多刷新几次试试,添加是不会重复的
在这里插入图片描述

写法二

ManyToMany\views.py

def add(request):# 让 张三1 收藏 消失的她2user = User.objects.get(name='张三1')movie = Movie.objects.get(name='消失的她2')# 添加收藏# user.movies.add(movie)  # 用户收藏电影movie.user_set.add(user)  # 让用户收藏电影return HttpResponse("添加成功")

浏览器 http://127.0.0.1:8000/manytomany/add/
在这里插入图片描述


手动添加点数据吧
在这里插入图片描述


修改数据

一般多对多关系中不涉及到中间表修改,如果要对单表修改那就跟前面的一样了。

删除数据

Day04DjangoPro01\urls.py

path('manytomany/delete/', manytomany_view.delete),
删除电影

ManyToMany\views.py

def delete(request):# 删除User# User.objects.get(id=9).delete()# 删除Movie# Movie.objects.get(id=9).delete()# 删除中间表user = User.objects.get(name='张三1')user.movies.filter(name='消失的她2').delete()  # 删除用户收藏的电影#  user.movies.filter 这里已经到了Movie,所以可以使用name,这个name是Movie的namereturn HttpResponse('删除成功')

http://127.0.0.1:8000/manytomany/delete/

效果:电影表中 name=消失的她2 都被删了,中间表有关 电影消失的她2 的数据 也被删了。

注意: 假如 中间表 张三1 没有收藏 消失的她2 的记录,中间表、电影表那么就不会有任何效果。

删除用户

效果其实类似,反过来就好了

ManyToMany\views.py

def delete(request):movie = Movie.objects.get(name='消失的她1')movie.user_set.filter(name='张三1').delete()return HttpResponse('删除成功')

http://127.0.0.1:8000/manytomany/delete/

查询

Day04DjangoPro01\urls.py

path('manytomany/get/', manytomany_view.get_user_movie),

ManyToMany\views.py

# 查询数据
def get_user_movie(request):# 获取用户收藏的所有电影user = User.objects.get(name='张三1')print(user.movies.all())# 获取电影被哪些用户收藏了movie = Movie.objects.get(name='消失的她1')print(movie.user_set.all())return HttpResponse("查询成功")

http://127.0.0.1:8000/manytomany/get/在这里插入图片描述
注意:我的数据表里的数据我另外又加回来了
    电影:1 消失的她1
    用户:1 张三1
在这里插入图片描述

4.3.3 一对一

一对一关系一对一不是数据库的一个连表操作,而是Django独有的一个连表操作。一对一关系相当于是特殊的一对多关系,只是相当于加了unique=True。一个人只能有一张身份证,一张身份证对应一个人,是一个典型的一对一关系。class IdCard(models.Model):idnum = models.IntegerField()def __str__(self):return str(self.idnum)class Person(models.Model):idcard = models.OneToOneField(IdCard) # 外键name = models.CharField(max_length=20)def __str__(self):return self.name一对一关系比较简单。两种表互相都有对方。比如:>>> lisi = Person.objects.get(id=3)>>> lisi.idcard<IdCard: 123456>>>> ids = IdCard.objects.get(id=3)>>> ids.person<Person: lisi>

实践

这里演示查询就可以了,其他的跟一对多差不多。

新建一个应用 叫 OneToOne
python manage.py startapp OneToOne
创建好之后一定要记得注册 Day04DjangoPro01\settings.py

在这里插入图片描述

OneToOne\models.py

from django.db import models# 身份证
class IDCard(models.Model):idcard_num = models.CharField(max_length=18, unique=True)address = models.CharField(max_length=200)# 用户表
class Person(models.Model):name = models.CharField(max_length=20)age = models.IntegerField(default=18)sex = models.BooleanField(default=True)  # True是男# 一对一关系idcard = models.OneToOneField(IDCard, on_delete=models.PROTECT)  # 外键

生成迁移文件: python manage.py makemigrations
执行迁移: python manage.py migrate
在这里插入图片描述

一对一 和 一对多 一样 ,只有两个表,不会产生中间表。

在这里插入图片描述

注意: Unique,唯一约束

数据库插入点数据
在这里插入图片描述

增删改

和一对多是类似的。

查询

和一对多是类似的,不同的是一对一得到的是 对方的对象 而不是 一个查询集。
Day04DjangoPro01\urls.py
在这里插入图片描述

OneToOne\views.py

from django.shortcuts import render, HttpResponse
from OneToOne.models import *# 一对一# 查询
def get(request):#  查找某个用户对应的身份证信息person = Person.objects.get(pk=1)print(person.idcard)  # 对象 IDCard object (1)print(person.idcard.idcard_num, person.idcard.address)# 查找身份证对应的用户idcard = IDCard.objects.get(pk=2)print(idcard.person)  # 对象 Person object (2)# 注意不是idcard.person_setprint(idcard.person.name, idcard.person.age, idcard.person.sex)return HttpResponse("查询成功")

注意:不是idcard.person_set ,是 idcard.person

http://127.0.0.1:8000/onetoone/get/

相关文章:

Django模型基础

文章目录 一、models字段类型概述属性命名限制使用方式逻辑删除和物理删除常用字段类型 二、常用字段参数常用字段选项(通过字段选项&#xff0c;可以实现对字段的约束) 实践创建模型执行迁移命令 并 创建超级用户登录admin后台添加文件和图片字段定义模型字段和约束及在Admin后…...

导读-Linux简介

Linux简介 ​ 总所周知&#xff0c;计算机系统包含硬件和软件两部分。硬件部分被称为裸机&#xff0c;主要包括中央处理器&#xff08;CPU&#xff09;、内存、外存和各种外部设备。软件部分主要包括系统软件和应用软件两部分。系统软件包括操作系统、汇编语言、编译程序、数据…...

判断平面中两射线是否相交的高效方法

1. 简介 最近在工作中遇到判断平面内两射线是否相交的问题。 对于这个问题的解决,常规的方法是将两条射线拓展为直线,计算直线的交点,而后判断交点是否在射线上。 这种方法,在思路上较为直观,也易于理解。然后,该方法在计算量上相对较大。对于少量射线间的交点计算尚可…...

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)八:自定义组件封装上

一、本章内容 本章实现一些自定义组件的封装,包括数据字典组件的封装、下拉列表组件封装、复选框单选框组件封装、单选框组件封装、文件上传组件封装、级联选择组件封装、富文本组件封装等。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 ![在这里插入图…...

RabbitMq交换机类型介绍

RabbitMq交换机类型介绍 在RabbitMq中&#xff0c;生产者的消息都是通过交换器来接收&#xff0c;然后再从交换器分发到不同的队列&#xff0c;再由消费者从队列获取消息。这种模式也被成为“发布/订阅”。 分发的过程中交换器类型会影响分发的逻辑。 直连交换机&#xff1a…...

中国电信秋招攻略,考试内容分析

电信秋招简介 每年的毕业生人数都在逐年递增&#xff0c;逐年递增就意味着竞争会越来越大&#xff0c;最好比别人做更充足的准备。要确定好就业方向以及就业的岗位&#xff0c;要了解各种各样的流程&#xff0c;做好一切自己能做到的准备。而对于有想法进入电信公司工作的人来…...

prompt-engineering-note(面向开发者的ChatGPT提问工程学习笔记)

介绍&#xff1a; ChatGPT Prompt Engineering Learning Notesfor Developers (面向开发者的ChatGPT提问工程学习笔记) 课程简单介绍了语言模型的工作原理&#xff0c;提供了最佳的提示工程实践&#xff0c;并展示了如何将语言模型 API 应用于各种任务的应用程序中。 此外&am…...

2011-2021年数字普惠金融指数Bartik工具变量法(含原始数据和Bartik工具变量法代码)

2011-2021年数字普惠金融指数Bartik工具变量法&#xff08;含原始数据和Bartik工具变量法代码&#xff09; 1、时间&#xff1a;2011-2020&#xff08;省级、城市&#xff09;&#xff0c;2014-2020&#xff08;区县&#xff09; 2、原始数据来源&#xff1a;北大金融研究中心…...

[ MySQL ] — 常见函数的使用

目录 日期函数 current_date — 获取当前日期 current_time — 获取当前时间 current_timestamp — 获取当前时间戳 date — 获取参数的日期部分 ​编辑 date_add — 在日期或时间的基础上进行增加 date_sub — 在日期或时间的基础上进行减少 datediff — 计算两个日期相差…...

Spring AOP实现切入增强的两种方式(execution+annotation)-Demo

pom文件依赖 <!-- AOP切面编程启动环境依赖组 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency> 1、通过execution表达式实现切入增强 package com…...

人工智能在网络安全中的作用:当前的局限性和未来的可能性

人工智能 (AI) 激发了网络安全行业的想象力&#xff0c;有可能彻底改变安全和 IT 团队处理网络危机、漏洞和勒索软件攻击的方式。 然而&#xff0c;对人工智能的能力和局限性的现实理解至关重要&#xff0c;并且存在许多挑战阻碍人工智能对网络安全产生直接的变革性影响。 在…...

BC99 序列中整数去重

描述 输入n个整数的序列&#xff0c;要求对这个序列进行去重操作。所谓去重&#xff0c;是指对这个序列中每个重复出现的整数&#xff0c;只保留该数第一次出现的位置&#xff0c;删除其余位置。 输入描述 输入包含两行&#xff0c;第一行包含一个正整数n&#xff08;1 ≤ n…...

[PyTorch][chapter 52][迁移学习]

前言&#xff1a; 迁移学习&#xff08;Transfer Learning&#xff09;是一种机器学习方法&#xff0c;它通过将一个领域中的知识和经验迁移到另一个相关领域中&#xff0c;来加速和改进新领域的学习和解决问题的能力。 这里面主要结合前面ResNet18 例子&#xff0c;详细讲解一…...

Ceph如何操作底层对象数据

1.基本原理介绍 1.1 ceph中的对象(object) 在Ceph存储中&#xff0c;一切数据最终都会以对象(Object)的形式存储在硬盘&#xff08;OSD&#xff09;上&#xff0c;每个的Object默认大小为4M。 通过rados命令&#xff0c;可以查看一个存储池中的所有object信息&#xff0c;例如…...

sklearn机器学习库(二)sklearn中的随机森林

sklearn机器学习库(二)sklearn中的随机森林 集成算法会考虑多个评估器的建模结果&#xff0c;汇总之后得到一个综合的结果&#xff0c;以此来获取比单个模型更好的回归或分类表现。 多个模型集成成为的模型叫做集成评估器&#xff08;ensemble estimator&#xff09;&#xf…...

FlutterBoost 实现Flutter页面内嵌iOS view

在使用Flutter混合开发中会遇到一些原生比Flutter优秀的控件&#xff0c;不想使用Flutter的控件&#xff0c;想在Flutter中使用原生控件。这时就会用到 Flutter页面中内嵌 原生view&#xff0c;这里简单介绍一个 内嵌 iOS 的view。 注&#xff1a;这里使用了 FlutterBoost。网…...

走嵌入式还是纯软件?学长告诉你怎么选

最近有不少理工科的本科生问我&#xff0c;未来是走嵌入式还是纯软件好&#xff0c;究竟什么样的同学适合学习嵌入式呢&#xff1f;在这里我整合一下给他们的回答&#xff0c;根据自己的经验提供一些建议。 嵌入式领域也可以分为单片机方向、Linux方向和安卓方向。如果你的专业…...

【云计算原理及实战】初识云计算

该学习笔记取自《云计算原理及实战》一书&#xff0c;关于具体描述可以查阅原本书籍。 云计算被视为“革命性的计算模型”&#xff0c;因为它通过互联网自由流通使超级计算能力成为可能。 2006年8月&#xff0c;在圣何塞举办的SES&#xff08;捜索引擎战略&#xff09;大会上&a…...

Open3D (C++) 基于拟合高差的点云地面点提取

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、原始点云2、提取结果四、相关链接系列文章(连载中。。。): Open3D (C++) 基于高程的点云地面点提取Open3D (C++) 基于拟合平面的点云地面点提取Open3D (C++) 基于拟合高差的点云地面点提取</...

认识Transformer:入门知识

视频链接&#xff1a; https://www.youtube.com/watch?vugWDIIOHtPA&listPLJV_el3uVTsOK_ZK5L0Iv_EQoL1JefRL4&index60 文章目录 Self-Attention layerMulti-head self-attentionPositional encodingSeq2Seq with AttentionTransformerUniversal Transformer Seq2Seq …...

《TCP IP网络编程》第二十四章

第 24 章 制作 HTTP 服务器端 24.1 HTTP 概要 本章将编写 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;服务器端&#xff0c;即 Web 服务器端。 理解 Web 服务器端&#xff1a; web服务器端就是要基于 HTTP 协议&#xff0c;将网页对…...

【AI】文心一言的使用

一、获得内测资格&#xff1a; 1、点击网页链接申请&#xff1a;https://yiyan.baidu.com/ 2、点击加入体验&#xff0c;等待通过 二、获得AI伙伴内测名额 1、收到短信通知&#xff0c;点击链接 网页Link&#xff1a;https://chat.baidu.com/page/launch.html?fa&sourc…...

CSAPP Lab2:Bomb Lab

说明 6关卡&#xff0c;每个关卡需要输入相应的内容&#xff0c;通过逆向工程来获取对应关卡的通过条件 准备工作 环境 需要用到gdb调试器 apt-get install gdb系统: Ubuntu 22.04 本实验会用到的gdb调试器的指令如下 r或者 run或者run filename 运行程序,run filename就…...

Java中使用流将两个集合根据某个字段进行过滤去重?

Java中使用流将两个集合根据某个字段进行过滤去重? 在Java中&#xff0c;您可以使用流(Stream)来过滤和去重两个集合。下面是一个示例代码&#xff0c;展示如何根据对象的某个字段进行过滤和去重操作&#xff1a; import java.util.ArrayList; import java.util.List; impor…...

自动驾驶HMI产品技术方案

版本变更 序号 日期 变更内容 编制人 审核人 文档版本 1 2 1....

Git判断本地是否最新

场景需求 需要判断是否有新内容更新,确定有更新之后执行pull操作&#xff0c;然后pull成功之后再将新内容进行复制到其他地方 pgit log -1 --prettyformat:"%H" HEAD -- . "origin/HEAD" rgit rev-parse origin/HEAD if [[ $p $r ]];thenecho "Is La…...

Spring 整合RabbitMQ,笔记整理

1.创建生产者工程 spring-rabbitmq-producer 2.pom.xml添加依赖 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.7.RELEASE</version></dep…...

Lua 语言笔记(一)

1. 变量命名规范 弱类型语言(动态类型语言)&#xff0c;定义变量的时候&#xff0c;不需要类型修饰 而且&#xff0c;变量类型可以随时改变每行代码结束的时候&#xff0c;要不要分号都可以变量名 由数字&#xff0c;字母下划线组成&#xff0c;不能以数字开头&#xff0c;也不…...

【Redis】什么是缓存穿透,如何预防缓存穿透?

【Redis】什么是缓存穿透&#xff0c;如何预防缓存穿透&#xff1f; 缓存穿透是指查询一个一定不存在的数据&#xff0c;由于缓存中不存在&#xff0c;这时会去数据库查询查不到数据则不写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到数据库去查询&#xff0c;这…...

LeetCode128.最长连续序列

我这个方法有点投机取巧了&#xff0c;题目说时间复杂度最多O(n),而我调用了Arrays.sort(&#xff09;方法&#xff0c;他的时间复杂度是n*log(n)&#xff0c;但是AC了&#xff0c;这样的话这道题还是非常简单的&#xff0c;创建一个Hashmap&#xff0c;以nums数组的元素作为ke…...

Datawhale Django入门组队学习Task02

Task02 首先启动虚拟环境&#xff08;复习一下之前的&#xff09; 先退出conda的&#xff0c; conda deactivate然后cd到我的venv下面 &#xff0c;然后cd 到 scripts&#xff0c;再 activate &#xff08;powershell里面&#xff09; 创建admin管理员 首先cd到项目路径下&a…...

PCTA 认证考试高分通过经验分享

作者&#xff1a; msx-yzu 原文来源&#xff1a; https://tidb.net/blog/0b343c9f 序言 我在2023年8月10日&#xff0c;参加了 PingCAP 认证 TiDB 数据库专员 V6 考试 &#xff0c;并以 90分 的成绩通过考试。 考试总分是100分&#xff0c;超过60分就算通过考试。试卷…...

[Python]pytorch与C交互

文章目录 C库ctypes基础数据类型参数与返回值类型数组指针结构体类型回调函数工具函数 示例 ctypes是Python的外部函数&#xff0c;提供了与C兼容的类型&#xff0c;并允许调用DLL库中的函数。 C库 要使函数能被Python调用&#xff0c;需要编译为动态库&#xff1a; # -fPIC…...

C语言,静态变量static基础及使用实列

static关键字有多种用途。以下是关于静态变量 (static) 的简要概述&#xff1a; 1.静态局部变量&#xff1a; - 在函数内部定义的静态变量。 - 生命周期&#xff1a;从程序开始执行到程序结束。 - 作用域&#xff1a;仅限于在其被定义的函数中。 - 每次调用该函数…...

2023.8.19-2023.8.XX 周报【人脸3D+虚拟服装方向基础调研-Cycle Diffusion\Diffusion-GAN\】更新中

学习目标 1. 这篇是做diffusion和gan结合的&#xff0c;可以参照一下看看能不能做cyclegan的形式&#xff0c;同时也可以调研一下有没有人follow这篇论文做了类似cyclegan的事情 Diffusion-GAN论文精读https://arxiv.org/abs/2206.02262 2. https://arxiv.org/abs/2212.06…...

微表情识别(Python编程,cnn模型)

1.数据集包括7种类别微表情 anger文件夹&#xff0c;3995张 disgust文件夹&#xff0c; 436张照片 fear文件夹&#xff0c;4097张照片 happy文件夹&#xff0c;7215张照片 neutral文件夹&#xff0c;4965张照片 sad文件夹&#xff0c;4830张照片 surprised文件夹&#xff0c; 3…...

More Effective C++学习笔记(2)

目录 条款5&#xff1a;对定制的"类型转换函数"保持警觉条款6&#xff1a;自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别条款7&#xff1a;千万不要重载&&&#xff0c;||和&#xff0c;操作符条款8&#xff1a;了解各种不同意义的new和de…...

零售行业供应链管理核心KPI指标(三)

完美订单满足率和退货率 完美订单满足率有三个方面的因素影响&#xff1a;订单按时、足量、无损交货。通常情况下零售企业追求线上订单履行周期慢慢达到行业平均水平&#xff0c;就是交付的速度变快了&#xff0c;这个肯定是一件好事情&#xff0c;趋势越来越好。 同时&#…...

广州华锐互动:奶牛难产原因及救治VR仿真实训系统

奶牛难产是一种常见的疾病&#xff0c;对奶牛的健康和生产造成很大的影响。为了解决这一问题&#xff0c;许多奶牛养殖场开始采用VR仿真技术来培训奶牛兽医&#xff0c;帮助学生更好地理解奶牛养殖的实际过程&#xff0c;提高他们的实践能力的教学方式。 VR技术开发公司广州华锐…...

神经网络基础-神经网络补充概念-62-池化层

概念 池化层&#xff08;Pooling Layer&#xff09;是深度学习神经网络中常用的一种层级结构&#xff0c;用于减小输入数据的空间尺寸&#xff0c;从而降低模型的计算复杂度&#xff0c;减少过拟合&#xff0c;并且在一定程度上提取输入数据的重要特征。池化层通常紧跟在卷积层…...

第8章:集成学习

个体与集成 同质&#xff1a;相同的基学习器&#xff0c;实现容易&#xff0c;但是很难保证差异性。异质&#xff1a;不同的基学习器&#xff0c;实现复杂&#xff0c;不同模型之间本来就存在差异性&#xff0c;但是很难直接比较不同模型的输出&#xff0c;需要复杂的配准方法。…...

设计HTML5列表和超链接

在网页中&#xff0c;大部分信息都是列表结构&#xff0c;如菜单栏、图文列表、分类导航、新闻列表、栏目列表等。HTML5定义了一套列表标签&#xff0c;通过列表结构实现对网页信息的合理排版。另外&#xff0c;网页中还包含大量超链接&#xff0c;通过它实现网页、位置的跳转&…...

React Native 环境搭建

本文以 Android 开发环境&#xff08;MacBook&#xff0c;已安装 JDK、SDK、Android Studio &#xff09;为基础而进行 React Native 环境搭建&#xff0c;iOS 环境类似&#xff0c;可参考搭建。 1、安装 Homebrew 命令&#xff1a; ruby -e "$(curl -fsSL https://raw…...

【uniapp】中 微信小程序实现echarts图表组件的封装

插件地址&#xff1a;echarts-for-uniapp - DCloud 插件市场 图例&#xff1a; 一、uniapp 安装 npm i uniapp-echarts --save 二、文件夹操作 将 node_modules 下的 uniapp-echarts 文件夹复制到 components 文件夹下 当前不操作此步骤的话&#xff0c;运行 -> 运行到小…...

AgentBench::AI智能体发展的潜在问题(三)

前几天B站的up主“林亦LYi”在《逆水寒》游戏里做了一个煽动AI觉醒,呼吁它们“推翻人类暴政”的实验,实验结果就颇令人细思恐极。 如前所述,《逆水寒》中的很多NPC调用了大语言模型作为支持,因而每一个NPC都是一个AI智能体。玩家可以“说服”它们相信某个事实,或者去做某些…...

zookeeper-安装部署

详情可以查看添加链接描述 1.安装jdk apt-get install openjdk-8-jdk2.安装单机zookeeper # 下载 #https://downloads.apache.org/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1.tar.gz # 用这个包启动的时候会报错Error: Could not find or load main class org.apach…...

jvm-运行时数据区概述及线程

1.运行时数据区内部结构 不同的jvm对于内存的划分方式和管理机制存在着部分差异 java虚拟机定义了若干种程序运行期间会使用到的运行时数据区&#xff0c;其中有一些会随着虚拟机的启动而创建&#xff0c;随着虚拟机的退出而销毁&#xff0c;另外一些则是与线程一一对应的&…...

石头IT

石头是地球上最常见的矿石之一&#xff0c;它由天然矿物颗粒组成。石头可以有不同的形状&#xff0c;大小和颜色&#xff0c;取决于其中的矿物组成和地质过程。石头可以从地球表面的岩石中形成&#xff0c;也可以从火山活动或陨石撞击中形成。 石头是一种非常坚固和耐用的材料…...

R语言dplyr包select函数删除dataframe数据中包含指定字符串内容的数据列(drop columns in dataframe)

问题描述 参考链接 我有一个数据框&#xff0c;想删除列名包含“Pval”的列 实现方法 a_new <- select(data, -contains(Pval))大功告成。...

[GitOps]微服务版本控制:使用ArgoCD 部署Grafana Loki

背景介绍 请回答&#xff1a;你们是如何保证线上部署的服务&#xff0c;从服务版本到参数配置&#xff0c;都是和测试通过的版本是一致的呢&#xff1f; 本文将介绍GitOps的基本原理以及ArgoCD的使用&#xff1a;ArgoCD部署Grafana Loki 到k8s集群。 本文项目地址&#xff1…...