[django]阅读笔记

https://dwz.cn/FUcnVGi8

新建目录

django-admin.exe startproject myblog

django-admin.exe startproject myblog .

django-admin命令

命令路径

manage.py是对django-admin命令的一个简答的封装

他们startapp功能相同

django-admin存在于安装django后/usr/local/bin/django-admin

manage.py创建目录后存在于当前目录

app目录

settings.py相关

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True  # 为true时, allowhost可以为空, 生产为false+allow自己的域名

ALLOWED_HOSTS = []


# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/ # i18n  internationalization

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

django源码目录(把django当作一个project)

如果你记不住settings.py里的字段名字 ,那请到global_settings.py里去查吧, 这里包含了所有settings.py的字段


http的app

contrib

from django.db import models

from django.contrib import admin
from django.urls import path

from django.shortcuts import render

from django.contrib import admin

makemigration


生成了里面的内容, 是一些py的类,
当model.py发生变化时候, 执行该命令, 会重新生成0002的文件.以此类推.

本质上是sql. 如何查看真实sql呢?

sqlmigrate blog 0001


CREATE TABLE "blog_blogarticle" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(300) NOT NULL, "body" text NOT NULL, "publish" datetime NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "blog_blogarticle_author_id_44cfb7b2" ON "blog_blogarticle" ("author_id");
COMMIT;
migrate  # 真正的执行sql.

settings.py控制插入数据库时时间

from django.contrib.auth.models import User
from django.db import models

# Create your models here.
from django.utils import timezone


class BlogArticles(models.Model):
    title = models.CharField(max_length=300)
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now) ##################
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')

    class Meta:
        ordering = ("-publish",)

    def __str__(self):
        return self.title

默认是utc时间,可以矫正下.

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'


USE_TZ = False

admin后台选项

class BlogArticlesAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'publish')
    list_filter = ('author', 'publish','title')
    search_fields = ('title', 'body')
    raw_id_fields = ('author',)
    date_hierarchy = "publish"
    ordering = ['author', 'publish']


admin.site.register(BlogArticles, BlogArticlesAdmin)

可以点进去看看有哪些选项


ORM


ORM的作用是在关系型数据库和业务实体对象之间进行映射,这样在操作业务对象时,就不需要再去和复杂的SQL语句打交道,只需简单地操作对象的属性和方法。

三大好处

可移植性强
安全性好,不需要考虑sql注入
查询简单

获取详情页

遵循规则:

首页: http://127.0.0.1:8000/blog/
详情: http://127.0.0.1:8000/blog/5/

django2的带参数url

path('<int:question_id>/', views.blog_article, name='blog_article'),

get_object_or_404

def blog_article(request, question_id):
    # article = BlogArticles.objects.get(id=question_id)
    article=get_object_or_404(BlogArticles, id=question_id)

    return render(request, 'blog/content.html', {'article': article})

get_object_or_404: 如果有返回实例, 如果无报404
get_object_ or_ 404(klass,*args, **kwargs)
    kclass: 一个模型
    args: 条件

template设置(django自动搜索模板规则)

注: template和static都是先在指定的目录下搜索, 然后在个app下搜索

maotaipro
├── tutorial
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── templates
│   │   └── tutorial
│   │       ├── index.html
│   │       └── search.html
│   ├── tests.py
│   └── views.py
├── tryit
│   ├── __init__.py
│   ├── admin.py
│   ├── models.py
│   ├── templates
│   │   └── tryit
│   │       ├── index.html
│   │       └── poll.html
│   ├── tests.py
│   └── views.py
├── manage.py
└── maotaipro
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

django template的查找机制
Django 模板查找机制: Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,这样就好了。

static和collectstatic作用

STATIC_URL = '/static/'
 
# 当运行 python manage.py collectstatic 的时候
# STATIC_ROOT 文件夹 是用来将所有STATICFILES_DIRS中所有文件夹中的文件,以及各app中static中的文件都复制过来
# 把这些文件放到一起是为了用apache等部署的时候更方便
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')

