第一篇包含基础的安装和环境配置,还有一些基础的尝试,戳链接: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,如图所示
然后按照图示方式直接连接即可。
然后我这边点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)
就会看到按照我们写的要求创建出来的表了。
————————————————————————————————————————
创建对象的其它方法
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() # create方法自带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
本文地址:https://blog.jixiaob.cn/?post=39
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。