初识Django-第一部分

创建项目

python -m django --version # 查看版本号

django-admin startproject project_name # 创建项目
# 层级结构
project_name/ # 项目的容器,可任意更改名称
    manage.py # Django 项目的命令行管理工具
    project_name/ # 纯 Python 包,不可更改名称
        __init__.py # 使其被认为是一个 Python 包
        settings.py # 配置文件
        urls.py #  URL调度器
        asgi.py # 异步Web服务器的配置,并发性能
        wsgi.py # 连接Web服务器和Django应用程序,应用程序能够正确地处理Web请求并返回响应
        
python manage.py runserver # 启动server
python manage.py runserver 8080 # 更换端口号
python manage.py runserver 0.0.0.0:8000 # 监听所有服务器公开IP
# 项目和应用区别:
# 应用是一个专门做某件事的网络应用程序——比如博客系统,或者公共记录的数据库,或者小型的投票程序
# 项目则是一个网站使用的配置和应用的集合。项目可以包含很多个应用。应用可以被很多个项目使用
python manage.py startapp mysapp # 创建应用
# 目录结构
mysapp/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
    
# urls.py配置
urlpatterns = [
    path("myapp/", include("myapp.urls")),
    path("admin/", admin.site.urls),
]

初识Django-第二部分

数据库等相关配置

# 时区设置
TIME_ZONE = 'Asia/Shanghai'
TIME_ZONE = 'UTC'
USE_TZ = True

# mysql数据库设置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        "USER": "root",
        "PASSWORD": "12345678",
        "HOST": "127.0.0.1",
        "PORT": 3306,
        'NAME': "login", # 必须为已存在的数据库名称
    }
}

# 站点语言设置
LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'

# INSTALLED_APPS 默认包括了以下 Django 的自带应用:

django.contrib.admin # 管理员站点, 你很快就会使用它。
django.contrib.auth # 认证授权系统。
django.contrib.contenttypes # 内容类型框架。
django.contrib.sessions # 会话框架。
django.contrib.messages # 消息框架。
django.contrib.staticfiles # 管理静态文件的框架

python manage.py makemigrations (myapp) # (对特定应用) 创建迁移
python manage.py migrate # 应用数据库迁移,用于对于模型的修改进行相应的数据库修改
python manage.py sqlmigrate polls 0001 # 返回迁移过程中使用的sql语句,但并未真正执行迁移

python manage.py createsuperuser # 创建超级管理员

# 往管理员站点注册应用(Question为models中的模型) admin.py
admin.site.register(Question)

初识Django-第三部分

视图

# 在myapp中的views.py文件中编写对应视图,如:
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)
 
# 将其添加到myapp.urls中
urlpatterns = [
    # polls/
    path("", views.index, name="index"),
    # polls/5/
    # 实际调用举例 detail(request=<HttpRequest object>, question_id=34)
    path("<int:question_id>/", views.details, name="detail"),
    # polls/5/results/
    path("<int:question_id>/results/", views.results, name="results"),
    # polls/5/vote/
    path("<int:question_id>/vote/", views.vote, name="vote")
]

# 使用模板视图,在myapp中创建templates目录 再创建myapp目录(是否无用操作?)
# 目录层级
# /templates
# 		/myapp
#		index.html
# Django 将会选择第一个匹配的模板文件,如果你有一个模板文件正好和另一个应用中的某个模板文件重名,
# Django 没有办法 区分 它们。我们需要帮助 Django 选择正确的模板,
# 最好的方法就是把他们放入各自的 命名空间[即 myapp 目录] 中


# 可以在html中使用 {% for %}这类python代码,如:

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

# latest_question_list 为http对象传递的参数
# 创建http对象方式一
from django.http import HttpResponse
from django.template import loader
template = loader.get_template("polls/index.html")
    context = {
        "latest_question_list": latest_question_list,
    }
return HttpResponse(template.render(context, request))


# 创建http对象方式二
from django.shortcuts import render
context = {"latest_question_list": latest_question_list}
return render(request, "polls/index.html", context)

# 对于不存在的对象抛出404错误
from django.http import Http404
try:
	question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
	raise Http404("Question does not exist")
    
# 或者使用快捷函数
# 好处:增加模型层和视图层的耦合性
from django.shortcuts import get_object_or_404
question = get_object_or_404(Question, pk=question_id)

#  get_list_or_404() 
# 工作原理和 get_object_or_404() 一样,除了 get() 函数被换成了 filter() 函数。
# 如果列表为空的话会抛出 Http404 异常


