版权声明:本文为CSDN博主「越过山丘,佳人等候」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42118531/article/details/107229662

1、ORM模型迁移
迁移命令
1.makemigrations:将模型生成迁移脚本。模型所在的app,必须放在settings.py中的INSTALLED_APPS中。这个命令有以下几个常用选项:

app_label:后面可以跟一个或者多个app,那么就只会针对这几个app生成迁移脚本。
如果没有任何的app_label,那么会检查INSTALLED_APPS中所有的app下的模型,针对每一个app都生成响应的迁移脚本。
–name:给这个迁移脚本指定一个名字。
–empty:生成一个空的迁移脚本。如果你想写自己的迁移脚本,可以使用这个命令来实现一个空的文件,
然后自己再在文件中写迁移脚本。(一般不用)

2.migrate:将新生成的迁移脚本。映射到数据库中。创建新的表或者修改表的结构。以下一些常用的选项:

app_label:将某个app下的迁移脚本映射到数据库中。如果没有指定,那么会将所有在INSTALLED_APPS中的app下的模型都映射到数据库中。
app_label migrationname:将某个app下指定名字的migration文件映射到数据库中。
–fake:可以将指定的迁移脚本名字添加到数据库中。但是并不会把迁移脚本转换为SQL语句,修改数据库中的表。
–fake-initial:将第一次生成的迁移文件版本号记录在数据库中。但并不会真正的执行迁移脚本。

3.showmigrations:查看某个app下的迁移文件。如果后面没有app,那么将查看INSTALLED_APPS中所有的迁移文件。

python manage.py showmigrations [app名字]
1

4.sqlmigrate:查看某个迁移文件在映射到数据库中的时候,转换的SQL语句

python manage.py sqlmigrate book 0001_initial
1
2、migrations中的迁移版本和数据库中的迁移版本对不上怎么办?
1.找到哪里不一致,然后使用python manage.py —fake [版本名字],将这个版本标记为已经映射。
2.删除指定app下migrations和数据库表django_migrations中和这个app相关的版本号,然后将模型中的字段和数据库中的字段保持一致,再使用命令python manage.py makemigrations重新生成一个初始化的迁移脚本,之后再使用命令python manage.py migrate —fake-initial来将这个初始化的迁移脚本标记为已经映射。以后再修改就没有问题了。
migrate作用
1、将migrations生成的迁移脚本文件翻译成SQL语句,在数据库中执行SQL语句
2、映射数据库出现的问题不是SQL语句问题,是错误记录在django_migrations表中。

迁移版本和数据库中的迁移版本对不上解决步骤:

3、根据已有的表自动生成模型
在实际开发中,有些时候可能数据库已经存在了。如果用Django来开发一个网站,读取的是之前已经存在的数据库中的数据。那么该如何将模型与数据库中的表映射呢?根据旧的数据库生成对应的ORM模型,需要以下几个步骤:

1.Django给我们提供了一个inspectdb的命令,可以非常方便的将已经存在的表,自动的生成模型。想要使用inspectdb自动将表生成模型。首先需要在settings.py中配置好数据库相关信息。不然就找不到数据库。

