Dajngo学习
- Django
-
- 安装Django
- 创建Django项目
-
- 无创建虚拟环境的情况下
- 有创建虚拟环境的情况下
- Django文件含义
- Django连接数据库并创建表的操作步骤
-
- Dajngo 数据事务性
- Dajngo 创建数据表
- Dajngo 数据表外键
-
- Dajngo 数据表保存外键
- Dajngo 数据表删除外键
- Dajngo 数据时间字段
-
- Django 时间校验
- Django 转换时间
- Dajngo ORM(Objects Relational Mapping)
- 创建 Dajngo 超级管理员
- 总结
Django
Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。
安装Django
- 下载好Django 的安装包:
,Django-2.2.7.tar.gz
- 解压安装包:
tar -zxvf Django-2.2.7.tar.gz
- 进入安装包:
cd Djang-2.2.7
- 安装Django:
sudo python setup.py install
- 查看Django版本:
django-admin.py -- version
创建Django项目
无创建虚拟环境的情况下
- 找到想安装的文件下:
django-admin startproject mydjango
- 进入Django项目下:
cd mydjango
- 创建app:
python manage.py startapp django
- 运行项目:
python manage.py runserver 0.0.0.0:8000
安装出现的问题:
Are you sure it installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
解决办法
python -m pip install Django
有创建虚拟环境的情况下
- 创建文件夹 :
mkdir wgt
- 进入文件夹:
cd wgt
- wgt 创建虚拟环境 venv:
python3 -m venv venv
- 启动虚拟环境:
source wgt/venv/bin/activate
- 虚拟环境下安装Django:
pip install django
- 退出虚拟机 :
deactivate
Django文件含义
- settings.py : Django 如何与你的系统交互以及如何管理项目,修改一些设置,或者添加一些配置,中间键。
- urls.py: 告诉Django应该创建哪些页面来响应浏览请求
- wsgi.py : 帮助Django提供他创建的文件(web server gateway interface)
- init.py : 配置数据库导入包
Django连接数据库并创建表的操作步骤
- settings文件的DATABASES中配置数据库
- makemgirations创建数据库变更文件
+ 文件名python manage.py makemigrations
- migrate将变更文件应用到数据库中
+ 文件名python manage.py migrate
- 创建app,并将app添加到settings中的INSTALLED_APPS中
- 在app的models文件中创建数据模型
- makegirations创建数据库变更文件
-
migrate将变更文件应用到数据库注意:
只要对数据模型做了更改或者添加了新的数据模型,
-
数据库介绍:Django项目默认 sqlite3 数据库, 生成的数据库名为 db.sqlite3
sqlite3 仅供测试使用,可以通过配置修改为使用 mysql
- 手动创建创建数据库 :
create database db_django charest=utf-8
- 初始化mysql 驱动 :
import pymysql , pymysql.install_as_MySQLdb()
setting.py 配置数据库:
DATABASES = {
# 配置使用mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库产品
'NAME': 'db_Django', # 数据库名
'HOST': 'localhost', # 主机地址,本机使用localhost,生产环境为实际主机ip
'PORT': '3306', # 端口
'USER': 'root', # 用户名
'PASSWORD': 'root', # 密码
}
}
Dajngo 数据事务性
数据库结构的特点
- 数据结构化 数据之间具有联系,面向整个系统。
- 数据的共享性高,冗余度低,易扩充
- 数据独立性高
- 数据由DBMS统一管理和控制
数据库的事务性
字段 | 含义 |
---|---|
Atomic(原子性) | 指整个数据库事务是不可分割的工作单位。只有使据库中所有的操作执行成功,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态。 |
Consistency(一致性) | 指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中Tom和Jack的存款总额为2000元。 |
Isolation(隔离性) | 指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。 |
Durability(持久性) | 指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。 |
事务性
在保存订单数据中,涉及到多张表(OrderInfo、OrderGoods、SKU)的数据修改,对这些数据的修改应该是一个整体事务,即要么一起成功,要么一起失败。
Django中对于数据库的事务,默认每执行一句数据库操作,便会自动提交。我们需要在保存订单中自己控制数据库事务的
执行流程。
在Django中可以通过django.db.transaction模块提供的atomic来定义一个事务,atomic提供两种用法
from django.db import transaction
@transaction.atomic
def viewfunc(request):
# 这些代码会在一个事务中执行
…
with语句用法是:
from django.db import transaction
from rest_framework.views import APIView
class OrderAPIView(APIView):
def post(self,request):
....
with transation.atomic():
# 设置事务回滚的标记点
sid = transation.savepoint()
....
# 出现异常时 回滚事物
try:
....
except:
transation.savepoint_rallback(sid)
transaction.savepoint_commit(save_id)
在Django中,还提供了保存点的支持,可以在事务中创建保存点来记录数据的特定状态,数据库出现错误时,可以恢复到数据保存点的状态
from django.db import transaction
//创建保存点
save_id = transaction.savepoint()
//回滚到保存点
transaction.savepoint_rollback(save_id)
//提交从保存点到当前状态的所有数据库事务操作
transaction.savepoint_commit(save_id)
Dajngo 创建数据表
class user(models.MOdel):
name = models.CharField(max_length=128, unique=True) //必填,最长不超过128个字符,并且唯一,也就是不能有相同姓名;
password = models.CharField(max_length=256)//必填,最长不超过256个字符(实际可能不需要这么长);
email = models.EmailField(unique=True) //使用Django内置的邮箱类型,并且唯一;
sex = models.CharField(max_length=32, choices=gender, default="男") // 性别,使用了一个choice,只能选择男或者女,默认为男;
c_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name // 使用__str__方法帮助人性化显示对象信息;
class Meta: //数据里定义用户按创建时间的反序排列,也就是最近的最先显示;
db_table = 'user' // 命名数据库名字是: user
ordering = ["-c_time"] // 以 创建时间从大到小排序
verbose_name = "用户"
verbose_name_plural = "用户"
Dajngo 数据表外键
关于ForeignKey.on_delete的几个选项;
当一个model对象的ForeignKey关联的对象被删除时,默认情况下此对象也会一起被级联删除的。
字段 | 含义 |
---|---|
CASCADE | 默认值,model对象会和ForeignKey关联对象一起被删除 |
SET_NULL | 将model对象的ForeignKey字段设为null。当然需要将null设为True |
SET_DEFAULT | 将model对象的ForeignKey字段设为默认值。 |
Protect | 删除ForeignKey关联对象时会生成一个ProtectedError,这样ForeignKey关联对象就不会被删除了 |
字段 | 含义 |
---|---|
models.CASCADE | 默认为models.CASCADE 级联删除。当删除’一’时,‘多’会被删除。 |
modles.PROTECT | 当删除一个具有外键关系的对象时,会引发一个异常,阻止删除该对象 |
models.SET_NULL | 设置删除对象所关联的外键字段为null。但字段的null属性必需为True |
models.SET_DEFAULT | 设置删除对象所关联的外键字段为默认的值。 |
models.SET(value) | 设置删除对象所关联的对象的外键字段为value,value也可以是一个可调用函数 |
Dajngo 数据表保存外键
何时使用save(commit=False)方法
Stackoverflow上其实已经有了一段非常精炼的答案。英文原文如下,我把它翻译了一下:
That is useful when you get most of your model data from a form, but need to populate some null=False fields with non-form data.
Saving with commit=False gets you a model object, then you can add your extra data and save it.
当你通过表单获取你的模型数据,但是需要给模型里null=False字段添加一些非表单的数据,该方法会非常有用。如果你指定commit=False,
那么save方法不会理解将表单数据存储到数据库,而是给你返回一个当前对象。这时你可以添加表单以外的额外数据,再一起存储。
何时使用save_m2m方法及如何使用
save_m2m方法只用来存储多对多的关系。当你同时满足下面两个条件时,你需要使用此方法。如果你直接使用save()或form_valid()方法,是可以直接存储多对多(m2m)关系的,不需要用save_m2m。你使用了save(commit=False)方法
你的model里有多对多的关系(比如tags)
if user_create_form.is_valid():
new_user = user_create_form.save(commit=False)
new_user.password = make_password(user_create_form.cleaned_data['password'])
if 'file' in request.FILES:
file_name = 'media/image/' + request.POST.get('name') + '_' + str(int(time.time())) + '.' + \
file_obj.name.split('.')[
-1] # 构造文件名以及文件路径
print(file_name)
with open(file_name, 'wb+') as f:
print(file_obj.read())
f.write(file_obj.read())
new_user.image = file_name[6:]
new_user.save()
user_create_form.save_m2m()
ret = {'status': 'success'}
Dajngo 数据表删除外键
记录一下踩的坑,同一个数据库下两个表,举个例子 user_info 表中的 username字段设置为外键,关联了 表user_pwd中的主键字段
user,现在因为重建表结构等原因,要把这个外键删除,这里的删除语法为:
alter table 表名 drop foreign key 外键别名;
需要注意的是,外键别名并不是设置为外键的字段名,
假如我们直接 alter table user_info drop foreign key username;这时候会报语法错误!
我们要在命令行输入
;这时候会显示建表的信息,有这么一句话
show create table user_info
这时候我们要这么修改这个时候就删除了表中字段的外键约束,这时候我们再
alter table user_info drop foreign key user_info;
,就可以删除这个原本是外键的字段了!
alter table user_info drop username
Dajngo 数据时间字段
字段 | 含义 |
---|---|
DateTimeField | 日期+时间,与python里的 datetime.datetime 实例同,数据库字段内容为 2018-08-30 16:31:00 |
DateField | 日期,与python里的 datetime.date 实例同。数据库字段内容为 2018-08-30,datetime.date 传到前台的值会转换成 2019年12月5日 |
有以下两个可选的选项,均为bool类型:
参数1:auto_now,默认值为false,设置为true时,每次执行 save 操作时,将其值设置为当前时间,并且每次修改model,都会自动更新。
使用场景:这个参数在需要存储“最后修改时间”的场景下,十分方便。
注意:设置该参数为true时,并不意味着字段的默认值设为当前时间,而是指字段会被“强制”更新到当前时间,你无法程序中手动为字段赋值;如果使用django自带的admin管理器,那么该字段在admin中是只读的。
参数2:auto_now_add,默认值为false,设置为true时,会在model对象第一次被创建时,将字段的值设置为创建时的时间,以后修改对象时,字段的值不会再更新。
使用场景:该属性通常被用在存储“创建时间”的场景下。
注意:一旦被设置为True,就无法在程序中手动为字段赋值,在admin中字段也会成为只读的。
auto_now和auto_now_add被设置为True后,这样做会导致字段成为editable=False和blank=True的状态。editable=False将导致字段不会被呈现在admin中,blank=Ture表示允许在表单中不输入值。
Django 时间校验
//转换成规范的时间
print(datetime.datetime.strptime(date_text, '%Y-%m-%d 00:00:00'))
//判断是否是时间格式
def validate(date_text):
try:
datetime.datetime.strptime(date_text, '%Y-%m-%d 00:00:00')
flag = True
except ValueError:
flag = False
return flag
Django 转换时间
//下载数据时,将不规范的时间转换
# cls=DateEnconding 转换成 2019/12/9
result = json.dumps(data, cls=DateEnconding)
class DateEnconding(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime.date):
return o.strftime('%Y/%m/%d')
安装出现的问题:
init() missing 1 required positional argument: ‘on_delete’
解决办法
category = models.ForeignKey(Category, verbose_name=‘分类’, on_delete=models.CASCADE)
在末尾加上 on_delete=models.CASCADE
安装Pymysql的问题:
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None
解决办法
找到Python安装路劲下的Python36-32\Lib\site-packages\django\db\backends\mysql\base.py文件将文件中的如下代码注释
if version < (1, 3, 3):
raise ImproperlyConfigured(“mysqlclient 1.3.3 or newer is required; you have %s” % Database.version)
重新在项目manage.py路劲下执行如下命令即可
安装数据库出现的问题:
No changes detected
解决办法
第一步:
删除该app下的migrations下的所有文件。
第二步:
进入数据库,将对应的该app所有相关表删除
第三步:执行一下三条命令
blog>python manage.py makemigrations --empty myblog
blog>python manage.py makemigrations
blog>python manage.py migrate
或者
python manage.py migrate --fake
Dajngo ORM(Objects Relational Mapping)
** 对象关系映射,是一种程序技术,用于实现对象编程语言里不同类型系统的数据之间的转换,ORM模型的简单性简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构。**
ORM将对对象的操作转换为原生SQL
优点
易用性,可以有效减少重复SQL
性能损耗少
设计灵活,可以轻松实现复杂查询
移植性好
- 模型查询
- 模型成员objects
Django默认通过模型的objects对象实现数据查询
- 过滤器
Django有两种过滤器用于筛选记录
filter : 返回符合筛选条件的数据集 exclude : 返回不符合筛选条件的数据集
-
all() 返回所有数据
filter() 返回符合条件的数据
filter(条件1,条件2,条件3)
filter(条件1).filter(条件2).filter(条件3)
exclude() 查询不满足条件的数据
-
order_by() 排序
升序:模型名.objects.all().order_by(‘id’)
降序:模型名.objects.all().order_by(’-id’)
-
运算符
icontains:大小写不敏感
contains:大小写敏感
模型名.objects.filter(s_name__icontains=‘小’)
startswith:以什么开始
endswith:以什么结束
-
范围查询
gt gte:大于、大于等于 —>greater than greater than equal
lt lte:小于、小于等于
in:在范围之内
-
values 获取
values方法可以获取number字段的字典列表。
values_list可以获取number的元组列表。
values_list方法加个参数flat=True可以获取number的值列表。
-
查询单个数据
get():返回一个满足条件的对象
获取不到数据会报错
get只能返回一个对象,如果找到多个会引发模型类MultiObjectsReturned异常
get_or_create():获取不到对象就创建对象
get_or_update();获取到对象就修改对象
-
查询先后条件
first():返回查询集中的第一个对象
last():返回查询集中的最后一个对象
count():返回当前查询集中的对象个数
exists():判断查询集中是否有数据,如果有数据返回True,没有返回False
-
查询或者条件/不等于条件
并且:filter(条件1,条件2,条件3)
或者:filter(Q(条件1) |Q(条件2))
取反:filter(~Q(条件1) | Q(条件2))
-
A字段和B字段进行算数运算
F()
filter(shuxue__gt = F(‘yuwen’) + 10)
-
- 模型成员objects
例子:
大于等于2 的书籍 且不等于3 的书籍
[<Book: 西游记>, <Book: 水浒传>]
book = list(Book.objects.filter(id__gte=2).filter(~Q(id=3)))
book = list(Book.objects.filter(id__gte=2).exclude(id=3).values())
外键查询
三国演义/黑龙江科技大学
西游记/西安工业大学
红楼梦/黑龙江科技
水浒传/黑龙江
根据外键 查询外键表,重新命名为‘publish_name’
books = Book.objects.annotate(publish_name=F('publish__name'))
for book in books:
print('%s/%s' % (book.title, book.publish_name))
books = Book.objects.all()
# <QuerySet [{'publish__name': '黑龙江科技大学', 'title': '三国演义'}]>
for book in books:
print('%s/%s' % (book.title, book.publish.name))
books = Book.objects.filter().values('publish__name', 'title')
#<QuerySet [<Book: 三国演义>, <Book: 西游记>, <Book: 红楼梦>, <Book: 水浒传>]>
for book in books:
print('%s/%s' % (book['title'], book['publish__name']))
总结:
- 第一种直接就把外键的name查询出,无需重新查询
- 第二种 需要查询
<QuerySet [{'id': 1, 'title': '三国演义', 'price': 100, 'pub_date': datetime.date(2019, 1, 8), 'publish_id': 1, 'publish_name': '黑龙江科技大学'}]>
<QuerySet [{'id': 1, 'title': '三国演义', 'price': 100, 'pub_date': datetime.date(2019, 1, 8), 'publish_id': 1}]>
- 排序 order_by
books = Book.objects.order_by('create_time')
class Meta:
orderinf = ['create_time','price']
创建 Dajngo 超级管理员
首选创建一个新用户,用来登录Django管理网站,进入manage.py目录下,使用如下命令来进行创建:
python manage.py createsuperuser
接下来输入用户名称:
Username(leave bkank to use ‘administrator’): root
然后是输入邮箱(QQemail等都可以):
Email address:(输入你的邮箱账号)
输入密码(输入密码时不会显示出来,并且长度必须超过八位才行):
Password:********
Password(again):********
当两次密码输入相同且超过八位的时候,就会提示创建超级用户成功:
Superuser created successfully.
再次运行你的服务,输入账号和密码就可以成功登陆了:
python manage.py runserver
总结
关于django框架
-
首先,django在运行程序时,最开始当你输入正确的网络地址的时候,
django会进入路由模块(urls)中去寻找是否有符合其要求的路径,
auth后面跟的就是路由路径了。我们在页面地址栏中输入“localhost:8000/index/”,
django会自动的寻找路由表(urls)中符合要求的后缀为“index/”的路径。
找到后,如果有index/,将会去执行这个路由后面所指向的函数。而这个函数就是view中的函数,执行函数相应的响应过程以后,
-
必定会return返回并跳转相应页面及携带数据。
(django强制要求必须return返回,强制返回主要原因是每一次网页操作,都会相应的跳转页面或交互)
看到return语句后面是不是跟着“index.html”,这就是让程序自动自行index的页面。
那么来到templates文件夹中打开这个页面。恭喜你,打开index.html页面。
-
经过上面的步骤,
可以看出,我们程序的执行流程是:路由,视图调度(V层),前端页面(HTML)。
所以我们在开发中,为了让大脑清晰,方便执行,我们从最容易观察到的前端页面视图层开始开发,这样不断能够及时的看到很好的反馈,
若看不到页面,我们还能及时的找到问题出在什么地方,能够及时的做出调整。