现在我们一般将静态文件放在指定的static下即可.
dj18static
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static # 应用 blog 下的 static, 默认会找这个文件夹
│   │   └── 【zqxt.png】
│   ├── tests.py
│   │
│   └── views.py
├── common_static # 已经添加到了 STATICFILES_DIRS 的文件夹
│   └── js
│       └── 【jquery.js】
│
├── dj18static
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
# 这个是默认设置,Django 默认会在 STATICFILES_DIRS中的文件夹 和 各app下的static文件夹中找文件
# 注意有先后顺序,找到了就不再继续找了
STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder"
)

form

from django import forms


class LoginForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)

dir(LoginForm()), 发现有很多的属性,常用的如下

d = {'username':'maotai','password':'123'}
'is_bound',      ******, 判断实例化时有没有传参数
'as_p',          ****** 
'cleaned',         ******
'clean_data',    ****** 取出d = {'username':'maotai','password':'123'}
'is_valid',      ******   判断传参是否正确
'error_class',   ****** 错误class
d = {'password': '123', 'username': 'maotai'}
lf = LoginForm(d)

print(lf)
<tr><th><label for="id_username">Username:</label></th><td><input type="text" name="username" value="maotai" required id="id_username" /></td></tr>
<tr><th><label for="id_password">Password:</label></th><td><input type="password" name="password" required id="id_password" /></td></tr>

lf.as_p()
Out[25]: 
'<p><label for="id_username">Username:</label> <input type="text" name="username" value="maotai" required id="id_username" /></p>
<p><label for="id_password">Password:</label> <input type="password" name="password" required id="id_password" /></p>'


lf.is_bound
Out[18]: 
True

lf.is_valid()
Out[19]: 
True

lf.cleaned_data
Out[22]: 
{'password': '123', 'username': 'maotai'}


lf.errors
Out[12]: 
{'username': ['这个字段是必填项。']}

自定义认证界面, django的authenticate, login

前端输入的登录表单ok ---> auth用户名密码 --> 执行login分配sessionid登录完成

from django.contrib.auth import authenticate, login
from django.http import HttpResponse
from django.shortcuts import render

from account.forms import LoginForm


def user_login(request):
    if request.method == "POST":
        print(request.POST)
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            cd = login_form.cleaned_data
            print(cd)
            user = authenticate(username=cd['username'], password=cd['password'])
            if user:
                login(request, user)
                return HttpResponse('login succ')
            else:
                return HttpResponse('error')
    return render(request, 'account/login.html')

# 扩展django默认的user表
AUTH_USER_MODEL = "users.UserProfile"

# 自定义认证逻辑backend
AUTHENTICATION_BACKENDS = ('users.views.CustomBackend',)

默认: AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']

https://www.cnblogs.com/iiiiiher/p/8331268.html
https://www.cnblogs.com/iiiiiher/p/8395177.html

from django.contrib.auth import authenticate, login
from django.contrib.auth.backends import ModelBackend
from django.shortcuts import render

# Create your views here.
from users.models import UserProfile

# 自定义authenticate backend的处理认证逻辑
## 密码对返回user 密码错返回none
class CustomBackend(ModelBackend):  # 继承认证类,diy它
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:  # 验证用户名密码 否则返回None
            user = UserProfile.objects.get(username=username)  # 表示有这个用户 查处自定义usermodel的用户名,
            from django.db.models import Q #或的关系
            user = UserProfile.objects.get(Q(username=username) | Q(email=username)) 
            if user.check_password(password):  # 表示这个用户密码正确, 这里django存储密码是加密的,必须用其下这个方法加密后比对是否正确
                return user
        except Exception as e:
            return None  # 密码错误返回None

# 获取用户名密码-->表单验证-->authenticate backend的处理认证逻辑-->login登录

def user_login(request):
    if request.method == "POST":
        user_name = request.POST.get("username", "")
        pass_word = request.POST.get("password", "")
        user = authenticate(username=user_name, password=pass_word)
        if user is not None:  # 用户名密码验证成功
            login(request, user)  # django执行用户登录
            return render(request, "index.html")
        else:
            return render(request, "index.html", {})

    elif request.method == "GET":
        return render(request, "login.html", {})

django的标准库contrib

