Cyrus Blog

FLAG{S0_H4PPY_C_U_H3R3} (>.<)

Django的一些需求和解决方案汇总

本文共 1.1k 字,预计阅读时间 5 分钟。

(不xia优jb雅baidu,持man续man更hua新shui)
 

py2编码原因报错

问题描述:
因为各种原因不使用py3而使用py2,Debug开启时报错:
UnicodeEncodeError at /XXX/X
'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
解决方案:
相关报错的文件头部添加以下代码:

1
2
3
import sys
reload(sys)
sys.setdefaultencoding(&#39;utf-8&#39;)

连接额外的数据库

问题描述:
已经使用一个数据库作default,需要临时连接一个数据库;该数据库与default数据库模型无关;仅少量使用,没有高频查询/写入。
此处以额外数据库为MySQL为例。
解决方案:
引入数据库:

1
2
3
4
5
6
import MySQLdb
db = MySQLdb.connect(host='127.0.0.1',
user='root',
passwd='root_password&',
db='database_name')
db_c = db.cursor()

查询和返回:

1
2
3
q = 'select * from table' # MySQL语句,不含行尾分号
db_c.execute(q)
db_c.fetchone()

将任意.py文件中的值传给template

问题描述:
在某个配置文件中有一些全局变量,希望在template中全局使用,并且不用views.py在每次render时都要传值。
此处以在app项目中引入conf.py中全局变量website_title为例。
解决方案:
views.py中添加:

1
2
3
import conf
def global_view(request):
return {'website_title': conf.website_title}

settings.py的TEMPLATES中添加(以下代码加粗部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
# ......
'app.views.global_view'; # ADD THIS
],
},
},
]

django admin自带的user类的扩展

问题描述:
想使用django自带的稳定的user类,不想使用user2等第三方轮子,也不想自己造;不魔改django源码。
此处以在user类中添加姓名(name),身份证号(cardid),电话(phone)为例,并通过gender()返回性别。
解决方案:
在models.py中作相应更改(不推荐,可能失效):

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
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
class ProfileBase(type):
def __new__(cls, name, bases, attrs):
parents = [b for b in bases if isinstance(b, ProfileBase)]
if parents:
fields = []
for obj_name, obj in attrs.items():
if isinstance(obj, models.Field): fields.append(obj_name)
User.add_to_class(obj_name, obj)
UserAdmin.fieldsets = list(UserAdmin.fieldsets)
UserAdmin.fieldsets.append((name, {&#39;fields&#39;: fields}))
return super(ProfileBase, cls).__new__(cls, name, bases, attrs)
class Profile(object):
__metaclass__ = ProfileBase
class Custom_Profile(Profile): # 后台显示自定义部分的标题
name = models.CharField(max_length=255, default='') # 自定义条目
cardid = models.CharField(max_length=18, default='')
phone = models.CharField(max_length=11, default='')
def gender(self): # 自定义函数
x = str(self.cardid[16:17])
if x.isdigit():
if int(x) % 2 == 0:
return 'female'
else:
return 'male'
else:
return 'unknown'

以上方法可能会失效,失效时可以换下面这个解决方案(推荐):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
# user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=255, default='')
cardid = models.CharField(max_length=18, default='')
phone = models.CharField(max_length=11, default='')

def gender(self):
x = str(self.cardid[16:17])
if x.isdigit():
if int(x) % 2 == 0:
return 'female'
else:
return 'male'
else:
return 'unknown'

后端传值给template中的js代码段

问题描述:
将views.py中的一个参数传递给template中某html文件的js代码段。
这里以在前端增加对posts.desc的Markdown渲染为例。
解决方案:
通过编码为json传递数据。
在views.py相关class的render中:

1
return render(request, ‘ctf/detail.html’, {‘posts’: posts, ‘content’: json.dumps({‘t’: posts.desc})})

(需要import json)
在对应的html temaplate中:

1
2
3
4
5
6
7
<div id="md-m">
</div>;
<script>;
content = {{content | safe}};
var md = Mdjs.md2html(content['t']);
document.getElementById("md-m").innerHTML = md;
</script>;

后端增加search和filter

问题描述:
在一个自定义model中,添加搜索和筛选功能。
此处以在record模型中添加以user和post为关键字的搜索和筛选功能。
解决方案:
在admin.py中,注册模块时使用自定义的class

1
2
3
4
class RecordAdmin(admin.ModelAdmin):
search_fields = (‘user‘, ’post‘)
list_filter = (’user’, ‘post’)
admin.site.register(record,RecordAdmin)

注:除此之外还有list_display等功能,详情参考官方英文docs

timezone.now()时区错误和设置时间

问题描述:

  1. timezone.now()在返回的时候返回时区不正常,后端model中则为正常信息。
  2. 如何设置一个timezone格式的时间
    解决方案:
    只要设置了USE_TZ=Truedjango.util.timezone.now()输出地永远是UTC时间,不管你设置的TIME_ZONE是什么。如果USE_TZ=False,则django.util.timezone.now()输出等同于datetime.datetime.now(),也不管TIME_ZONE设置的是什么。
    所以USE_TZ=True就好。
    设置用timezone.datetime(年,月,日,时,分,秒)就好了