Django笔记

教学视频地址Python Django Web Framework Full Course for Beginnners

创建的model需要在admin.py中注册

1
2
from .models import Product
admin.site.register(Product)

通过python shell添加模型

首先进入django的python shell

1
python manage.py shell

导入模型

1
from products.models import Product

查看已创建的Product对象

1
Product.objects.all()

创建一个新的对象

1
Product.objects.create(title='New product', description="another one", price="19.2", summary="sweet")

创建页面

创建app

1
python manage.py startapp pagess

在views.py中创建函数

1
2
3
4
5
6
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def home_view(*args, **kwargs):
return HttpResponse("<h1>Hello</h1>")

在mysite中的urls.py中加入path

1
2
3
4
5
6
7
8
9
from django.contrib import admin
from django.urls import path

from pages import views ##注意引入pages中的views

urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home_view, name='home') #注意这里的home_view没有括号的也就是一个纯函数名
]

views中函数的request参数

1
2
3
4
5
def home_view(request, *args, **kwargs):
print(request)
print(request.user)
print(args, kwargs)
return HttpResponse("<h1>Hello</h1>")

我们这边设置request变量, 打印出来是<WSGIRequest: GET '/'>, 一个WSGIRequest,再打印出request.user, 结果是AnonymousUser

模板的使用

1
2
3
def home_view(request, *args, **kwargs):

return render(request, "home.html", {})

第一个参数是request, 第二个是模板的名称, 第三个是需要传入的参数字典

如果需要使用模板,必须在settings.py中设置模板路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},

'DIRS'设置为根目录下的template目录就可以在这个目录下创建模板的html文件了

模板的继承

创建模板html文件

这里我们创建base.html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Coding for Entrepreneurs is doing try django</title>
</head>
<body>
{% block content %}
replace me
{% endblock %}
</body>
</html>

注意,这里的block模块, 在子模板中再次引入可以替换block间的内容

1
2
3
{% block content %}
replace me 这里将会被代替
{% endblock %}

引入模板

这里我们在home.html中继续base.html

1
2
3
4
5
{% extends 'base.html' %}
{% block content %}
<h1> Hello world </h1>
<p>this is a template</p>
{% endblock %}

模板的include

创建需要include的模板, 这里我们创建navbar.html

1
2
3
4
5
6
7
<nav>
<ul>
<li>Brand</li>
<li>Contact</li>
<li>About</li>
</ul>
</nav>>

base.html中include进去

1
{% include 'navbar.html' %}

模板的上下文

首先在views.py中添加上下文参数

1
2
3
4
5
6
7
def about_view(request, *args, **kwargs):
my_context = {
"my_text": "this is about me",
"my_number": 123,
"my_list": [1, 2, 3, 4],
}
return render(request, 'about.html', my_context)

在模板中使用格式化渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% extends 'base.html' %}
{% block content %}
<h1> About page </h1>
<p>this is a template</p>
<p>
{{ my_number }}
{{ my_text }}
</p>
<ul>
{% for item in my_list %}
<li>{{ forloop.counter }}---{{ item }}</li>
{% endfor %}
</ul>
{% endblock %}

filters

Django Template Filters

介绍几个重要的

save

1
2
3
4
5
6
context = {
'Hello': "你好",
"lala": "啦啦啦",
'my_list': [1, 2, 3, 5],
'my_html': '<h1>Hello World</h1>'
}

假设有一段html源代码被传入, 如果直接用调用是不行的,没有被渲染出来

需要

1
{{ my_html|safe}}

需要添加save filter才能诶渲染

app中的template

在app中建立template可以使得这个app成为一个插件,在哪里都可以用

在app中建立template文件夹

这里我们的app是product, 所以在product文件夹下建立template文件夹

在建立的template文件夹中建立一个名称为app名字的文件夹

这里我们建立的是/products/template/products

—products

——-template

————products

—————–product_detail.html


在设置中给’APP_DIRS’赋值为True

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

APP_DIRS决定了Djang是否会去寻找app中的template

如果说根目录下的template和app中的template有相同的路径,那么Django会先去找根目录下的template中的模板

比如

app下的 1

根目录下 2

这样的情况下,在view.py中设置render模板的路径为’/products/product_detail.html’Django会先选择/mysite/template/products/product_detail.html, 而不是/mysite/products/product_detail.html

forms

我们需要用户上传数据,这就需要forms

在app根目录下创建forms.py

1
2
3
4
5
6
7
8
9
10
11
12
from django import forms

from .models import Product

class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = [
'title',
'description',
'price',
]

注意这边的files如果有一个是没有设置defaul、不能是空的,那么用户提交的数据将会不完整, 无法进入数据库,导致错误发生

为表单提交创建新的view

1
2
3
4
5
6
7
8
9
10
11
def product_create_view(request):
form = ProductForm(request.POST or None)
if form.is_valid():
form.save()

# rerender it, to clear the text
form = ProductForm()
context = {
'form': form
}
return render(request, "products/product_create.html", context)

其中

1
2
form.save()
form.ProductForm()

是保存了数据之后刷新表单, 将输入框中的数据清空

创建html模板文件

在app目录下的/template/products中创建product_create.html

1
2
3
4
5
6
7
8
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
{% endblock %}

添加到路由中

1
path('create/', product_create_view, name="product_create"),

创建生的Form

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class RawProductForm(forms.Form):
# overwrite the basic attar
title = forms.CharField(label='MY Label', widget=forms.TextInput(
attrs={
'placeholder':"Your title"
}
))
description = forms.CharField(
required = False,
widget=forms.Textarea(
attrs={

"class":"new-lass two",
"rows":20,
"col":120,
}
)
)
price = forms.DecimalField()

效果将会是
6

Django POST 和 GET

https://docs.djangoproject.com/en/2.2/ref/request-response/

在view.py中定义的函数,第一个参数是request

当有post和get请求时, 返回的request中有GET和POST两种属性

其实他们两个都是QueryDict对象,可以通过request.POST.get() 和request.GET.get()方法获取参数