http://djangobook.py3k.cn/2.0/chapter16/

Django标准库
Django的标准库存放在 django.contrib 包中。每个子包都是一个独立的附加功能包。 这些子包一般是互相独立的,不过有些django.contrib子包需要依赖其他子包。

在 django.contrib 中对函数的类型并没有强制要求 。其中一些包中带有模型(因此需要你在数据库中安装对应的数据表),但其它一些由独立的中间件及模板标签组成。

django.contrib 开发包共有的特性是: 就算你将整个django.contrib开发包删除,你依然可以使用 Django 的基础功能而不会遇到任何问题。 当 Django 开发者向框架增加新功能的时,他们会严格根据这一原则来决定是否把新功能放入django.contrib中。

django.contrib 由以下开发包组成:

admin : 自动化的站点管理工具。 请查看第6章。

admindocs:为Django admin站点提供自动文档。 本书没有介绍这方面的知识;详情请参阅Django官方文档。

auth : Django的用户验证框架。 参见第十四章。

comments : 一个评论应用,目前,这个应用正在紧张的开发中,因此在本书出版的时候还不能给出一个完整的说明,关于这个应用的更多信息请参见Django的官方网站. 本书没有介绍这方面的知识;详情请参阅Django官方文档。

contenttypes : 这是一个用于引入文档类型的框架,每个安装的Django模块作为一种独立的文档类型。 这个框架主要在Django内部被其他应用使用,它主要面向Django的高级开发者。 可以通过阅读源码来了解关于这个框架的更多信息,源码的位置在 django/contrib/contenttypes/。

csrf : 这个模块用来防御跨站请求伪造(CSRF)。参 见后面标题为”CSRF 防御”的小节。

databrowse:帮助你浏览数据的Django应用。 本书没有介绍这方面的知识;详情请参阅Django官方文档。

flatpages : 一个在数据库中管理单一HTML内容的模块。 参见后面标题为“Flatpages”的小节。

formtools:一些列处理表单通用模式的高级库。 本书没有介绍这方面的知识;详情请参阅Django官方文档。

gis:为Django提供GIS(Geographic Information Systems)支持的扩展。 举个例子,它允许你的Django模型保存地理学数据并执行地理学查询。 这个库比较复杂,本书不详细介绍。 请参看http://geodjango.org/上的文档。

humanize : 一系列 Django 模块过滤器,用于增加数据的人性化。 参阅稍后的章节《人性化数据》。

localflavor:针对不同国家和文化的混杂代码段。 例如,它包含了验证美国的邮编 以及爱尔兰的身份证号的方法。

markup : 一系列的 Django 模板过滤器,用于实现一些常用标记语言。 参阅后续章节《标记过滤器》。

redirects : 用来管理重定向的框架。 参看后面的“重定向”小节。

sessions : Django 的会话框架。 参见14章。

sitemaps : 用来生成网站地图的 XML 文件的框架。 参见13章。

sites : 一个让你可以在同一个数据库与 Django 安装中管理多个网站的框架。 参见下一节:

syndication : 一个用 RSS 和 Atom 来生成聚合订阅源的的框架。 参见13章。

webdesign:对设计者非常有用的Django扩展。 到编写此文时,它只包含一个模板标签{% lorem %}。详情参阅Django文档。

shortcut快捷函数

This module collects helper functions and classes that "span" multiple levels
of MVC. In other words, these functions/classes introduce controlled coupling
for convenience's sake.
django.shortcuts 收集了“跨越” 多层MVC 的辅助函数和类。 换句话讲,这些函数/类为了方便,引入了可控的耦合。

django中间件, 从请求到view

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

django 中的render和render_to_response()和locals()

http://www.cnblogs.com/wangchaowei/p/6750512.html

return render(request, 'blog_add.html', {'blog': blog, 'form': form, 'id': id, 'tag': tag})
 return render_to_response('blog_add.html', {'blog': blog, 'form': form, 'id': id, 'tag': tag})

很明显,如果使用render_to_response就省去了render里传递的request。

1.加载template
2.生成contenxt
3.render成字符串
4.httpresponse返回

使用render_to_response的背景