# 去除模板中的硬编码 "/polls/{{ question.id }}/"
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
# 可更改为
href="{% url 'detail' question.id %}"

# 对于多个应用存在相同的视图名称,解决方法
# 在myapp.urls中添加 即模板命名空间
app_name = "myapp"
# 模板文件修改为
href="{% url 'myapp:detail' question.id %}"

初识Django-第四部分

表单与通用视图

# CSRF 令牌 ({% csrf_token %}):
# Django 为了防止跨站请求伪造(CSRF)攻击,要求每个 POST 表单都包含一个 CSRF 令牌。{% csrf_token %} 模板标签会生成这个令牌

# html中
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
# views.py中
question.choice_set.get(pk=request.POST["choice"])
# name="choice" 与 request.POST["choice"]相对应,所获得为  value="{{ choice.id }}" 即主键

from django.urls import reverse
from django.views import generic

reverse("demo:results", args=(question.id,)) # 返回结果为 "/demo/3/results/"

# 通用视图
# ListView 和 DetailView 通用视图分别抽象了 "显示对象列表" 和 "显示特定类型对象的详细页面"
# 期望从 URL 中捕获的主键值被称为 "pk"如:
path("<int:pk>/", views.DetailView.as_view(), name="detail")

# 默认情况下,通用视图 DetailView 使用一个叫做 <app name>/<model name>_detail.html 的模板
# ListView 使用一个叫做 <app name>/<model name>_list.html 的默认模板
# 在我们的例子中,它将使用 "demo/question_detail.html" 模板,也可手动指定
template_name = "demo/detail.html"
# 每个通用视图都需要知道它将要操作的模型,如
class ResultsView(generic.DetailView):
    model = Question
    template_name = "polls/results.html"

初识Django-第五部分

自动化测试

