Django世界-迈出第一步-安装和创建

Django

Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。

安装Django

  1. 下载好Django 的安装包:Django-2.2.7.tar.gz
  2. 解压安装包: tar -zxvf Django-2.2.7.tar.gz
  3. 进入安装包:cd Djang-2.2.7
  4. 安装Django:sudo python setup.py install
  5. 查看Django版本:django-admin.py -- version

创建Django项目

无创建虚拟环境的情况下

  1. 找到想安装的文件下:django-admin startproject mydjango
  2. 进入Django项目下:cd mydjango
  3. 创建app:python manage.py startapp django
  4. 运行项目: 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

有创建虚拟环境的情况下

  1. 创建文件夹 : mkdir wgt
  2. 进入文件夹:cd wgt
  3. wgt 创建虚拟环境 venv: python3 -m venv venv
  4. 启动虚拟环境:source wgt/venv/bin/activate
  5. 虚拟环境下安装Django:pip install django
  6. 退出虚拟机 : deactivate

Django文件含义

  1. settings.py : Django 如何与你的系统交互以及如何管理项目,修改一些设置,或者添加一些配置,中间键。
  2. urls.py: 告诉Django应该创建哪些页面来响应浏览请求
  3. wsgi.py : 帮助Django提供他创建的文件(web server gateway interface)
  4. init.py : 配置数据库导入包

Django连接数据库并创建表的操作步骤

  1. settings文件的DATABASES中配置数据库
  2. makemgirations创建数据库变更文件 python manage.py makemigrations + 文件名
  3. migrate将变更文件应用到数据库中 python manage.py migrate+ 文件名
  4. 创建app,并将app添加到settings中的INSTALLED_APPS中
  5. 在app的models文件中创建数据模型
  6. makegirations创建数据库变更文件
  7. migrate将变更文件应用到数据库注意:
    只要对数据模型做了更改或者添加了新的数据模型,
  8. 数据库介绍:Django项目默认 sqlite3 数据库, 生成的数据库名为 db.sqlite3
    sqlite3 仅供测试使用,可以通过配置修改为使用 mysql
  9. 手动创建创建数据库 : create database db_django charest=utf-8
  10. 初始化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 数据事务性

数据库结构的特点

  1. 数据结构化 数据之间具有联系,面向整个系统。
  2. 数据的共享性高,冗余度低,易扩充
  3. 数据独立性高
  4. 数据由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 数据表删除外键

set foreign_key_checks = 0; 

记录一下踩的坑,同一个数据库下两个表,举个例子 user_info 表中的 username字段设置为外键,关联了 表user_pwd中的主键字段 
user,现在因为重建表结构等原因,要把这个外键删除,这里的删除语法为:

alter table 表名 drop foreign key 外键别名;

需要注意的是,外键别名并不是设置为外键的字段名,
假如我们直接 alter table user_info drop foreign key username;这时候会报语法错误!
我们要在命令行输入 show create table user_info;这时候会显示建表的信息,有这么一句话

CONSTRAINT `user_info` FOREIGN KEY (`username`) REFERENCES `user_pwd` (`user`)

这时候我们要这么修改 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
性能损耗少
设计灵活,可以轻松实现复杂查询
移植性好

  1. 模型查询
    1. 模型成员objects

       Django默认通过模型的objects对象实现数据查询
      
    2. 过滤器

       Django有两种过滤器用于筛选记录
      
      filter    : 返回符合筛选条件的数据集
      exclude   : 返回不符合筛选条件的数据集
      
      1. all() 返回所有数据
        filter() 返回符合条件的数据
        filter(条件1,条件2,条件3)
        filter(条件1).filter(条件2).filter(条件3)
        exclude() 查询不满足条件的数据
      1. order_by() 排序
        升序:模型名.objects.all().order_by(‘id’)
        降序:模型名.objects.all().order_by(’-id’)
      1. 运算符
        icontains:大小写不敏感
        contains:大小写敏感
        模型名.objects.filter(s_name__icontains=‘小’)
        startswith:以什么开始
        endswith:以什么结束
      1. 范围查询
        gt gte:大于、大于等于 —>greater than greater than equal
        lt lte:小于、小于等于
        in:在范围之内
      1. values 获取
        values方法可以获取number字段的字典列表。
        values_list可以获取number的元组列表。
        values_list方法加个参数flat=True可以获取number的值列表。
      1. 查询单个数据
        get():返回一个满足条件的对象
        获取不到数据会报错
        get只能返回一个对象,如果找到多个会引发模型类MultiObjectsReturned异常
        get_or_create():获取不到对象就创建对象
        get_or_update();获取到对象就修改对象
      1. 查询先后条件
        first():返回查询集中的第一个对象
        last():返回查询集中的最后一个对象
        count():返回当前查询集中的对象个数
        exists():判断查询集中是否有数据,如果有数据返回True,没有返回False
      1. 查询或者条件/不等于条件
        并且:filter(条件1,条件2,条件3)
        或者:filter(Q(条件1) |Q(条件2))
        取反:filter(~Q(条件1) | Q(条件2))
      1. A字段和B字段进行算数运算
        F()
        filter(shuxue__gt = F(‘yuwen’) + 10)

例子:

大于等于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']))

总结:

  1. 第一种直接就把外键的name查询出,无需重新查询
  2. 第二种 需要查询
<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}]>
  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框架

  1. 首先,django在运行程序时,最开始当你输入正确的网络地址的时候,
    django会进入路由模块(urls)中去寻找是否有符合其要求的路径,
    auth后面跟的就是路由路径了。我们在页面地址栏中输入“localhost:8000/index/”,
    django会自动的寻找路由表(urls)中符合要求的后缀为“index/”的路径。
    找到后,如果有index/,将会去执行这个路由后面所指向的函数。而这个函数就是view中的函数,执行函数相应的响应过程以后,
  2. 必定会return返回并跳转相应页面及携带数据
    (django强制要求必须return返回,强制返回主要原因是每一次网页操作,都会相应的跳转页面或交互)
    看到return语句后面是不是跟着“index.html”,这就是让程序自动自行index的页面。
    那么来到templates文件夹中打开这个页面。恭喜你,打开index.html页面。
  3. 经过上面的步骤
    可以看出,我们程序的执行流程是:路由,视图调度(V层),前端页面(HTML)。
    所以我们在开发中,为了让大脑清晰,方便执行,我们从最容易观察到的前端页面视图层开始开发,这样不断能够及时的看到很好的反馈,
    若看不到页面,我们还能及时的找到问题出在什么地方,能够及时的做出调整。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值