第一个Django demo

平台:Pycharm Django

使用 Pycharm 进行开发,需要提前在 Pycharm 中(File > Settings > Project: Python > Project Interpreter)下载 Django ,安装过程会自动把 Django 路径加载到系统的环境变量中。

进入 cmd 查询 Django 是否安装成功。出现以下一系列命令,说明已安装成功。

 

创建第一个项目 guest ,可在 Pycharm 的 Terminal 中使用命令行创建

G:\Python>django-admin startproject guest

创建完成,Django 自动生成以下目录结构

guest/
    manage.py
    guest/
        __init__.py
        settings.py
        urls.py
        wsgi.py

 

guest/manage.py : Django 项目的命令行工具,三种命令模式可选:

$ django-admin <command> [options]
$ manage.py <command> [options]
$ python -m django <command> [options]

guest/guest/__init__.py : 空文件夹,表示 guest 目录是 python 的标准包

guest/guest/settings.py : 项目的配置文件,包含Django 模块应用配置、数据库配置、模板配置等

guest/guest/urls.py : 关于项目的 URL 声明,定义 URLconf

guest/guest/wsgi.py : 提供服务的入口,暂未知 wsgi 有何用

guest/manage.py : 一个命令行工具,通过 命令  python manage.py 可以查看 manage 所提供的命令

 

创建第一个应用

G:\Python\guest>python mangage.py startapp sign

在 Terminal 中使用以上命令创建 sign 应用后,会自动生成一些文件(templates 目录不是自动生成),如下面目录结构:

目录文件说明:

migrations/ : 用于记录models 中数据的变更

admin.py : 映射 models 中的数据到 Django 自带的后台

apps.py : 用于应用程序配置

models.py : 创建数据表模型,与数据库相关操作对应

views.py : 视图文件,控制向前端输送内容

 

启动项目,使用 runserver 命令

G:\Python\guest>python manage.py runserver

Django 默认在127.0.0.1:8000 进行监听,在浏览器输入 http://127.0.0.1:8000 , 若可见 It worked! 提示,说明 Django 已经可以工作。

PS: Django 在 settings.py 中默认开启 DEBUG = True,若改为 False ,则无法正常打开网页。 127.0.0.1 指向本机(本电脑)

 

使用模板

创建模板使用 templates 目录,Django 会默认去查找该目录下面的 HTML 文件,在上面已创建的 sign 应用下面,创建了一个

templates/index.html 文件

 

简述 Django 工作流(以默认访问的地址为例):

向浏览器发送一个请求,如 http://127.0.0.1:8000/index/ ,Django 默认在127.0.0.1地址,端口8000 上进行监听,根据 URL 的路径 /index/,

到 urls.py 文件中对 /index/ 路径进行匹配(前提:在 urls.py 中对该路径已进行配置),匹配到该路径,则调用相应的视图函数,匹配不到,则提示网页找不到(404)。

url 路径匹配模式如下:

urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index), #添加index/ 路径配置
]

上面/index/ 路径已经提前配置好,下一步根据路径,去调用相应的视图函数 views.index (请求指向 sign 应用下的 views.py 文件中的 index 函数)。该函数定义如下:

def index(request):
return render(request, "index.html")

该函数使用 render 模板,返回一个已经写好的 HTML 页面。该模板放在 templates 目录下,使用render() 函数进行调用,浏览器最终呈现 index.html 页面的内容(返回响应)。

 

各模块要点

Django MTV 开发模式

M(Models): 代表模型,进行数据存取。处理与数据相关的事物,既如何存取,如何验证有效。

T(Template): 代表模板,表现层。处理如何展示相关页面或其它类型文档。

V(View): 代表视图,业务逻辑层。处理如何存取模型及调用恰当的模板展现数据,可看做是模型与模板之间的桥梁。

URLconf模块 urls.py

1、URLconf 模块包含了 URL 模式(简单的正则表达式)到视图函数(views.py)的简单映射。URLconf的值通过 ROOT_URLCONF 进行设置, 在 /settings.py 中
'''python ROOT_URLCONF = 'guest.urls' ''' Django 会加载 urls.py 文件,并在 urlpatterns 中依次匹配每个 URL 模式,匹配到就指向对应的视图函数处理。

 2、使用正则表达式定义URL模式,使用 re_path() 方法而不是 path() ,命名正则表达式组的语法是(?P <name> pattern),其中name是参数变量的名称,pattern是要匹配的模式。

例子:

from django.urls import path, re_path
from sign import views

urlpatterns = [
    re_path('sign_index/(?P<eid>[0-9]+)/', views.sign_index),  # 签到

]

URL调度器使用参考:https://docs.djangoproject.com/zh-hans/2.0/topics/http/urls/

3、在 guest/url.py 文件的 urlpatterns的 path() 中插入 include() 方法,在当包括其它 URL 模式时你应该使用 include()。函数 include() 允许引用其它 URLconfs。每当 Django

遇到 :func:~django.urls.include 时,它会截断与此项匹配的 URL 的部分,并将剩余的字符串发送到 URLconf 以供进一步处理。