# 所有测试用例写在myapp的tests.py中,并会创建测试数据库 如
class QuestionDetailViewTests(TestCase):
    def test_future_question(self):
        """
        The detail view of a question with a pub_date in the future
        returns a 404 not found.
        """
        future_question = create_question(question_text="Future question.", days=5)
        url = reverse("demo:detail", args=(future_question.id,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)
# 运行myapp测试用例
python manage.py test myapp

# 所有测试用例为TestCase的子类
from django.test import TestCase

# 测试视图 client
from django.test.utils import setup_test_environment
setup_test_environment()
# 安装模板渲染器,将使我们能够检查响应上的一些额外属性
# 如 response.context,否则将无法使用此功能
# 不会建立测试数据库,将针对现有的数据库运行

# django.test.TestCase 类自带一个客户端,使用TestCase无需创建client
# TestCase中
url = reverse("polls:detail", args=(future_question.id,))
response = self.client.get(url)


from django.test import Client
client = Client()
response = client.get("/")
# response = client.get(reverse("polls:index"))
response.status_code
response.content
response.context["latest_question_list"]

# "-pub_date" 表示根据pub_date字段降序排序。在Django中,字段名前加负号(-)表示降序排序
# __lte 是Django ORM中的一个字段查找类型,代表“小于或等于”(less than or equal to)
Question.objects.filter(pub_date__lte=timezone.now()).order_by("-pub_date")[:5]

# 测试断言
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerySetEqual(
            response.context["latest_question_list"],
            [question],
        )
# 其他断言
"""
assertEqual(a, b):检查a和b是否相等。
assertNotEqual(a, b):检查a和b是否不相等。
assertTrue(x):检查x是否为真值(True)。
assertFalse(x):检查x是否为假值(False)。
assertIs(a, b):检查a和b是否是同一个对象(具有相同的身份)。
assertIsNot(a, b):检查a和b是否不是同一个对象。
assertIsNone(x):检查x是否是None。
assertIsNotNone(x):检查x是否不是None。
assertIn(a, b):检查a是否是b的子集或成员(例如,在字符串、列表、元组、集合或字典中)。
assertNotIn(a, b):检查a是否不是b的子集或成员。
assertIsInstance(a, b):检查a是否是b的实例或其子类的实例。
assertNotIsInstance(a, b):检查a是否不是b的实例或其子类的实例。
assertGreater(a, b):检查a是否大于b。
assertGreaterEqual(a, b):检查a是否大于或等于b。
assertLess(a, b):检查a是否小于b。
assertLessEqual(a, b):检查a是否小于或等于b。
assertAlmostEqual(a, b, places=None, msg=None, delta=None):检查a和b是否几乎相等(在指定的位数内)。
assertNotAlmostEqual(a, b, places=None, msg=None, delta=None):检查a和b是否不几乎相等。
assertRegex(s, pattern, msg=None):检查字符串s是否匹配正则表达式pattern。
assertNotRegex(s, pattern, msg=None):检查字符串s是否不匹配正则表达式pattern
"""

初识Django-第六部分

静态文件以及样式表

# 在myapp下创建static目录
# 层级结构:
# /myapp
# 	/static
#		/myapp
#			style.css
#			/images
#				saber.png

# style.css
li a {
    color: green;
}
body {
    background: white url("images/saber.png") no-repeat;
}
# html头部
# 加载静态资源路径
{% load static %}

<link rel="stylesheet" href="{% static 'demo/style.css' %}">

# {% static %} 模板标签在静态文件(例如样式表)中是不可用的,
# 因为它们不是由 Django 生成的,应该始终使用 相对路径 在静态文件之间相互引用

初识Django-第七部分

自定义后台表单

# 原始语句
admin.site.register(Question)
# 修改后[模型后台类]
class QuestionAdmin(admin.ModelAdmin):
    # 将"pub_date"调整至"question_text"之前
    fields = ["pub_date", "question_text"]

admin.site.register(Question, QuestionAdmin)
# 调整顺序后如下图
1.png
# TabularInline单行显示关联对象
class ChoiceInline(admin.TabularInline): # admin.StackedInline会占据大量屏幕空间
    model = Choice
    # 三个关联的选项插槽
    extra = 3
    
class QuestionAdmin(admin.ModelAdmin):
    # 数十个字段的表单,可以将表单分为几个字段集
    # fieldsets 元组中的第一个元素是字段集的标题
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}),
    ]
    # 添加关联的对象,一个 Question 有多个 Choice,此举可以在后台页显示多个Choice选项
    # 相比于直接在admin中创建模型Choice,此方法更能体现出对应关系
    inlines = [ChoiceInline]
    # Django 显示每个对象的 str() 返回的值,如果我们能够显示单个字段,它会更有帮助
    # 使用 list_display 后台选项,它是一个包含要显示的字段名的元组,在更改列表页中以列的形式展示这个对象
    # 使admin中以列表显示
    list_display = ["question_text", "pub_date", "was_published_recently"]
    # 对于"was_published_recently"可在models的定义中修改站点显示
    @admin.display(
        # 表示该列或字段应该显示为布尔值
        boolean=True,
        # 依据目标进行排序
        ordering="pub_date",
        # 增加描述
        description="Published recently?",
    )
    # 添加了一个“过滤器”侧边栏,允许人们以 pub_date 字段来过滤列表
    list_filter = ["pub_date"]
    # 在列表的顶部增加一个搜索框。当输入待搜项时,Django 将搜索 question_text 字段
    # 可以使用任意多的字段——由于后台使用 LIKE 来查询数据
    search_fields = ["question_text"]
# 如下图
2.png
# 修改工程模板,在manage.py同级目录下创建templates目录
# 层级结构
# /templates
# 		/admin
#			base_site.html
# 在settings.py中TEMPLATES添加
"DIRS": [BASE_DIR / "templates"],
# 将默认的 Django 管理界面模板目录中的模板文件 admin/base_site.html 复制到该目录中
# 默认的 Django 管理界面模板目录位于 Django 源代码中(django/contrib/admin/templates)
# 查看源码位置
python -c "import django; print(django.__path__)"

# DIRS 默认是空的,APP_DIRS 被置为 True,Django 会自动在每个应用包内递归查找 templates/ 子目录
# 注意,所有的 Django 默认后台模板均可被复写。
# 若要复写模板,像你修改 base_site.html 一样修改其它文件——先将其从默认目录中拷贝到你的自定义目录,再做修改

初识Django-第八部分

调试工具

# Django Debug Toolbar 是一个用于调试 Django Web 应用程序的有用工具
# 提供面板来提供有关当前请求和响应的调试信息
python -m pip install django-debug-toolbar
"""
与 Django 集成的第三方包需要一些安装后的设置,通常
需要将包的 Django 应用程序添加到你的 INSTALLED_APPS 设置中
有些包需要其他更改,比如添加到你的 URL 配置(urls.py)中

Django Debug Toolbar 请按照 安装指南 中的步骤进行操作
https://django-debug-toolbar.readthedocs.io/en/latest/installation.html
"""