Python Django开发 异常及解决办法(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 代码如下

1.Django2.2报错’gbk’ codec can’t decode byte 0xa6 in position 9737

在使用Django时,可能会报错如下:

File "C:\Users\LENOVO\.virtualenvs\Django_Framework-wC9HNSeq\lib\site-packages\django\views\debug.py", line 94, in technical_500_response
    html = reporter.get_traceback_html()
  File "C:\Users\LENOVO\.virtualenvs\Django_Framework-wC9HNSeq\lib\site-packages\django\views\debug.py", line 332, in get_traceback_html
    t = DEBUG_ENGINE.from_string(fh.read())
UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 9737: illegal multibyte sequence
[24/Aug/2020 20:03:51] "GET / HTTP/1.1" 500 59
C:\Users\LENOVO\.virtualenvs\Django_Framework-wC9HNSeq\Lib\site-packages\django\views\debug.py changed, reloading.
Watching for file changes with StatReloader

提示django\views\debug.py332行GBK解码错误,即源码出错,此时只需要修改源码即可。

在PyCharm中按住Ctrl键鼠标移到File "C:\Users\LENOVO\.virtualenvs\Django_Framework-wC9HNSeq\lib\site-packages\django\views\debug.py", line 332, in get_traceback_html行(会有蓝色和下划线提示),即可打开源码,在331行和338行的open()方法中加入参数encoding="utf-8"即可,修改后如下:

    def get_traceback_html(self):
        """Return HTML version of debug 500 HTTP error page."""
        with Path(CURRENT_DIR, 'templates', 'technical_500.html').open(encoding="utf-8") as fh:
            t = DEBUG_ENGINE.from_string(fh.read())
        c = Context(self.get_traceback_data(), use_l10n=False)
        return t.render(c)
    def get_traceback_text(self):
        """Return plain text version of debug 500 HTTP error page."""
        with Path(CURRENT_DIR, 'templates', 'technical_500.txt').open(encoding="utf-8") as fh:
            t = DEBUG_ENGINE.from_string(fh.read())
        c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
        return t.render(c)

此时再运行就不会报错。

2.Django在使用原生SQL插入数据到MySQL数据库报错Unknown column ‘XXX’ in ‘field list’"

Django中可以使用ORM操作数据库,也可以使用原生SQL,在使用原生SQL插入数据时,报错:

_mysql.connection.query(self, query)
django.db.utils.OperationalError: (1054, "Unknown column 'XXX' in 'field list'")

这是在Python中使用单引号和双引号错误导致的,错误的方法是cursor.execute('insert into book(name,price) values("%s", "%s")' % (name, price)),即外层是单引号、内层是双引号,可能是MySQL中对双引号和单引号的使用与Python中不一致,因此报错,改为外层双引号、内层单引号即可,如下:

cursor.execute("insert into book(`name`, `price`) values('%s', '%s')" % (name, price))

3.映射数据库时提示No migrations to apply

我们都知道,Django中一般使用的是ORM进行数据库操作,在app中的models.py中定义好模型之后,需要先执行python manage.py makemigrations命令生成迁移脚本文件,再执行python manage.py migrate命令进行数据库映射。

有时候明明执行makemigrations命令可以正常产生脚本文件,但是在执行migrate命令时会提示:

Operations to perform:
  Apply all migrations: admin, auth, book, contenttypes, sessions
Running migrations:
  No migrations to apply.

这可能是因为在当前Django项目之前,还有别的Django项目也用到了同样的数据库,并且存在相同的app,导致了生成了名称相同的迁移脚本文件因此映射记录已经存在于django_migrations表中(映射记录都会保存到该表中),会被认为当前项目app中的迁移文件已经被执行,因此无需再执行。

django_migrations表示意如下:

+----+--------------+------------------------------------------+----------------------------+    
| id | app          | name                                     | applied                    |    
+----+--------------+------------------------------------------+----------------------------+    
|  1 | contenttypes | 0001_initial                             | 2020-09-11 02:28:06.214540 |    
|  2 | auth         | 0001_initial                             | 2020-09-11 02:28:06.482821 |    
|  3 | admin        | 0001_initial                             | 2020-09-11 02:28:06.820916 |    
|  4 | admin        | 0002_logentry_remove_auto_add            | 2020-09-11 02:28:06.888777 |    
|  5 | admin        | 0003_logentry_add_action_flag_choices    | 2020-09-11 02:28:06.901704 |    
|  6 | contenttypes | 0002_remove_content_type_name            | 2020-09-11 02:28:06.967527 |    
|  7 | auth         | 0002_alter_permission_name_max_length    | 2020-09-11 02:28:06.999439 |    
|  8 | auth         | 0003_alter_user_email_max_length         | 2020-09-11 02:28:07.037338 |    
|  9 | auth         | 0004_alter_user_username_opts            | 2020-09-11 02:28:07.049306 |    
| 10 | auth         | 0005_alter_user_last_login_null          | 2020-09-11 02:28:07.087205 |    
| 11 | auth         | 0006_require_contenttypes_0002           | 2020-09-11 02:28:07.090199 |    
| 12 | auth         | 0007_alter_validators_add_error_messages | 2020-09-11 02:28:07.112138 |    
| 13 | auth         | 0008_alter_user_username_max_length      | 2020-09-11 02:28:07.152031 |    
| 14 | auth         | 0009_alter_user_last_name_max_length     | 2020-09-11 02:28:07.193919 |    
| 15 | auth         | 0010_alter_group_name_max_length         | 2020-09-11 02:28:07.232815 |    
| 16 | auth         | 0011_update_proxy_permissions            | 2020-09-11 02:28:07.245782 |    
| 17 | sessions     | 0001_initial                             | 2020-09-11 02:28:07.267760 |    
| 18 | front        | 0001_initial                             | 2020-09-13 09:03:00.399662 |    
| 19 | book         | 0001_initial                             | 2020-09-13 11:29:40.427567 |    
+----+--------------+------------------------------------------+----------------------------+    
19 rows in set (0.00 sec)                                                                        

可以看到,第19条记录app为book,迁移文件名为0001_initial,这是前一个DJango项目的bokk app的初始化映射记录。如果当前项目和之前项目使用了同一个数据库,并且要映射的app也为book,并且也是初始化,在执行migrate命令时,就会出现上述的问题,解决办法有两种:

更换数据库

因为是使用的同一个数据库,所以会出现冲突,所以当前项目可以换一个数据库,在settings.py中进行相关数据库配置即可。

删除django_migrations表记录

将django_migrations表中app为book的记录删除,可以在命令行中执行命令delete from django_migrations where app=book;删除,也可以在可视化工具中手动删除。再进行映射,因为表中没有相关记录,就可以正常映射了,打印:

Operations to perform:
  Apply all migrations: admin, auth, book, contenttypes, sessions
Running migrations:
  Applying book.0001_initial... OK

即说明进行映射成功。

此时再查看django_migrations表,如下:

+----+--------------+------------------------------------------+----------------------------+       
| id | app          | name                                     | applied                    |       
+----+--------------+------------------------------------------+----------------------------+       
|  1 | contenttypes | 0001_initial                             | 2020-09-11 02:28:06.214540 |       
|  2 | auth         | 0001_initial                             | 2020-09-11 02:28:06.482821 |       
|  3 | admin        | 0001_initial                             | 2020-09-11 02:28:06.820916 |       
|  4 | admin        | 0002_logentry_remove_auto_add            | 2020-09-11 02:28:06.888777 |       
|  5 | admin        | 0003_logentry_add_action_flag_choices    | 2020-09-11 02:28:06.901704 |       
|  6 | contenttypes | 0002_remove_content_type_name            | 2020-09-11 02:28:06.967527 |       
|  7 | auth         | 0002_alter_permission_name_max_length    | 2020-09-11 02:28:06.999439 |       
|  8 | auth         | 0003_alter_user_email_max_length         | 2020-09-11 02:28:07.037338 |       
|  9 | auth         | 0004_alter_user_username_opts            | 2020-09-11 02:28:07.049306 |       
| 10 | auth         | 0005_alter_user_last_login_null          | 2020-09-11 02:28:07.087205 |       
| 11 | auth         | 0006_require_contenttypes_0002           | 2020-09-11 02:28:07.090199 |       
| 12 | auth         | 0007_alter_validators_add_error_messages | 2020-09-11 02:28:07.112138 |       
| 13 | auth         | 0008_alter_user_username_max_length      | 2020-09-11 02:28:07.152031 |       
| 14 | auth         | 0009_alter_user_last_name_max_length     | 2020-09-11 02:28:07.193919 |       
| 15 | auth         | 0010_alter_group_name_max_length         | 2020-09-11 02:28:07.232815 |       
| 16 | auth         | 0011_update_proxy_permissions            | 2020-09-11 02:28:07.245782 |       
| 17 | sessions     | 0001_initial                             | 2020-09-11 02:28:07.267760 |       
| 18 | front        | 0001_initial                             | 2020-09-13 09:03:00.399662 |       
| 20 | book         | 0001_initial                             | 2020-09-16 08:51:09.527889 |       
+----+--------------+------------------------------------------+----------------------------+       
19 rows in set (0.00 sec)                                                                           

此时可以看到,第20条记录即为刚生成的,同时是当前项目的app生成的。

再查看数据库中的表:

+----------------------------+            
| Tables_in_django_fw        |            
+----------------------------+            
| auth_group                 |            
| auth_group_permissions     |            
| auth_permission            |            
| auth_user                  |            
| auth_user_groups           |            
| auth_user_user_permissions |            
| book                       |            
| book_article               |            
| book_book                  |            
| django_admin_log           |            
| django_content_type        |            
| django_migrations          |            
| django_session             |            
| front_book                 |            
+----------------------------+            
14 rows in set (0.00 sec)                 
  • 表book_article即是成功映射生成的表。

4.Django中使用DateTimeField类定义字段时提示DateTimeField XXX.xxx received a naive datetime

在使用DateTimeField类定义字段并进行数据库映射,再进行访问测试时,提示警告信息如下:

RuntimeWarning: DateTimeField XXX.xxx received a naive datetime (2020-09-16 19:35:14.528853) while time zone support is active.
  warnings.warn("DateTimeField %s received a naive datetime (%s)"

意思是当时区支持开启时,DateTimeField接受了一个naive time。

如需要直接解决问题可以直接跳到总结部分第(1)点。

在Django中有两种时间,即naive time和aware time两种,前者是不带时区标记的时间格式,后者是带有时区标记的时间格式。

在settings.py中一般会进行时区的默认设置,如下:

TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True

其中,USE_TZ参数用于控制是否使用时区,TIME_ZONE用于选择具体的时区,并且TIME_ZONE只有在USE_TZ设置为False时才起作用。

(1)USE_TZ为True时使用带时区标记的aware时间格式,并且默认将aware的时间设为UTC即东0区,可以将UTC时间转化为所在时区的本地时间,如模板中即可对时间使用date过滤器过滤为本地时间,如下:

{% for article in articles %}
    <p>{{ article.release_time | date:'H:i:s' }}</p>
{% endfor %}

(2)USE_TZ为False时使用的就是不带时区标记的naive时间格式。

因此可以总结如下:

(1)对于国内项目,可以进行配置如下:

TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

即USE_TZ为False,并且设置TIME_ZONE为我国的时区。

此时在定义模型字段时设置DateTimeField的属性时再使用auto_now_add=True、auto_now=True或者default=datetime.now均能以当前时间作为存储到数据库中的时间,并且不会报错。

(2)对于国外或全球性的项目,USE_TZ需要设置为True,并使用模板过滤器或者时间计算转化为当地所在时区的时间。

5.使用ListView展示数据显示警告信息UnorderedObjectListWarning

Django开发中经常会遇到需要将数据以列表的形式展示出来的兵,此时一般会用到ListView,如下:

class ArticleListView(ListView):
    model = Article
    template_name = 'article_list.html'
    paginate_by = 10
    context_object_name = 'articles'
    ordering = 'create_time'
    page_kwarg = 'page'
    def get_context_data(self, **kwargs):
        context = super(ArticleListView, self).get_context_data(**kwargs)
        for key, value in context.items():
            print(key, value)
        return context
    def get_queryset(self):
        return Article.objects.filter(id__lte=78)

在访问时,会出现警告信息,如下:

UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class 'article.models.Article'> QuerySet.
  return self.paginator_class(

即UnorderedObjectListWarning无序对象列表警告,提示是未对数据进行排序,因此可以对数据进行排序。

有两种方式实现:

(1)在模型中定义ordering属性

在模型中的Meta子类中定义模型的全局属性,ordering即是用来控制默认排序方式的,所以可以通过该属性来设置排序方式,如下:

class Article(models.Model):
    title = models.CharField(max_length=30)
    content = models.TextField()
    create_time = models.DateTimeField(auto_now_add=True)
    class Meta:
        ordering = ['id']

(2)在get_queryset(self)中设置order_by()

重写类视图的get_queryset(self)方法,在获取到数据后调用order_by()方法指定排序字段,如下:

class ArticleListView(ListView):
    model = Article
    template_name = 'article_list.html'
    paginate_by = 10
    context_object_name = 'articles'
    ordering = 'create_time'
    page_kwarg = 'page'
    def get_context_data(self, **kwargs):
        context = super(ArticleListView, self).get_context_data(**kwargs)
        for key, value in context.items():
            print(key, value)
        return context
    def get_queryset(self):
        return Article.objects.filter(id__lte=78).order_by('create_time')

6.CentOS部署Django项目映射数据库时报错perationalError: (1366, “Incorrect string value: ‘\xE7\x94\xA8\xE6\x88\xB7’ for column ‘name’ at row 1”)

将Django项目迁移到CentOS进行部署,在执行python3 manage.py migrate映射数据库时,可能会报错如下:

_mysql.connection.query(self, query)
MySQLdb._exceptions.OperationalError: (1366, "Incorrect string value: '\\xE7\\x94\\xA8\\xE6\\x88\\xB7' for column 'name' at row 1")

这可能是因为新建数据库时需要指定编码格式,而在迁移到CentOS后,新建数据库时并没有指定数据库的编码格式,导致不能识别出不在编码集中的字符。

解决办法如下:

先修改Django项目的配置文件,如settings.py如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST':'127.0.0.1',
        'PORT':'3306',
        'NAME':'db_name',
        'USER':'root',
        'PASSWORD':'root',
        'TEST': {
            'CHARSET' : 'utf8',
            'COLLATION':'utf8_general_ci'
        }
    }
}

然后执行drop database db_name;删除所使用的数据库,最后执行CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;指定编码格式重新创建数据库。

此时再执行python3 manage.py migrate映射数据库就可以正常执行了。


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
API C++ 开发者
PySide vs PyQt:Python GUI开发史诗级对决,谁才是王者?
PySide 和 PyQt 是 Python GUI 开发领域的两大利器,各有特色。PySide 采用 LGPL 协议,更灵活;PyQt 默认 GPL,商业使用需授权。两者背后团队实力雄厚,PySide 得到 Qt 官方支持,PyQt 由 Riverbank Computing 打造。API 设计上,PySide 简洁直观,贴近原生 Qt;PyQt 增加 Pythonic 接口,操作更高效。性能方面,两者表现优异,适合不同需求的项目开发。选择时可根据项目特点与开源要求决定。
335 20
|
2月前
|
Shell 数据库 网络架构
Django+DRF 实战:从异常捕获到自定义错误信息(下)
本文详解了 Django REST Framework 中 ValidationError 的验证流程与优先级,涵盖字段内置验证、自定义验证方法、对象级验证及数据库约束,并通过实战演示如何自定义异常提示信息。
95 1
Django+DRF 实战:从异常捕获到自定义错误信息(下)
|
2月前
|
存储 前端开发 应用服务中间件
Django 实战:静态文件与媒体文件从开发配置到生产部署
Django项目中,静态文件(Static Files)和媒体文件(Media Files)是两类不同用途的文件。本文详细介绍了它们的区别、配置方法以及在开发与生产环境中的处理方式,并结合用户头像上传功能进行实战演示,最后讲解了如何通过Nginx或OpenResty部署静态与媒体文件服务。
130 1
|
2月前
|
数据采集 存储 数据库
Python爬虫开发:Cookie池与定期清除的代码实现
Python爬虫开发:Cookie池与定期清除的代码实现
|
3月前
|
人工智能 搜索推荐 数据可视化
用 Python 制作简单小游戏教程:手把手教你开发猜数字游戏
本教程详细讲解了用Python实现经典猜数字游戏的完整流程,涵盖从基础规则到高级功能的全方位开发。内容包括游戏逻辑设计、输入验证与错误处理、猜测次数统计、难度选择、彩色输出等核心功能,并提供完整代码示例。同时,介绍了开发环境搭建及调试方法,帮助初学者快速上手。最后还提出了图形界面、网络对战、成就系统等扩展方向,鼓励读者自主创新,打造个性化游戏版本。适合Python入门者实践与进阶学习。
305 1
|
3月前
|
Linux 数据库 数据安全/隐私保护
Python web Django快速入门手册全栈版,共2590字,短小精悍
本教程涵盖Django从安装到数据库模型创建的全流程。第一章介绍Windows、Linux及macOS下虚拟环境搭建与Django安装验证;第二章讲解项目创建、迁移与运行;第三章演示应用APP创建及项目汉化;第四章说明超级用户创建与后台登录;第五章深入数据库模型设计,包括类与表的对应关系及模型创建步骤。内容精炼实用,适合快速入门Django全栈开发。
113 1
|
4月前
|
人工智能 C# Python
处理python异常
本文介绍了Python中的异常处理机制,并实现了一个简单的异常装饰器。通过`try/except`语句捕获异常,结合`finally`子句完成清理工作。为进一步优化代码结构,文章提出了使用装饰器处理异常的方法,避免函数中大量冗长的异常处理语句。通过类封装异常装饰器,多个函数可共享异常处理逻辑,提升代码简洁性和可维护性。总结强调了装饰器在异常处理中的优势,使代码更加优雅高效。
121 27
|
2月前
|
数据安全/隐私保护 网络架构 UED
Django+DRF 实战:从异常捕获到自定义错误信息
本文介绍了DRF(Django REST framework)中的异常处理机制,重点讲解了内置异常类ValidationError的使用场景与示例。同时通过用户注册功能的实战演示,展示了如何在序列化器中自定义参数校验规则,并在视图中捕获并返回结构化的错误信息,提升接口的健壮性与用户体验。
64 0
|
3月前
|
存储 算法 数据可视化
用Python开发猜数字游戏:从零开始的手把手教程
猜数字游戏是编程入门经典项目,涵盖变量、循环、条件判断等核心概念。玩家通过输入猜测电脑生成的随机数,程序给出提示直至猜中。项目从基础实现到功能扩展,逐步提升难度,适合各阶段Python学习者。
177 0
|
3月前
|
数据采集 存储 监控
抖音直播间采集提取工具,直播间匿名截流获客软件,Python开发【仅供学习】
这是一套基于Python开发的抖音直播间数据采集与分析系统,包含观众信息获取、弹幕监控及数据存储等功能。代码采用requests、websockets和sqlite3等...

推荐镜像

更多