时区设置
时间分层查询报错Database returned an invalid datetime value. Are time zone definitions for your database installed?
但插入数据时是按照UTC时间插入的
参考这里 设置如下就好了:
# LANGUAGE_CODE = 'en-us'
#
# TIME_ZONE = 'UTC'
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
# 主要是设置为不使用UTC
# USE_TZ = True
查看数据库设置:
mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name | Value |
+------------------+---------------------+
| system_time_zone | China Standard Time |
| time_zone | SYSTEM |
+------------------+---------------------+
2 rows in set (0.00 sec)
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2019-03-25 17:28:03 |
+---------------------+
1 row in set (0.00 sec)
mysql> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+
1 row in set (0.00 sec)
静态文件和数据库一些设置
保持连接最大时间10分钟
DEBUG = True
ALLOWED_HOSTS = ['*']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "webdb",
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
'CONN_MAX_AGE': 60*10,
# 'ATOMIC_REQUESTS': True , 将每个http请求加入事务, 去除这种<请求-事务>绑定,可以@transaction.non_atomic_requests
# 'AUTOCOMMIT': False, 禁用django事务管理, 自己处理
}
}
STATIC_URL = '/static/'
# STATIC_ROOT = os.path.join(BASE_DIR, 'static/').replace("\\","/")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static/").replace("\\", "/"),
)
运行项目内应用测试模块 tests.py
,报错Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured
加上以下初始化配置,等效于python manage.py shell
进入控制台:
from django.test import TestCase
# Create your tests here.
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your project.settings')
django.setup()
# 模型类的导入必须在django启动初始化配置以后进行
from index.models import Author
Author.objects.create(name="小明", age=20, email="110@gmail.com")
模型字段
机器读变量名 question_text = CharField('text', max_length=200)
人类读Field的第一个参数 pub_date = DateTimeField('date published')
激活模型
插入polls应用的配置 INSTALLED_APPS = [ 'polls.apps.PollsConfig',...]
生成迁移文件 $ python manage.py makemigrations polls
如果django 无法迁移数据库,可能是因为没有指定应用polls
检查问题 python manage.py check
查看迁移文件sql语句 python manage.py sqlmigrate polls 0001
迁移到数据库 python manage.py migrate
QuerySet缓存
使用缓存需要两步:
1.创建QuerySet
对象时不会缓存,但重复使用这个对象是缓存的基础,
2. 需要全部遍历时,就触发一次缓存,如果只查询一部分,则不会触发,
3. 继续查询,则使用缓存,保持了数据同步性,
4. 丢掉缓存,再次查询,只要回到1. 步骤,再创建QuerySet
对象即可,
QuerySet惰性
求值触发数据操作:
迭代遍历,列表生成式,切片,Pickling/缓存,repr,len,list,bool,or,and,if,in
添加从表记录
通过从表,必须加上主表id Choice(choice_text='Not Much',votes=0,question_id=1).save()
查询出来 Choice.objects.first().question
或者通过主表,获得从表集合对象进行创建
q = Question.objects.get(pk=1)
c = q.choice_set.create(choice_text='Just hacking again',votes=0)
c.question
关系创建
双下划线__
分隔关系 q.choice_set.filter(choice_text__startswith='J')
应用URL配置
URL自解析标签 {% url 'detail' question.id %}
app命名空间URL app_name = 'polls'
{% url 'polls:detail' question.id %}
报错Reverse for 'detail' with arguments '('',)' not found
原因是question.id
写成了question_id
而context
中没有这个变量
防御跨站点请求伪造,内部URL的POST表单都应该使用{% csrf_token %}
模板标签。
通用显示视图
model
属性告诉通用视图, 它作用哪个模型,但ListView
好像可以通过被覆写的方法确认到model
属性
DetailView
期望从URL中捕获名为"pk
"的主键值
ListView
自动生成的context 变量默认是question_list
, 需要覆写context_object_name属性
和get_queryset方法
模型测试流程
python manage.py test polls
查找polls 应用下的测试用例
它找到 django.test.TestCase
类的一个子类
它为测试创建了一个特定的数据库
它查找用于测试的方法 —— 名字以test
开始
它运行pub_date创建一个Question为未来30天的 test_was_published_recently_with_future_question实例
…并使用assertIs()
方法,发现它的was_published_recently()返回True,尽管我们希望它返回False
静态文件
链接入应用内static目录
{% load static %}
<link rel="stylesheet" href="{% static 'polls/style.css' %}" type="text/css">
静态文件之间,使用相对路径来相互链接
后台表单字段集
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
('Text', {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]
admin.site.register(Question, QuestionAdmin)
项目模板
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
},
]
可重用打包
README.rst 文件可以看到,重用需要设置:
INSTALLED_APPS
插入APP名,
路由中include
导入URLconf
,
python manage.py migrate
迁移数据库,
打开admin访问后台,或者打开应用分享
=====
Polls
=====
Polls is a simple Django app to conduct Web-based polls. For each
question, visitors can choose between a fixed number of answers.
Detailed documentation is in the "docs" directory.
Quick start
-----------
1. Add "polls" to your INSTALLED_APPS setting like this::
INSTALLED_APPS = [
...
'polls',
]
2. Include the polls URLconf in your project urls.py like this::
url(r'^polls/', include('polls.urls')),
3. Run `python manage.py migrate` to create the polls models.
4. Start the development server and visit http://127.0.0.1:8000/admin/
to create a poll (you'll need the Admin app enabled).
5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.
事务管理,悲观锁
如何在Django模型中管理并发性
1.要在Django中锁定一个对象,我们使用select_for_update
2.锁定一行需要一个数据库事务, transaction.atomic()
来定义事务。
3.我们使用类方法而不是实例方法 - 我们告诉数据库要上锁,然后它会返回锁的对象给我们。 为了实现这一点,我们需要从数据库中获取对象。 如果我们使用self,那么就是在操作一个已经从数据库中获取出来的对象,这个对象无法保证自己是没有被上锁的。
4.帐户中的所有操作都在数据库事务中执行。
5.乐观锁(隔离级别必须设置为读提交, 以保证独到的是其他线程修改后的数据), 否则读的是本线程的数据, 则锁无效
指定user表
继承AbstractUser, 需要在setting中重载, 需要先迁移数据库
AUTH_USER_MODEL = 'users.UserProfile'
users:你的app
UserProfile:model
django 自带验证, 登录, 登出
UserInfo表集成自AbstractUser
验证: 用户名和密码(需要加密成密文才能验证, 但不关心加密类型)
登录: 将用户对象绑定在request对象上, 给cookies生成了sessionid字段, 说明session是建立的, 但没有将字段存入session
登出: 删除cookies中sessionid字段
# 验证, 登出
user = auth.authenticate(username=username, password=password)
if user and user.isactive:
auth.login(request, user)
return redirect('index')
# 登出
auth.logout(request)
获取choice的值
要获取一个choices的第二元素的值,可以使用get_FOO_display()方法
可以这样重新__str__方法:
def __str__(self):
return self.get_name_display()
Django表单防重复提交
解决思路:
Step 1:首先我们在进入表单填写页面时,对该页面(或view吧)随机生成一个校验字符串并存放于Session中,在页面form中新增一个hidden input来存放,以便提交时一起POST到服务器端;
Step 2:当POST时,服务器端将收到的校验串与Session中对应值比对,若相同则正常提交,否则跳转至指定的错误提示页面;需要注意的是当比对成功后, 必须立即将该Session的值设置为空,这样才可保证页面再次POST时表单中的校验串就无法于Session中的空值比对成功。