DATABASES = {
‘default’: {
# 修改数据库引擎
‘ENGINE’: ‘django.db.backends.mysql’,
# 数据库名字
‘NAME’: ‘old_db_demo’,
# 用户名
“USER”: “root”,
# 密码
“PASSWORD”: “root”,
# 地址
“HOST”: ‘127.0.0.1’,
# 端口
“PORT”: 3306,
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

python manage.py inspectdb

python manage.py inspectdb > models.py
1
2
3
2.修正模型:新生成的ORM模型有些地方可能不太适合使用。比如模型的名字,表之间的关系等等

2.1 模型名:自动生成的模型,是根据表的名字生成的,可能不是你想要的。这时候模型的名字你可以改成任何你想要的。
2.2 模型所属app:根据自己的需要,将相应的模型放在对应的app中。放在同一个app中也是没有任何问题的。只是不方便管理。
2.3 模型外键引用:将所有使用ForeignKey的地方,模型引用都改成字符串。这样不会产生模型顺序的问题。另外,如果引用的模型已经移动到其他的app中了,那么还要加上这个app的前缀。
2.4 让Django管理模型:将Meta下的managed=False删掉,如果保留这个,那么以后这个模型有任何的修改,使用migrate都不会映射到数据库中。
2.5 当有多对多的时候,应该也要修正模型。将中间表注释,然后使用ManyToManyField来实现多对多。并且,使用ManyToManyField生成的中间表的名字可能和数据库中那个中间表的名字不一致,这时候肯定就不能正常连接了。那么可以通过db_table来指定中间表的名字。
2.6 表名:切记不要修改表的名字。不然映射到数据库中,会发生找不到对应表的错误
实例操作:将第一步生成的models.py文件中的模型放入到项目app中的模型文件中,并修改:

同时修改表之间的关系 :article/models.py文件

from django.db import models

Create your models here.
from django.db import models

class Article(models.Model):
title = models.CharField(max_length=100, blank=True, null=True)
content = models.TextField(blank=True, null=True)
author = models.ForeignKey(‘front.User’, models.DO_NOTHING, blank=True, null=True)

# 多对多关系,需要使用中间表模型
tags = models.ManyToManyField(“Tag”, db_table=”article_tag”)

class Meta:
db_table = ‘article’

中间表模型创建之后,这里的模型就不需要了
# class ArticleTag(models.Model):
# article = models.ForeignKey(Article, models.DO_NOTHING, primary_key=True)
# tag = models.ForeignKey(‘Tag’, models.DO_NOTHING)
#
# class Meta:
#
# db_table = ‘article_tag’
# unique_together = ((‘article’, ‘tag’),)

class Tag(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)

class Meta:

db_table = ‘tag’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
settings.py文件设置INSTALLED_APPS中的项目app名称

INSTALLED_APPS = [
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘front’,
‘article’,
]

1
2
3
4
5
6
7
8
9
10
11
3 执行命令python manage.py makemigrations生成初始化的迁移脚本。方便后面通过ORM来管理表。这时候还需要执行命令python manage.py migrate —fake-initial,因为如果不使用–fake-initial,那么会将迁移脚本会映射到数据库中。这时候迁移脚本会新创建表,而这个表之前是已经存在了的,所以肯定会报错。此时我们只要将这个0001-initial的状态修改为已经映射,而不真正执行映射,下次再migrate的时候,就会忽略他。

4 将Django的核心表映射到数据库中:Django中还有一些核心的表也是需要创建的。不然有些功能是用不了的。比如auth相关表。如果这个数据库之前就是使用Django开发的,那么这些表就已经存在了。可以不用管了。如果之前这个数据库不是使用Django开发的,那么应该使用migrate命令将Django中的核心模型映射到数据库中。

映射到数据库中:

此时可以修改模型文件,添加字段等操作,后续生成迁移脚本和映射数据库都是之前的命令行操作:
python manage.py makemigrations和python manage.py migrate

4、Django限制请求方法
常用的请求method
1.GET请求:GET请求一般用来向服务器索取数据,但不会向服务器提交数据,不会对服务器的状态进行更改。比如向服务器获取某篇文章的详情。
2.POST请求:POST请求一般是用来向服务器提交数据,会对服务器的状态进行更改。比如提交一篇文章给服务器。
限制请求装饰器
Django内置的视图装饰器可以给视图提供一些限制。比如这个视图只能通过GET的method访问等。以下将介绍一些常用的内置视图装饰器。

1.django.views.decorators.http.require_http_methods:这个装饰器需要传递一个允许访问的方法的列表
from django.views.decorators.http import require_http_methods

@require_http_methods([“GET”])
def my_view(request):
pass
1
2
3
4
5
2.django.views.decorators.http.require_GET:这个装饰器相当于是require_http_methods([‘GET’])的简写形式,只允许使用GET的method来访问视图。
from django.views.decorators.http import require_GET

@require_http_methods([“GET”])
@require_GET # 简写方式
def get_view(request):
return HttpResponse(“get_view”)

1
2
3
4
5
6
7
3.django.views.decorators.http.require_POST:这个装饰器相当于是require_http_methods([‘POST’])的简写形式,只允许使用POST的method来访问视图。
from django.views.decorators.http import require_GET, require_POST # 简写方式

@require_http_methods([“POST”])
@require_POST # 简写方式
def post_view(request):
return HttpResponse(“post_view”)

1
2
3
4
5
6
7
8
4.django.views.decorators.http.require_safe:这个装饰器相当于是require_http_methods([‘GET’,‘HEAD’])的简写形式,只允许使用相对安全的方式来访问视图。因为GET和HEAD不会对服务器产生增删改的行为。
from django.views.decorators.http import require_safe

@require_safe
def my_view(request):
pass
1
2
3
4
5
5、页面重定向
重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。

永久性重定向:http的状态码是301,多用于旧网址被废弃了要转到一个新的网址确保用户的访问,最经典的就是京东网站,你输入www.jingdong.com的时候,会被重定向到www.jd.com,因为jingdong.com这个网址已经被废弃了,被改成jd.com,所以这种情况下应该用永久重定向。
暂时性重定向:http的状态码是302,表示页面的暂时性跳转。比如访问一个需要权限的网址,如果当前用户没有登录,应该重定向到登录页面,这种情况下,应该用暂时性重定向。
在Django中,重定向是使用redirect(to, args, permanent=False, *kwargs)来实现的。to是一个url,permanent代表的是这个重定向是否是一个永久的重定向,默认是False。

from django.shortcuts import reverse,redirect
def profile(request):
if request.GET.get(“username”):
return HttpResponse(“%s,欢迎来到个人中心页面!”)
else:
return redirect(reverse(“user:login”))
1
2
3
4
5
6

越过山丘