美文网首页
django(4)ORM基础

django(4)ORM基础

作者: xinmin | 来源:发表于2019-03-30 14:07 被阅读0次

    前奏:原生SQL语句操作数据库

    • 简单的图书管理系统示例:
      ** 虚拟环境中安装pip install mysqlclient相应模块 **
      book APP的views.py中:
      from django.shortcuts import render, redirect, reverse
      from django.db import connection
      
      def get_cursor():
          return connection.cursor()
      
      
      def index(request):
          cursor = get_cursor()
          cursor.execute('select id,name,author from book')
          books = cursor.fetchall()
          # books返回时列表,里面是元组 [(1, '三国演义', '罗贯中'), ··]
          return render(request, 'index.html', context={'books': books})
      
      
      def add_book(request):
          if request.method == 'GET':
              return render(request, 'add_book.html')
          else:
              name = request.POST.get('name')
              author = request.POST.get('author')
              cursor = get_cursor()
              cursor.execute(
                  "insert into book(id,name,author) values(null, '%s', '%s')" % (name, author))
      
              return redirect(reverse('index'))
      
      
      def book_detail(request, book_id):
          cursor = get_cursor()
          cursor.execute("select id,name,author from book where id=%s" % book_id)
          book = cursor.fetchone()
          return render(request, 'book_detail.html', context={'book': book})
      
      
      def delete_book(request):
          if request.method == 'POST':
              book_id = request.POST.get('book_id')
              cursor = get_cursor()
              cursor.execute("delete from book where id=%s" % book_id)
              return redirect(reverse('index'))
          else:
              raise RuntimeError("删除图书的method错误")
      
      urls.py中代码如下:
      from django.urls import path
      from book import views
      
      urlpatterns = [
          path('', views.index, name='index'),
          path('add_book/', views.add_book, name='add_book'),
          path('book_detail/<int:book_id>/', views.book_detail, name='book_detail'),
          # re_path('book_detail/(?P<book_id>/d+)/',views.book_detail, name='book_detail')
          path('delete_book/', views.delete_book, name='delete_book'),
      ]
      
      settings.py中配置:
      DATABASES = {
          'default': {
              # 数据库引擎(sqlite3/mysql/oracle等)
              'ENGINE': 'django.db.backends.mysql',
              # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
              'NAME': 'django_db2',
              'USER': 'root',
              'PASSWORD': '123456',
              'HOST': '127.0.0.1',
              'PORT': '3306',
          }
      }
      

    ORM模型的创建和映射:

    创建ORM模型:

    ORM模型一般都是放在appmodels.py文件中。每个app都可以拥有自己的模型。并且如果这个模型想要映射到数据库中,那么这个app必须要放在settings.pyINSTALLED_APP中进行安装。以下是写一个简单的书籍ORM模型。示例代码如下:

    from django.db import models
    class Book(models.Model):
        name = models.CharField(max_length=20,null=False)
        author = models.CharField(max_length=20,null=False)
        pub_time = models.DateTimeField(default=datetime.now)
        price = models.FloatField(default=0)
    

    以上便定义了一个模型。这个模型继承自django.db.models.Model,如果这个模型想要映射到数据库中,就必须继承自这个类。这个模型以后映射到数据库中,表名是模型名称的小写形式,为book。在这个表中,有四个字段,一个为name,这个字段是保存的是书的名称,是varchar类型,最长不能超过20个字符,并且不能为空。第二个字段是作者名字类型,同样也是varchar类型,长度不能超过20个。第三个是出版时间,数据类型是datetime类型,默认是保存这本书籍的时间。第五个是这本书的价格,是浮点类型。
    还有一个字段我们没有写,就是主键id,在django中,如果一个模型没有定义主键,那么将会自动生成一个自动增长的int类型的主键,并且这个主键的名字就叫做id

    映射模型到数据库中:

    ORM模型映射到数据库中,总结起来就是以下几步:

    1. settings.py中,配置好DATABASES,做好数据库相关的配置。
    2. app中的models.py中定义好模型,这个模型必须继承自django.db.models
    3. 将这个app添加到settings.pyINSTALLED_APP中。
    4. 在命令行终端,进入到项目所在的路径,然后执行命令python manage.py makemigrations来生成迁移脚本文件。
    5. 同样在命令行中,执行命令python manage.py migrate来将迁移脚本文件映射到数据库中。

    ORM对数据库的基本操作:

    添加数据:

    只要使用ORM模型创建一个对象。然后再调用这个ORM模型的save方法就可以保存了。
    示例代码如下:

    book = Book(name='西游记',author='吴承恩',price=100)
    book.save()
    

    查找数据:

    所有的查找工作都是使用模型上的objects属性来完成的。当然也可以自定义查询对象。这部分功能会在后面讲到。

    1. 根据主键进行查找:使用主键进行查找。可以使用objects.get方法。然后传递pk=xx的方式进行查找。示例代码如下:
      book = Book.objects.get(pk=2)
      
    2. 根据其他字段进行查找:可以使用objects.filter方法进行查找。示例代码如下:
      books = Book.objects.filter(name='三国演义')
      
      使用filter方法返回来的是一个QuerySet对象。这个对象类似于列表。我们可以使用这个对象的first方法来获取第一个值。

    删除数据:

    首先查找到对应的数据模型。然后再执行这个模型的delete方法即可删除。示例代码如下:

    book = Book.objects.get(pk=1)
    book.delete()
    

    修改数据:

    首先查找到对应的数据模型。然后修改这个模型上的属性的值。再执行save方法即可修改完成。示例代码如下:

        book = Book.objects.get(pk=2)
        book.price = 200
        book.save()
    

    常用Field:

    navie时间和aware时间:

    什么是navie时间?什么是aware时间?

    1. navie时间:不知道自己的时间表示的是哪个时区的。也就是不知道自己几斤几两。比较幼稚。
    2. aware时间:知道自己的时间表示的是哪个时区的。也就是比较清醒。

    pytz库:

    专门用来处理时区的库。这个库会经常更新一些时区的数据,不需要我们担心。并且这个库在安装Django的时候会默认的安装。如果没有安装,那么可以通过pip install pytz的方式进行安装。

    astimezone方法:

    将一个时区的时间转换为另外一个时区的时间。这个方法只能被aware类型的时间调用。不能被navie类型的时间调用。
    示例代码如下:

    import pytz
    from datetime import datetime
    now = datetime.now() # 这是一个navie类型的时间
    utc_timezone = pytz.timezone("UTC") # 定义UTC的时区对象
    utc_now = now.astimezone(utc_timezone) # 将当前的时间转换为UTC时区的时间
    >> ValueError: astimezone() cannot be applied to a naive datetime # 会抛出一个异常,原因就是因为navie类型的时间不能调用astimezone方法
    
    
    now = now.replace(tzinfo=pytz.timezone('Asia/Shanghai'))
    utc_now = now.astimezone(utc_timezone)
    # 这时候就可以正确的转换。
    

    replace方法:

    可以将一个时间的某些属性进行更改。

    django.utils.timezone.now方法:

    会根据settings.py中是否设置了USE_TZ=True获取当前的时间。如果设置了,那么就获取一个aware类型的UTC时间。如果没有设置,那么就会获取一个navie类型的时间。

    django.utils.timezone.localtime方法:

    会根据setting.py中的TIME_ZONE来将一个aware类型的时间转换为TIME_ZONE指定时区的时间。

    DateField:

    日期类型。在Python中是datetime.date类型,可以记录年月日。在映射到数据库中也是date类型。使用这个Field可以传递以下几个参数:

    1. auto_now:在每次这个数据保存的时候,都使用当前的时间。比如作为一个记录修改日期的字段,可以将这个属性设置为True
    2. auto_now_add:在每次数据第一次被添加进去的时候,都使用当前的时间。比如作为一个记录第一次入库的字段,可以将这个属性设置为True

    DateTimeField:

    日期时间类型,类似于DateField。不仅仅可以存储日期,还可以存储时间。映射到数据库中是datetime类型。这个Field也可以使用auto_nowauto_now_add两个属性。

    TimeField:

    时间类型。在数据库中是time类型。在Python中是datetime.time类型。

    navie和aware介绍以及在django中的用法:

    https://docs.djangoproject.com/en/2.0/topics/i18n/timezones/

    EmailField:

    类似于CharField。在数据库底层也是一个varchar类型。最大长度是254个字符。在数据库层面并不会限制存入的数据,而是在ModelForm中会起作用

    FileField:

    用来存储文件的。这个请参考后面的文件上传章节部分。

    ImageField:

    用来存储图片文件的。这个请参考后面的图片上传章节部分。

    FloatField:

    浮点类型。映射到数据库中是float类型。

    IntegerField:

    整形。值的区间是-2147483648——2147483647

    BigIntegerField:

    大整形。值的区间是-9223372036854775808——9223372036854775807

    PositiveIntegerField:

    正整形。值的区间是0——2147483647

    SmallIntegerField:

    小整形。值的区间是-32768——32767

    PositiveSmallIntegerField:

    正小整形。值的区间是0——32767

    TextField:

    大量的文本类型。映射到数据库中是longtext类型。

    UUIDField:

    只能存储uuid格式的字符串。uuid是一个32位的全球唯一的字符串,一般用来作为主键。

    URLField:

    类似于CharField,只不过只能用来存储url格式的字符串。并且默认的max_length是200。


    Field常用的参数

    null:

    如果设置为TrueDjango将会在映射表的时候指定是否为空。默认是为False。在使用字符串相关的Field(CharField/TextField)的时候,官方推荐尽量不要使用这个参数,也就是保持默认值False。因为Django在处理字符串相关的Field的时候,即使这个Fieldnull=False,如果你没有给这个Field传递任何值,那么Django也会使用一个空的字符串""来作为默认值存储进去。因此如果再使用null=TrueDjango会产生两种空值的情形(NULL或者空字符串)。如果想要在表单验证的时候允许这个字符串为空,那么建议使用blank=True。如果你的FieldBooleanField,那么对应的可空的字段则为NullBooleanField

    blank:

    标识这个字段在表单验证的时候是否可以为空。默认是False
    这个和null是有区别的,null是一个纯数据库级别的。而blank是表单验证级别的。

    db_column:

    这个字段在数据库中的名字。如果没有设置这个参数,那么将会使用模型中属性的名字。

    default:

    默认值。可以为一个值,或者是一个函数,但是不支持lambda表达式。并且不支持列表/字典/集合等可变的数据结构。

    primary_key:

    是否为主键。默认是False

    unique:

    在表中这个字段的值是否唯一。一般是设置手机号码/邮箱等。

    更多Field参数请参考官方文档:https://docs.djangoproject.com/zh-hans/2.0/ref/models/fields/


    模型中Meta配置:

    对于一些模型级别的配置。我们可以在模型中定义一个类,叫做Meta。然后在这个类中添加一些类属性来控制模型的作用。比如我们想要在数据库映射的时候使用自己指定的表名,而不是使用模型的名称。那么我们可以在Meta类中添加一个db_table的属性。示例代码如下:

    class Book(models.Model):
        name = models.CharField(max_length=20,null=False)
        desc = models.CharField(max_length=100,name='description',db_column="description1")
    
    class Meta:
        db_table = 'book_model'
    

    以下将对Meta类中的一些常用配置进行解释。

    db_table:

    这个模型映射到数据库中的表名。如果没有指定这个参数,那么在映射的时候将会使用模型名来作为默认的表名。

    ordering:

    设置在提取数据的排序方式。后面章节会讲到如何查找数据。比如我想在查找数据的时候根据添加的时间排序,那么示例代码如下:

    class Book(models.Model):
        name = models.CharField(max_length=20,null=False)
        desc = models.CharField(max_length=100,name='description',db_column="description1")
        pub_date = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            db_table = 'book_model'
            ordering = ['pub_date']
    

    更多的配置,参考官方文档。
    官方文档:https://docs.djangoproject.com/en/2.0/ref/models/options/

    相关文章

      网友评论

          本文标题:django(4)ORM基础

          本文链接:https://www.haomeiwen.com/subject/spbivqtx.html