【代码】啃Django文档

这篇博客详细探讨了Django项目中的时区设置,解决时间分层查询报错的问题,以及静态文件、数据库配置和URL自解析。还讨论了QuerySet缓存机制,事务管理和并发控制,包括悲观锁和乐观锁的实现。此外,还涉及了Django的模型测试流程、静态文件处理、后台表单字段集、用户认证与登录、防止重复提交的策略等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时区设置
时间分层查询报错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_idcontext中没有这个变量

防御跨站点请求伪造,内部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中的空值比对成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值