例子:

from django.urls import path, re_path, include
# 导入 sign 应用 views 文件
from sign import views

urlpatterns = [
    path('api/', include('sign.urls', namespace="sign")),  # 接口根路径
]

 

sign.urls 有自己的路径,任意一个都可以放在 /api/ 后面,形成完成的路径。例如其中某一个匹配例子(在 sign.urls 中的 urlpatterns):

from django.urls import path
from sign import views_if

app_name = "sign"
urlpatterns = [
    # sign system interface:
    # ex : /api/add_event/
    path('add_event/', views_if.add_event, name='add_event'),
    
]

 

include() 使用 参考:https://docs.djangoproject.com/zh-hans/2.0/intro/tutorial01/

 

views.py 

(Django 中的视图的概念是「一类具有相同功能和模板的网页的集合」)

1、 index() 视图函数,接受 Web 请求并且返回 Web 响应。(Django 只要求视图返回的是一个 HttpResponse ,或者抛出一个异常)

2、 login_action(request) 处理登录请求,客户端发送的请求信息都包含在 request 中。request.POST 通过 .get() 方法获取“username”和“password”所获取的用户名和密码

3、 HttpResponseRedirect() 对路径进行重定向,将登录成功后的请求指向了 /event_manage/ 目录

4、 render()方法:render(request, template_name, context=None, content_type=None, status=None, using=None)
作用:把 context(一个给定的上下文字典)的内容, 加载进 templates(一个给定的模板)中定义的文件, 并通过浏览器渲染呈现. 参数讲解: request: 是一个固定参数.

template_name: templates 目录下定义的文件, 要注意路径名. 比如'templates\polls\index.html', 参数就要写‘polls\index.html’

context: 要传入文件中用于渲染呈现的数据, 默认是字典格式

content_type: 生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值。

status: http的响应代码,默认是200.

using: 用于加载模板使用的模板引擎的名称。

5、auth.authenticate() 方法,用于登录认证。它接受两个参数,用户名 username 和 密码 password ,并在用户名和密码正确的情况下返回一个 User 对象。 否则 authenticate() 返回None。

6、auth.login() 方法,用于用户登录。该函数接受一个 HttpRequest 对象和一个 User 对象作为参数并使用Django的会话(session)框架把用户的ID保存在该会话中。

7、user.is_active 判断用户名和密码是否有效。

8、 @login_required 此装饰器显限制某个视图函数必须登录才能访问,默认跳转的 URL 中会包含“/accounts/login/”,需要在 urls.py 中添加新的路径配置。

9、Django 中 objects.all()、objects.get()、objects.filter() 的区别
  · all 返回的是QuerySet(查询集)对象,程序并没有真的在数据库中执行SQL语句查询数据,但支持迭代,使用for循环可以获取数据。

  · get(** kwargs) 返回的是Model对象,类型为列表,说明使用get方法会直接执行sql语句获取数据。

  · filter(** kwargs) 和get类似,但支持更强大的查询功能,查询到的值唯一且不变。

10、request.session.get('user') 为了获取 sessionid ,用于认证用户

11、Paginator(guest_list, 2),Django提供了一个分页器类Paginator(django.core.paginator.Paginator),可以很容易的实现分页的功能。该类有两个构造参数,一个是数据的集合,另一个是每页放多少条数据
分页器相关源码参考 

https://docs.djangoproject.com/zh-hans/2.2/_modules/django/core/paginator/

12、table.objects.get()返回一个对象,而table.objects.filter()返回一个对象列表

13、get_object_or_404(klass, *args, **kwargs) 用特定查询条件获取某个对象,成功则返回该对象,否则引发一个 Http404
参数: · klass 接受一个 Model 类,Manager 或 QuerySet 实例,表示你要对该对象进行查询
· **kwargs 查询条件,格式需要被 get() 和 filter() 接受

Django 文档解释
为什么我们使用辅助函数 get_object_or_404() 而不是自己捕获 ObjectDoesNotExist 异常呢?还有,为什么模型 API 不直接抛出 ObjectDoesNotExist 而是抛出 Http404 呢?

因为这样做会增加模型层和视图层的耦合性。指导 Django 设计的最重要的思想之一就是要保证松散耦合。一些受控的耦合将会被包含在 django.shortcuts 模块中。

14、

 

templates 模板

1、使用模板动态的生成 HTML

2、简单了解两个方法:GET 和 POST
GET: 从指定的资源请求数据,一般用于查询数据;
POST: 向指定的资源提交要被处理的数据,一般用于更新数据,提交表单。

3、GET 方法将用户提交的数据添加到 URL 中,路径后面跟问号 “?”,用于区分路径和参数(问号后面是参数),多个参数之间用“&”隔开。

4、 index.html 中{% csrf_token %},是CSRF令牌(跨站请求伪造),通过该令牌判断POST请求是否来自同一个网站

5、 form 表单中的 action="/login_action" 指定了提交的路径,根据该路径去 urls.py 中匹配 URL 模式,再去 views.py 中执行相应的视图。

 

models.py

