欢迎食用『主界面』~,这里是赵苦瓜的看板娘desu~
【点滴记录】Django框架的入门 - 第二篇(切换SQL数据库、基本模板、Django Shell、简单数据集连、模型层)
首页 > 点滴记录    作者:赵苦瓜   2021年1月20日 8:49 星期三   热度:229°   百度已收录  
时间:2021-1-20 8:49   热度:229° 

第一篇包含基础的安装和环境配置,还有一些基础的尝试,戳链接:https://blog.jixiaob.cn/?post=37

————————————————————————————————————————

如何将默认的SQLite切换成MySQL数据库?

在settings.py中把DATABASES修改一下即可

DATABASES = {
    'default': {
        # 'ENGINE': 'django.db.backends.sqlite3',    一定是注释掉,不要删
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'ENGINE': 'django.db.backends.mysql',     # 引擎为MySQL
        'NAME': 'GP1HelloDjango',  # 数据库名称
        'USER': 'root',    # 用户名
        'PASSWORD': 'Zheshimima',  # 密码
        'HOST': '127.0.0.1',  # 主机地址
        'PORT': 3306,   # 端口,可以加引号,也可以不加
    }
}
之后连接MySQL数据库,创建刚才写的数据库名



CREATE DATABASE GP1HelloDjango charset=utf8;
创建好之后使用Pycharm连接。


选择Database的加号,选择Data Sourse,选择MySQL,如图所示

连接MySQL数据库.png

然后按照图示方式直接连接即可。

连接MySQL数据库2.png

然后我这边点Test Connection的时候提示我时区错误,我点击下方的set timezone设置时区,再返回去就能连上了。

连接之后还不能直接进行迁移,因为还没有安装连接MySQL的驱动。

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?                                              # 没安装MySQLdb驱动,连接会报错


连接MySQL的三种驱动:

① MySQLClient   兼容python2,3 都能直接使用。致命缺点:对MySQL的安装有要求,必须在指定位置存在配置文件。

② Python-MySQL   对python2支持的非常棒,不支持Python3

③ Pymysql   支持python2,python3,这个库还可以伪装成前两个库。


这里就要使用pymysql的伪装来进行

在项目的__init__.py里面这样写:

import pymysql

pymysql.install_as_MySQLdb()



之后在Terminal里面执行迁移就可以成功进行了输入python manage.py migrate

然后我输入完之后还是报错了:


 query = query.decode(errors='replace')
AttributeError: 'str' object has no attribute 'decode'


去网上查了一下,需要把operations.py(从报错提示里面点链接进去)大概第146行的decode改为encode

    def last_executed_query(self, cursor, sql, params):
        # With MySQLdb, cursor objects have an (undocumented) "_executed"
        # attribute where the exact query sent to the database is saved.
        # See MySQLdb/cursors.py in the source distribution.
        query = getattr(cursor, '_executed', None)
        if query is not None:
            query = query.encode(errors='replace')    # 这里改为encode
        return query
这个是Django 2.2不兼容pymysql导致的,详见这篇博客:


https://zhuanlan.zhihu.com/p/112516747


然后就迁移成功了,可以在右边的库里面看到。

注意:这个迁移只会把表的结构迁移过去,之前表里面的数据是不会迁移过去的。

MySQL:关系型数据库。

常见的关系,一对一(外键添加唯一约束OneToOneField),一对多(外键ForeignKey),多对多(额外一张关系表,通过两个外键ManyToManyField)

大项目中一般不推荐外键。

下面演示创建一个学生关系表:

from django.db import models

# Create your models here.


class Grade(models.Model):
    g_name = models.CharField(max_length=32)   # 创建年级


class Student(models.Model):
    s_name = models.CharField(max_length=16)  # 创建学生
    s_grade = models.ForeignKey(Grade)     # 年级作为学生的外键
之后生成迁移文件,python manage.py makemifrations


然后我们获得了一个报错:TypeError: __init__() missing 1 required positional argument: 'on_delete'

这个是2.0之后的Django做的更改,定义外键时必须写on_delete,我们在上面ForeignKen()里面加上on_delete=models.CASCADE即可。

