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.py
332行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**表,如下:
```python
+----+--------------+------------------------------------------+----------------------------+
| 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生成的。
再查看数据库中的表:
```sql
+----------------------------+
| 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
映射数据库就可以正常执行了。
本文原文首发来自博客专栏Python Web开发实战,由本人转发至https://www.helloworld.net/p/O997UGeiALU2D,其他平台均属侵权,可点击https://blog.csdn.net/CUFEECR/article/details/108207448查看原文,也可点击https://blog.csdn.net/CUFEECR浏览更多优质原创内容。