1、模型基础知识
· 每一个 model 都是 Python 类,都要继承 django.db.models.Model 类 · 模型的每个属性表示数据库的表字段 · Django 把这一些已经给了一个自动生成的访问数据库的 API · 创建模型时,后台会在数据库自动生成一个 id 作为主键,这个主键可以被覆盖

2、str()是被 print 函数调用的,str()返回的内容以字符串形式输出,该方法告诉 Python 如何将对象以 str 的方式显示出来。

3、类 Meta 的作用:

模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据库表名(db_table)或者人类可读的单复数名称(verbose_name 和verbose_name_plural)。在模型中添加class Meta是完全可选的,所有选项都不是必须的。
更多 Django 元数据选项 Django Meta

4、makemigrations 与 migrate 命令的作用
在 models.py 中设计好模型后,需要将模型中的各个属性(或改动)映射到数据库中,首先通过 makemigrations 命令操作
\guest> python manage.py makemigrations sign
相当于在该 sign 应用中的 migrations 目录,记录了所有的关于 modes.py 的改动(比如添加字段,删除模型等),会自动生成 0001_initial.py 记录操作, 但是这个改动还没有作用到数据库文件
\guest> python manage.py migrate
将对模型的改动作用到数据库文件,比如产生 table ,修改字段的类型等
注意:若更换数据库,数据库迁移前要保证在建模阶段,把相关字段都填写正确和规划完整,不然迁移过程会暴露许多问题。这里说的是数据库迁移,迁移执行的是同步表字段,在 MySQL 数据库中生成表,而数据是无法复制过去的,可能迁移后需要重新造数据,不然就提前导出数据,迁移完后再导入。

 

数据库
1、在 django 中配置 mysql,在 setting.py 修改 DATABASES 就好

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'NAME': 'test',
        'USER': 'root',
        'PASSWORD': '',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },

    }
}

 

test.py
(该部分编写单元测试代码,对发布会、嘉宾管理、嘉宾搜索等进行测试)

 

Django shell

1、进入 Django shell 模式
\guest> python manage.py shell
在 Ipython 模式下编辑

2、获得某个 table 中的所有对象
table.objects.all()

In [3]: Event.objects.all()
Out[3]: <QuerySet [<Event: 荣耀发布会>]>

In [4]: Guest.objects.all()
Out[4]: <QuerySet []>  

2、插入数据的两种方式

In [7]: e1 = Event(id=2, name='红米发布会', limit=20, status=True, address='北京', start_time=datetime(2016,8,10,14,0,0))
   ...: e1.save()
Event.objects.create(id=1, name='荣耀发布会', limit=200, status=True, address='深圳会展中心', start_time=datetime(2018,9,22,14,0,0))

3、查询数据
table.objects.get()

In [14]: e1 = Event.objects.get(name='红米 MAX 发布会')
In [15]: e1
Out[15]: <Event: 红米 MAX 发布会>
In [16]: e1.address
Out[16]: '北京会展中心'

4、过滤数据
table.objects.filter() 相当于 SQL 语句中的 LIKE 语句

In [18]: e2 = Event.objects.filter (name__contains='发布会')
In [19]: e2
Out[19]: <QuerySet [<Event: 荣耀发布会>, <Event: 红米发布会>, <Event: 红米 MAX 发布会>]>

5、删除数据
table.objects.get().delete()

In [20]: Guest.objects.get(phone='13423454334').delete()
Out[20]: (1, {'sign.Guest': 1})

6、更新数据

In [21]: g3 = Guest.objects.get(phone='13012345690')
In [22]: g3.realname = 'andy2'
In [23]: g3.save()
In [24]: Guest.objects.select_for_update().filter(phone='13012345690').update(realname='andy')
Out[24]: 1

 

其它

1、创建 django_session 表,存放用户 sessionid 对应的信息
命令:\guest> python manage.py migrate 使用 “migrate” 进行数据迁移,Django 会同时生成 auth_user 表

2、Django 自带 Admin 管理后台,创建登录 Admin 后台的管理员账号
命令:\guest> python manage.py createusperuser
Admin 管理后台登录地址: http:127.0.0.1:8000/admin/

 

问题

1、当对手机号进行查询,若将手机号进行 encode ,则无法正常进行查询,且分页器按每页2条记录进行划分。
原因:查询手机号时,输入的数字,网页按照默认的编码格式将参数进行提交。后台获取该参数后,在进行一次 encode ,则无法与正确的手机号进行匹配,故
无法使用手机号成功查询,且分页器因为手机号无法正常匹配,也无法显示分页。

2、在 sign_index() 方法 和 sign_index_action() 方法中,传入的第二个参数无法更换为其它值,如 event_id ,否则报错,
sign_index() got an unexpected keyword argument 'eid 将 event_id 换为 eid 后,传参变得正常。
在谷歌看了挺多资料,也看了相关源码,仍未找到该问题原因。猜测, eid 在这里作为一个位置参数,且名字不可更改。

 

posted @ 2019-05-15 17:53  chenzy01  阅读(2270)  评论(0编辑  收藏  举报