on_delete的详细参数详见这篇博客:https://www.cnblogs.com/gerenboke/p/12091960.html

之后我们就可以正常地生成迁移文件了。然后执行迁移python manage.py migrate


————————————————————————————————————————

基本模板

render模板是一个简化了的过程,实际过程如下:

from django.template import loade


def index2(request):
    index_2 = loader.get_template('index2.html')    # 加载模板
    result = index_2.render()                     # 将模板渲染成HTML字符串(如果挖空了,括号里面context = context(字典))
    return HttpResponse(result)
——————————————————————————————————————


Django Shell —— 方便的调试工具

在Terminal中输入python manage.py shell

这个shell是集成了这个django项目的shell(集成了Python环境的Shell终端)

比如要从之前的Two的app里面查学生信息:

(venv) C:\Users\dell\PycharmProjects\djangoProject1>python manage.py shell
Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from Two.models import Student
>>> students = Student.objects.all()
>>> for student in students:
...     print(student.s_name)
...
Jack                              #  查询学生信息
Jerry3sadsada
Jerry4
Jerry54
>>> student = Student()         # 添加一个学生
>>> student.s_name = 'Fucker'
>>> student.save()
>>> 


————————————————————————————————————————

简单数据集连

def get_grade(request):                       # 通过学生获取grade信息
    student = Student.objects.get(pk=1)
    grade = student.s_grade
    return HttpResponse('Grade %s' % grade.g_name)
def get_students(request):              #  通过grade获取学生信息
    grade = Grade.objects.get(pk=1)
    students = grade.student_set.all()    # 这一步是关键。其中的student是类似object的东西 context = {
        "students": students
    }
    return render(request, 'students.html', context=context)

————————————————————————————————————————

Model(模型)

在企业开发中,我们通常都是从数据开始开发的

Django对各州数据库都提供了很好的支持,对不同的数据库使用统一调用的API,可以根据不同的业务需求使用不同的数据库。

开发流程:

1.配置数据库

2.定义模型类(一个模型类对应数据库中的一张表)

3.生成迁移文件

4.执行迁移生成数据表

5.使用模型进行增删改查(CRUD)操作


ORM(Object Relational Mapping)对象关系映射

可以简单理解为翻译机,是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。(核心思想也是一个解耦合的过程)


重要概念:模型、表、属性、字段

一个模型类在数据库中对应一张表,在模型类中定义的属性,对应该模型对照表中的一个字段。

定义属性:

由于django的查询方式,命名不允许连续的下划线

拒绝中文、空格、特殊字符、关键字、保留字在你的路径中。拒绝数字开头。

逻辑删除:对于重要的数据都做逻辑删除,不做物理删除,实现方法是isDelete属性,类型为BooleanField,默认值为False

字段类型:

AutoField    一个根据ID自动增长的IntegerField  如果不指定,一个主键字段将自动添加到模型中。

CharField(max_length=字符长度)  字符串,默认表单样式是TextInput

TextField    大文本字段,一般超过4000使用,默认的表单控件是Textarea

IntegerField    整数

DecimalField(max_digits=None, decimal_place=None)    使用Python的Decimal实例表示的十进制浮点数(高精度计算)

                      位数总数               小数点后的数字位数

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

BooleanField    true/false 字段,此字段的默认表单控制是CheckboxInput

NullBooleanField    支持null、true、false三种值

DateField    日期字段

TimeField    时间字段

DateTimeField    日期时间字段

FileField    一个上传文件的字段   (存路径)

ImageField    继承了FieldField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image

字段选项:

null:True允许空值,默认False

blank:True允许空白"",默认值是False

db_colum:字段的名称,如果未指定则为属性的名称

db_index:True会在表中为此字段创建索引(不能滥用,只针对外键)

default:默认值

primary_key:主键字段



创建模型类:

原选项:在模型类中定义Meta,用于设置元信息(类中类)

比如定义一个Person类:

class Person(models.Model):

    p_name = models.CharField(max_length=16, unique=True)
    p_age = models.IntegerField(default=18, db_column='age')  # 字段名改为age
    # False代表男,True代表女
    p_sex = models.BooleanField(default=False, db_column='sex')    # 字段名改为sex

    class Meta:
        db_table = 'People'      # 自定义数据表名



    然后生成迁移文件(python manage.py makemigrations)、执行迁移(python manage.py migrate)

