随便学学。。渐渐的发现简书没有lark在线文档好用了。。以后不一定会搬笔记过来了。。大概可能。
- 安装
git clone https://github.com/django/django.git
cd django/
sudo python setup.py install
- 创建第一个django项目
django-admin startproject HelloWorld
python3 manage.py runserver 0.0.0.0:8000
踩坑:
第一次在浏览器输入0.0.0.0:8080发现显示这样的页面:
解决方案:打开这个项目文件夹-settings.py,改其中的ALLOWED_HOSTS = []为ALLOWED_HOSTS = ['*'],成功便会显示如下:
- django项目的目录
settings.py 项目配置
urls.py 项目的URL声明
urls.py 项目的URL声明
manage.py:启动django的主要文件
在写settings.py里的DIRS时,出现了报错:
unsupported operand type(s) for +: 'PosixPath' and 'str' 应该先把BASE_DIR的PosixPath转换成str类型
- 开始写一个小demo
理解深入一下:
假设我们的view.py是这样的:
from django.shortcuts import render
def hello(request):
content = [{"username":"yumi","password":"hahahah"},{"username":"arashi","password":"5*20"}]
# context['hello'] = 'Hello World!'
# 使用 render 来替代之前使用的 HttpResponse
# 这里render参数:request请求对象;template_name使用的模板;context:添加到模板的上下文词典
return render(request, 'hello.html', {"ch":content})
我们可以把这个content看作是从数据库获取到的一系列数据
hello.html这样写:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<th>username</th>
<th>password</th>
{% for item in ch%}
<tr>
<td>{{item.username}}</td>
<td>{{item.password}}</td>
</tr>
{%endfor%}
</table>
</body>
</html>
urls.py里:
from django.conf.urls import url
from HelloWorld.view import hello
urlpatterns = [
# 输入的url以hello/开头的将去匹配hello这个请求
# 例如,当输入为hello/开头时都会去执行view.py里的hello方法
url("^hello/",hello),
]
起服务:在这个项目文件夹里python manage.py runserver
在浏览器中输入http://127.0.0.1:8000/hello/ 即可看到:
接下来,如果我们想有一个表单提交输入的数据,插入到表格中,可以这么写:
hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test post data</title>
</head>
<body>
<form action="/hello/" method="post">
{% csrf_token %}
<P>
<label >用户名:</label>
<input type="text" name ='username'/>
</P>
<P>
<label>密码:</label>
<input type="text" name='password'/>
</P>
<p><input type="submit" value="提交"/></p>
</form>
<!--<h1>{{result.username}}</h1>-->
<table border="1">
{%for line in ch%}
<tr>
<td>{{line.username}}</td>
<td>{{line.password}}</td>
</tr>
{%endfor%}
</table>
</body>
view.py
def check(request):
name=request.POST.get("username",None)
pwd = request.POST.get("password",None)
content = [{"username": "yumi", "password": "hahahah"}, {"username": "arashi", "password": "5*20"}]
content.append({"username":name,"password":pwd})
return render(request, 'hello.html', {"ch":content})
- url和path
from django.urls import path
path(route,view,kwargs=None,name=None)
route:路径
view:view中的哪个方法
name:好像是用来跳转新网址用的?
新建应用:python manage.py startapp polls
外层的settings.py中INSTALLED_APPS里添加"polls",新建的 app 如果不加到 INSTALL_APPS 中的话, django 就不能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)
假设在urls.py中,我们需要更改路由,从add/3/4的形式变成了add/3and4,那么我们的网页中超链接依然有很多相对路径是add/3/4,需要做大量的更高。如果我们这么写~
超链接中使用name命名的那个方法,由于这个方法需要传入变量,所以在超链接也是传入变量的:
<a href="{%url 'add2' 4 5%}">计算 4+5</a>
一定要记得add2是加了括号的!这里url接收的第一个参数是name。
接下来,在urls.py的路由里添加一个相当于重定向:
path('add/<int:a>/<int:b>/', polls_view.add2, name='add2'),#之前的url映射到add2方法了
path('add/<int:a>and<int:b>/', polls_view.new_add),#新的url映射到新方法
在view.py里利用reverse把之前的方法映射到新的路由上:
def new_add(request,a,b):
return HttpResponseRedirect(reverse("add2",args=(a,b)))
关于路由更改详情查看这篇文章:
https://www.cnblogs.com/s-1314-521/p/9752814.html
虽然HttpResponses可以返回HTML页面,但是当我们需要对模板进行填充的时候它就不行了,render函数的功能是载入模板,填充数据,然后生成HttpResponse对象,然后返回这个对象。
- django中模板文件的加载方式
在最外层的settings文件中,我们配置了这样一个路径:
INSTALLED_APPS = [
...
# 添加APP
'app1',
'app2',
]
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 修改 DIRS
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
...
},
]
可以看到DIRS,就表示Django从哪里搜索模板文件。假设整体的project目录是这样的:
├── app1
│ │ urls.py
│ │ views.py
│ │ ...
│ └── templates
│ └── app1
│ └── home.html
│
├── app2
│ │ urls.py
│ │ views.py
│ │ ...
│ └── templates
│ └── app2
│ └── home.html
│
│── django_test
│ │ settings.py
│ │ urls.py
│ └── ...
│
└── templates
└── home.html
那么在加载模板的过程中,是会加载在最外层的那个templates/home.html,如果没有,再按照settings.py中INSTALLED_APPS的顺序依次加载每个应用目录下的templates/home.html。那么如果我们想让它加载app1应用目录下的home.html呢?
有两种方法(按以下两种方法的层册结构):
方式一、/project_name/app_name/templates/app_name/template_file_name.html
方式二、/project_name//templates/app_name/template_file_name.html
不论哪种方式,在视图函数中view.py引用模板都只要 "app_name/template_file_name.html" 就可以了
Reference:
django模板加载顺序与模板存放结构位置
django中的templates
7.模板继承
如果一个网站,点击某个按钮只有部分页面的主体变了,整体的排版布局什么的没有特别大的变化,是可以写个父模板,然后让子模板继承父模板来实现的。
父模板这样写:
{% block title %} {% endblock title %}
⚠️注意:
如果在模版中使用extends标签,它必须是模版中的第一个标签
不能在一个模版中定义多个相同名字的block标签
子模版不必定义全部父模版中的blocks,如果子模版没有定义block,则使用了父模版中的默认值
子模板这样写,使用的时候直接在继承的标签内部写就行
{% extends "basepage.html" %}
{% block title %}欢迎光临首页{% endblock %}
2019/11/22发现一个问题,即继承了父模板的子模板在使用include调用其他文件时,没有放在block标签里时显示不出来,其实不止是include显示不出来,如果你在没有重写的情况下在子模板里写啥都显示不出来。看到这么一句话:
重写的覆盖规则
- 不重写,将按照父模板的效果显示
- 重写,则按照重写效果显示`
子模板中block包含的东西为覆盖掉父模板中同名block所包含的东西
8.一些备忘录
如果view文件中传的是一个字典类型的数据,在模板中取字典时使用dict.key来取,而不是python中的dict[key]
render()
from django.shortcuts import render
render(*request*, *template_name*, *context=**None*, *content_type=**None*, *status=**None*, *using=**None*)
request,固定参数。
通俗的讲就是把context的内容, 加载进templates中定义的文件, 并通过浏览器渲染呈现.