由于加载模板、填充 context 、将经解析的模板结果返回为 HttpResponse 对象这一系列操
作实在太常用了,Django 提供了一条仅用一行代码就完成所有这些工作的捷径。
该捷径就是位于 django.shortcuts 模块中名为 render_to_response() 的函数。
大多数时候,你将使用 render_to_response() ,而不是手动加载模板、创建 Context 和 HttpResponse 对象。

实例

下面就是使用 render_to_response() 重新编写过的 current_datetime 范例。

from django.shortcuts import render_to_response
import datetime
def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})

render_to_response总结

大变样了!让我们逐句看看代码发生的变化:
1.我们不再需要导入 get_template 、 Template 、 Context 和 HttpResponse 。
2.相反, 我们导入 django.shortcuts.render_to_response 。
3.import datetime 继续保留.

4.在 current_datetime 函数中,我们仍然进行 now 计算,但模板加载、上下文创建、模板解析和 HttpResponse 创建工作均在对 render_to_response() 的调用中完成了。

5.由于 render_to_response() 返回 HttpResponse 对象,因此我们仅需在视图中return 该值。
6.render_to_response() 的第一个参数必须是要使用的模板名称。
7.如果要给定第二个参数,那么该参数必须是为该模板创建 Context 时所使用的字典。如果不提供第二个参数,render_to_response() 使用一个空字典。

https://blog.csdn.net/Mr_JJ_Lian/article/details/6787786

django部署 gu or uwsgi

django的models.DateTimeField

- 有字段可以填写
from django.utils import timezone


class BlogArticles(models.Model):
    title = models.CharField(max_length=300)
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
auto_now=true          # 前端无法显示字段, 创建时间
auto_now_add=true # 更新时间

子表获取父表的数据

方法1:
class BlogArticles(models.Model):
    title = models.CharField(max_length=300)
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')

前端:
<small>{{ article.author.username }}</small>

参考: https://www.cnblogs.com/iiiiiher/p/9560240.html

inspectdb: 库--->生成模型

orm使用原生的sql

https://docs.djangoproject.com/en/2.1/topics/db/sql/
https://my.oschina.net/watcher/blog/1573503

debug =false不仅影响static 还能让allow_host失效

==true会使得不去查app/static/app/xxx.css

获取用户权限

request.GET request.POST属性和方法

  • request.get获取的是字典

http://127.0.0.1:8000/blog/?a=1

uuid和datetime

http://blog.51cto.com/xujpxm/2090382

class Datacenter(models.Model):
    id = models.UUIDField('机房ID', default=uuid.uuid4, primary_key=True)
    zone = models.ForeignKey(Zone, verbose_name='所在区域', on_delete=models.PROTECT)
    dc_name = models.CharField('机房', max_length=128, unique=True)
    networks = models.CharField('IP地址段', max_length=128, blank=True, unique=True)
    update_time = models.DateTimeField('更新时间', auto_now=True)

    def __str__(self):
        return self.dc_name

    class Meta:
        verbose_name = '机房配置'
        verbose_name_plural = '机房配置'
from datetime import datetime
add_time = models.DateTimeField(default=datetime.now)



publish = models.DateTimeField(default=timezone.now)


auto_now=true          # 前端无法显示字段, 创建时间
auto_now_add=true # 更新时间

默认主键用的是AutoField,作为pk,每次自增1

class Blog(models.Model):
    sid = models.AutoField(primary_key=True)

admin里是看不到这个字段的

还有类似的DateTimeField: django:DateTimeField如何自动设置为当前时间并且能被修改
http://www.nanerbang.com/article/5488/

djanog的QueryDict

APPEND_SLASH = False

https://www.liurongxing.com/django-append_slash-true.html

APPEND_SLASH = False

http://example.com/hello
自动跳转到
http://example.com/hello/

model自定义字段

css/js等静态文件找不到

但是我这个已经配置了

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static', ),
)

原来是
debug=false了. 靠.

连接mysql

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'bbs',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'OPTIONS':{
            'init_command': 'SET default_storage_engine=INNODB;',
        },
    }
}
原文地址:https://www.cnblogs.com/iiiiiher/p/9560956.html