就会看到按照我们写的要求创建出来的表了。

People类.png


————————————————————————————————————————

创建对象的其它方法

def add_person(request):
    person = Person.objects.create(p_name='Sunk', p_age=16, p_sex=True)
    # person = Person()               # 两种方法创建对象
    # person.p_name = 'Sunk'
    # person.p_age = 16
    # person.p_sex = True
    person.save()               # 这一句两个方法都得有
    return HttpResponse('Sunk创建成功!')
注意:__init__已经在父类model.Model中使用,在自定义的模型中无法使用

创建对象的方案:

在模型类中增加类方法去创建对象。

Python中的方法有三种,对象方法(可以调用对象的属性,也可以调用类的属性)、类方法(不能调用对象属性)和静态方法(啥都不能调用,不能获取对象属性和类属性)


此外还可以自己写一个类方法创建对象。在Person类中:

@classmethod
    def create(cls, p_name, p_age=100, p_sex=True, p_hobby='gaming'):    # cls表示这个类本身
        return cls(p_name=p_name, p_age=p_age, p_sex=p_sex, p_hobby=p_hobby)
——————————————————————————————————————

模型查询(查询集和过滤器)

查询集表示从数据库获取的对象集合,查询集可以有多个过滤器

过滤器就是一个函数,基于所给的参数限制查询集的结果

模型过滤

之前我们用过object.all()和object.get(),而这在开发中都不常用。

Django有两种过滤器用于筛选记录:

        filter   返回符合筛选条件的数据集(过滤符合条件的数据)

        exclude    返回不符合筛选条件的数据集

多个filter和exclude可以连接在一起查询(疯狂.  链式编程、链式调用)

Person.objects.filter(条件).filter(条件).exclude(条件).filter(条件)

def get_persons(request):
    # persons = Person.objects.filter(p_age__gt=50).filter(p_age__lt=80)  # 获取年龄50<年龄<80的人
  persons = Person.objects.exclude(p_age__lt=50).filter(p_age__lt=80)  # 获取50<=年龄<80的人
  persons_two = persons.filter(p_age__in=[50, 55, 57])  # 可以在刚才的persons的基础上接着filter
  print(type(Person))  # 可以看到类型不是列表,而是<class 'django.db.models.base.ModelBase'>
 context = {
        'persons': persons,
    }
    return render(request, 'PersonList.html', context=context)


gt 大于 lt 小于

还有all()返回所有数据  order_by()排序(默认根据id排序,倒序加-号)  values()一条数据就算一个字典,返回一个列表(可以方便地转换成json)

persons = Person.objects.all().order_by('-id').order_by('p_age')  # 主要按年龄排序,次要按-id排序
    persons_values = persons.values()
    print(persons_values, type(persons_values))  # 查看.values()之后的列表中的字典类型的数据

get()返回一个满足条件的对象。多个或没有满足条件的都会引发异常。  first()返回查询集中的第一个对象。last()返回最后一个 count() 返回对象个数。 exists() 存在返回True。

def get_person(request):
    person = Person.objects.all().first()   # 获取第一个
    print(person.p_name)
    person = Person.objects.all().last()    # 获取最后一个
    print(person.p_name)
    return HttpResponse('获取成功!')
first和last默认情况下是可以正常获取的,但是可能会出现first和last获取到的是相同的对象。==>显式,手动写排序规则



————————————————————————————————————————

状态码

官方占用2~5系列

2xx 请求成功    如:200

3xx  转发(或重定向)  如:301,302

4xx  客户端错误   如:403,404

5xx  服务器内部错误(后端开发人员最不想看到的) 如:500

本文作者:赵苦瓜      文章标题: 【点滴记录】Django框架的入门 - 第二篇(切换SQL数据库、基本模板、Django Shell、简单数据集连、模型层)
本文地址:https://blog.jixiaob.cn/?post=39
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。

返回顶部    首页    后花园  
版权所有:赵苦瓜のBlog~    站长: 赵苦瓜    主题寒光唯美式V2.4.1  程序:emlog   鲁ICP备20030743号-1