官文
https://docs.djangoproject.com/en/2.2/ref/models/querysets/#django.db.models.query.QuerySet.values
Django映射类去增加数据库数据
本文创建数据库的表映射出来是这样
class Subject(models.Model):
no = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
intro = models.CharField(max_length=1000, blank=True, null=True)
is_hot = models.IntegerField(blank=True, null=True) #这里用IntegerField,修改的时候写0,1
#is_hot = models.BooleanField(blank=True, null=True) 用BooleanField,修改时写True,Flase
class Meta:
managed = False #如果改为True,可以通过类去修改数据库的表。如果为假,则是不可以
db_table = 'tb_subject'
打开当前虚拟环境终端(django)命令行工具
输入: python manage.py shell 可以进入django交互式环境
Django模型操作数据库代码
iterator()
方法用于在查询结果集中逐行迭代数据,而不是一次性将所有结果加载到内存中。这对于处理大量数据时非常有用,因为它可以减少内存使用并提高性能。
from your_app.models import YourModel
queryset = YourModel.objects.filter(some_condition=True).iterator()
for row in queryset:
# 处理每一行数据
print(row)
#增加数据
subject = Subject(name='Python全栈开发',intro='当下最热门学科',is_hot=True)
subject.save()
#删除数据
subject = Subject.objects.get(no=2)
subject.delete()
#修改数据
subject = Subject.objects.get(no=2)
subject.name = '...'
subject.save()
#查询数据
subject = Subject.objects.get(no=1)
subject
'''
可用名字查,可能查到同名的所有数据 subject = Subject.objects.filter(name='..')
'''
#查询所有数据 --会拿到一个容器
subjects = Subject.objects.all()
subjects
# 悲观锁(多进程查询之前必须拿到锁才能继续,否则阻塞)
subject = Subject.objects.select_for_update().get(no=1)
# 乐观锁(查询不加锁,更新时做判断)
https://blog.csdn.net/weixin_43692357/article/details/88708954?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-19.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-19.control
# values查询(并重命名key)
contents = Content.objects.values('author_id', author_name=F('author__username'))
# 反向查询
1. 如果多的一方orm模型中有related_name属性则用这个属性查,否则用一的一方的orm 属性名_set 查
(一的一方必须为单个对象,不能是查询集)
示例:
class User(models.Model): # 多的一方
'''用户'''
user_id = models.AutoField(primary_key=True)
openid = models.CharField(max_length=255, blank=True, null=True)
img = models.CharField(max_length=255, blank=True, null=True)
channel = models.ForeignKey(to='Channel', on_delete=models.DO_NOTHING, blank=True, null=True, related_name='user') #
update_time = models.DateTimeField(auto_now=True)
class Meta:
managed = False
db_table = 'tb_user'
class Channel(models.Model): # 一的一方
'''渠道表'''
channel_id = models.AutoField(primary_key=True)
channel_name = models.CharField(max_length=255, blank=True, null=True)
qrcode = models.CharField(max_length=255, null=True)
class Meta:
managed = False
db_table = 'tb_channel'
1. Channel.objects.get(channel_id_id=1).user_set.all() #这种不需要配related_name
2. Channel.objects.get(channel_id_id=1).user.all() # 这种需要配related_name, 查询对象后跟related_name属性名
如果要使用Django模型管理的话,需要数据迁移
当前虚拟环境下输入:
python manage.py migrate #把Django框架自带的模型类,变成数据库的表(迁移10张表到数据库)
创建超级管理员账号,终端再次输入:
python manage.py createsuperuser
#会让输入账号,邮箱,密码。 本文用admin账号,这步操作完就可以登录Django后台管理系统了
注册模型
在应用下找admin.py文件中(本文创建的应用是polls/admin.py)
from django.contrib import admin
from polls.models import Subject #导入模型类 --添加这句
admin.site.register(Subject) #注册模型 --添加这句 完成后可刷新django管理页
汉化模型
在应用下找models.py文件中(本文创建的应用是polls/models.py).在Meta类中添加代码
class Meta:
managed = False
db_table = 'tb_subject'
verbose_name = '学科' #添加这句 这是单数形式,只添加这句name后加s为复数
verbose_name_plural = '学科' #添加这句 复数也显示name,不加s
如果想汉化数据页面的语言,可以在数据库的表映射出来的类属性后面加上verbose_name='别名'.例如:
no = models.AutoField(primary_key=True,verbose_name='编号')
name = models.CharField(max_length=20,verbose_name='名称')
自定义模型显示方式
点击学科表,不会显示具体数据,只显示主键.找到polls/admin.py 修改数据
from django.contrib import admin
from polls.models import Subject
class SubjectModelAdmin(admin.ModelAdmin): #定义新类继承django中admin.ModelAdmin的类
list_display = ('no','name','intro','is_hot') #查询数据都显示那些数据
search_fields = ('name',) #添加搜索框
list_per_page = 20 #每页存放的数据
list_filter = ('yi_name',) #可以根据条件筛选
ordering = ('no',) #主键排序 ('-主键')降序,('主键')升序
admin.site.register(Subject,SubjectModelAdmin) #把数据库的表映射到后台管理系统上
simpleui中admin的基本配置信息(settings中)
SIMPLEUI_ANALYSIS = False #关闭分析(一般加在settings中,这个框架默认采集信息,默认开启)
SIMPLEUI_HOME_INFO = False #关闭服务器信息
SIMPLEUI_LOGO = 'https://avatars2.githubusercontent.com/u/13655483?s=60&v=4' #修改logo
(admin中)
admin.AdminSite.site_header = '商品信息管理' #修改登陆页的标题
admin.AdminSite.site_title = '商品信息管理' #修改登陆页面的标题
admin中如果要上传文件的话(例如图片)
1.在项目下新建文件夹(例如:media)
#数据库中必须有Field字段
2.MEDIA_URL = "/media/" # 设置获取文件时的访问根路径 (访问的路径)
#访问时,会加上这个路径,如果数据库中是绝对路径则不需要
3.MEDIA_ROOT = os.path.join(BASE_DIR, "media")#设置上传图片的文件夹(存入的路径)
#此时数据库中存的是文件名,如果访问的话,会自动加上/media/这个路径
4.主urls中添加访问路由
from django.urls import re_path
from django.views.static import serve
urlpatterns = [
re_path(r'media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}),
]
渲染subjects.html
在视图views.py中
def show_subjects(request):
subujects = Subject.objects.all().order_by('-no') #获取到数据库中表的所有数据,order_by('-no')降序
res = render(request,'subjects.html',{
'subjects':subujects #渲染数据到subjects.html中
})
return HttpResponse(res) #返回一个渲染后的html文件(response对象)
Django中放静态资源
一般放主项目路径下My_django/static/css images js (本文项目为My_django,static文件自己创建)
修改setting.py文件,创建后最底下会多出一行代码STATIC_URL = '/static/'如果没有自己添加
STATICFILES_DIRS = [os.path.join(BASE_DIR,'static'),] #添加这句
STATIC_URL = '/static/' #添加这句 --在文件末行
修改完成找到html文件中的存放静态资源的src修改资源路径
示例:<img src="static/images/hot-icon-small.png"> #最后部署项目不是这种方式访问静态资源
Django超链接跳转对应的视图函数
修改subject.html
{% for subject in subjects %}
<dl>
<dt>
#改了这句 <a href="teachers/?subject_no={{ subject.no }}">{{ subject.name }}</a>
{% if subject.is_hot %}
<img src="static/images/hot-icon-small.png">
{% endif %}
</dt>
<dd>{{ subject.intro }}</dd>
</dl>
{% endfor %} #href后改为点击后访问的视图函数地址
在views.py中写跳转后的视图函数
def show_teachers(request : HttpResponse) -> HttpResponse:
teachers = None
res = render(request,'teachers.html',{
'teachers':teachers
)}
return HttpResponse(res)
在urls.py中添加访问链接:
path('teachers/',show_teachers),
##完成这步可以访问teachers页面,但是由于老师数据库模型还没搭建,所以只会显示静态资源
深入模型Django模型 --查询(这里以此项目为例)
查询所有数据
Subject.objects.all()
过滤数据
Subject.objects.filter(name='Python全栈开发+人工智能')
#查询名为'Python全栈开发+人工智能'的学科 (精准查询)
Subject.objects.filter(name__contains='全栈')
#查询名为'全栈'的学科 (模糊查询)
Subject.objects.filter(is_hot =True)
#查询热门学科,模型里面为True的字段 (精准查询)
Subject.objects.filter(no__gt=3).filter(no__lt=10)
Subject.objects.filter(no__gt=3,no__lt=10)
#查询编号大于3,小于10的字段 (精准查询)
Subject.objects.filter(no__ge=3,no__le=10)
Subject.objects.filter(no__range=(3,10))
#查询编号3到10的字段 (精准查询,区间查询)
Subject.objects.get(pk=1)
Subject.objects.get(no=1)
Subject.objects.get(no=1).first()
Subject.objects.get(no=1).last()
#查询主键为1的学科 (精准查询)
Subject.objects.order_by('no')
#查询所有,按编号升序 (精准查询)
Subject.objects.order_by('-no')
#查询所有,按编号降序
Subject.objects.order_by('no')[:3]
#查询从编号从小到大前3个字段 (精准查询)
Subject.objects.count()
#查询数据库一共有多少条数据 (精准查询)
Teacher.objects.filter(subject__no=1)
Subject.objects.get(pk=1).teacher_set.all()
# 查询编号为1的学科的老师
Teacher.objects.filter(subject__name__contains='全栈')
# 查询学科名称有“全栈”二字的学科的老师 (模糊查询)
说明1:由于老师与学科之间存在多对一外键关联,所以能通过学科反向查询到该学科的老师(从
一对多关系中“一”的一方查询“多”的一方),反向查询属性默认的名字是 类名⼩写_set (如上面例
子中的 teacher_set ),当然也可以在创建模型时通过 ForeingKey 的 related_name 属性指定反
向查询属性的名字。如果不希望执行反向查询可以将 related_name 属性设置为 '+' 或者以 '+' 开
头的字符串。
说明2:ORM查询多个对象时会返回QuerySet对象,QuerySet使用了惰性查询,即在创建
QuerySet对象的过程中不涉及任何数据库活动,等真正用到对象时(对QuerySet求值)才向数据
库发送SQL语句并获取对应的结果,这⼀点在实际开发中需要引起注意!
说明3:如果希望更新多条数据,不用先逐一获取模型对象再修改对象属性,可以直接使用
QuerySet对象的 update() 方法一次性更新多条数据。
查询并重命名字段
假设有一个模型类MyModel
,其中有一个字段age
,我们想要筛选出年龄大于等于18岁的记录,并将年龄字段重命名为adult_age
,
可以使用以下代码
方法一
MyModel.objects.filter(age__gte=18).annotate(adult_age=F('age'))
方法二
MyModel.objects.filter(age__gte=18).values(adult_age=F('age'))
方法三
MyModel.objects.filter(age__gte=18).extra(select={'adult_age': 'age'})
Q查询与数组结合(数组内每个元素的模糊查询)
from django.db.models import Q
keywords = ['keyword1', 'keyword2', 'keyword3']
query = Q()
for keyword in keywords:
query |= Q(name__icontains=keyword) # | Q(其他字段名=元素) 如果多个条件这样连接
results = MyModel.objects.filter(query)
查询参考
按字段查找可以用的条件
1. exact / iexact :精确匹配/忽略大小写的精确匹配查询
2. contains / icontains / startswith / istartswith / endswith / iendswith :基于 like 的模糊查询
3. in :集合运算
4. gt / gte / lt / lte :大于/大于等于/小于/小于等于关系运算
5. range :指定范围查询(SQL中的 between…and… )
6. year / month / day / week_day / hour / minute / second :查询时间日期
7. isnull :查询空值(True)或非空值(False)
8. search :基于全文索引的全文检索(一般很少使⽤)
9. regex / iregex :基于正则表达式的模糊匹配查询
动态获取django中模型的字段名和类型
要获取Django ORM模型中的属性(字段),您可以使用模型类的属性或实例对象的属性。以下是两种常见的方法:
使用模型类的属性:
您可以使用模型类的属性来获取字段信息。每个模型类都有一个_meta属性,它包含有关模型的元数据,包括字段信息。您可以通过访问_meta.fields
属性来获取模型的所有字段。
from your_app.models import YourModel
fields = YourModel._meta.fields
for field in fields:
print(field.name) # 打印字段名
print(field.get_internal_type()) # 打印字段类型
# 其他字段属性和方法