配置及环境:Mac Os + Python3.6.2
1.使用虚拟环境
#快速创建虚拟环境
python -m venv prjvenv
#激活虚拟环境
source prjvenv/bin/activate
2.创建项目
#安装django
pip install django
#创建项目
django-admin startproject myblog
3.django设置
TIME_ZONE='Asia/Shanghai'
4.数据库迁移
python manage.py migrate
5.启动
python manage.py runserver
from django.http import HttpResponse
#最简单视图
def hello(request):
return HttpResponse("Hello world")
#带参数的视图
def hours_ahead(request, offset):
try:
offset = int(offset)
except ValueError:
raise Http404()
dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
html = "In %s hour(s), it will be %s." % (offset, dt)
return HttpResponse(html)
from django.conf.urls import url
from django.contrib import admin
from myblog.views import hello
from mysite.views import hours_ahead
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^hello/$',hello),
url(r'^time/plus/(\d{1,2})/$', hours_ahead),
]
1.模板目录配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['app1/templates','app2/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',
],
},
},
]
如果想在项目根目录中放一些主模板(例如在 mysite/templates 目录中),需要像这样设定 DIRS:
'DIRS': [os.path.join(BASE_DIR, 'templates')],
2.视图函数
from django.shortcuts import render
import datetime
def current_datetime(request):
now = datetime.datetime.now()
return render(request, 'current_datetime.html', {'current_date': now})
3.模板文件
"-//W3C//DTD HTML 4.01//EN">
"en">
{% block title %}{% endblock %}
My helpful timestamp site
{% block content %}{% endblock %}
{% block footer %}
Thanks for visiting my site.
{% endblock %}
1.配置数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
} }
2.创建应用
python manage.py startapp books
3.激活应用
INSTALLED_APPS = (
...
'books',
)
4.创建模型
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __str__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __str__(self):
return self.last_name
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE)
publication_date = models.DateField()
def __str__(self):
return self.title
5.迁移数据库
#括号中的内容可以不需要
python manage.py makemigrations (books)
python manage.py migrate
6.操作数据
方式一:
p1 = Publisher(...)
p1.save()
方式二:
p1 = Publisher.objects.create(...)
方式一:
p.name = 'Apress Publishing'
p.save()
方式二:
Publisher.objects.filter(id=52).update(name='Apress') #推荐
返回查询集合
Publisher.objects.all()
Publisher.objects.filter(name='Apress') #WHERE name = 'Apress';
Publisher.objects.filter(name__contains="press") #WHERE name LIKE '%press%';
返回单个对象
Publisher.objects.get(name="Apress") #不是1个对象就会报异常
try:
p = Publisher.objects.get(name='Apress') #数据库中存在一个数据
except Publisher.DoesNotExist:
print ("Apress isn't in the database yet.") #数据库中没有数据
else:
print ("Apress is in the database.") #有多个数据
方式一:单个删除
p = Publisher.objects.get(name="O'Reilly")
p.delete()
方式二:批量删除
Publisher.objects.filter(country='USA').delete()
Publisher.objects.all().delete()
方式一:使用order_by()
Publisher.objects.order_by("name", "age") #根据姓名和年龄排序,-name/-age实现反向排序
方式二:在模型内定义
class Publisher(models.Model):
...
class Meta:
ordering = ['name']
Publisher.objects.order_by('name')[0:2]
1.创建管理员用户
python manage.py createsuperuser
2.将模型添加到后台管理
from django.contrib import admin
from .models import Publisher, Author, Book
admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)
3.修改模型,使字段在后台输入时变为可选项
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE)
publication_date = models.DateField(blank=True, null=True)
注意:如果想让日期字段(如 DateField、TimeField、DateTimeField)或数值字段(如 IntegerField、DecimalField、FloatField)接受空值,要同时添加 null=True 和 blank=True。
4.通过模型字段的verbose_name值指定后台显示的字段别名
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(blank=True, verbose_name='e-mail')
5.自定义修改后台管理列表
from django.contrib import admin
from .models import Publisher, Author, Book
#自定义Author的后台管理列表
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email') #定义显示字段
search_fields = ('first_name', 'last_name') #添加字段搜索
#自定义Book的后台管理列表
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date') #定义显示字段
list_filter = ('publication_date',) #添加时间过滤器
date_hierarchy = 'publication_date' #另一种日期过滤器
ordering = ('-publication_date',) #排序
fields = ('title', 'authors', 'publisher', 'publication_date') #自定义修改表单
filter_horizontal = ('authors',) #使用选项框(多对多关系时使用)
raw_id_fields = ('publisher',) #通过id选择对应选项
admin.site.register(Publisher)
admin.site.register(Author,AuthorAdmin)
admin.site.register(Book,BookAdmin)
一、原生表单
1.获取request数据应该try或者设置默认值,防止报错
方式一:
def ua_display_good1(request):
try:
ua = request.META['HTTP_USER_AGENT']
except KeyError:
ua = 'unknown'
return HttpResponse("Your browser is %s" % ua)
方式二:
def ua_display_good2(request):
ua = request.META.get('HTTP_USER_AGENT', 'unknown')
return HttpResponse("Your browser is %s" % ua)
2.简单的表单提交及表单实例
get和post指向相同的url,根据 if ‘q’ in request.GET:判断是GET还是POST
#表单页面:myblog/templates/search_form.html
Search
{% if errors %} #提示错误信息
{% for error in errors %}
- {{ error }}
{% endfor %}
{% endif %}
#结果展示页面:myblog/templates/search_results.html
Book Search
You searched for: {{ query }}
{% if books %}
Found {{ books|length }} book{{ books|pluralize }}.
{% for book in books %}
- {{ book.title }}
{% endfor %}
{% else %}
No books matched your search criteria.
{% endif %}
from django.shortcuts import render
from django.http import HttpResponse
def search(request):
errors = []
if 'q' in request.GET: # 如果是post,则存在GET['q']
q = request.GET['q']
if not q:
errors.append('Enter a search term.') # 提交了表单,但是内容为空
elif len(q) > 20: # 提交表单,长度超过限制
errors.append('Please enter at most 20 characters.')
else: # 正常提交数据
books = Book.objects.filter(title__icontains=q)
return render(request, 'search_results.html',
{'books': books, 'query': q})
return render(request, 'search_form.html',{'errors': errors}) #不存在GET['q']说明是GET请求
urlpatterns = [
...
url(r'^search/$',views.search)
]
二、Django表单模型
1.定义表单类
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100) # max_length指定最大长度
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea) # widget参数,指定表现逻辑,此次指定为文本框
def clean_message(self): # 自定义验表单证器
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message
自定义表单验证器:Django 的表单系统会自动查找名称以 clean_ 开头、以字段名结尾的方法。如果存在这样的方法,在验证过 程中调用。这里,clean_message() 方法会在指定字段的默认验证逻辑(这个 CharField 是必填的)执行完毕 后调用。
2.视图函数
from books.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
#提示:如果没有配置邮件服务器,调用 send_mail() 时会抛出 ConnectionRefusedError。
send_mail(
cd['subject'],
cd['message'],
cd.get('email', '[email protected]'),
['[email protected]'],
)
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm(
initial={'subject': 'I love your site!'} # 可以初始值
)
return render(request, 'contact_form.html', {'form': form})
3.表单页面
方式一:使用系统默认表单
Contact us
Contact us
{% if form.errors %}
"color: red;">
Please correct the error{{ form.errors|pluralize }} below.
{% endif %}
方式二:自定义表单外观样式
Contact us
Contact us
{% if form.errors %}
"color: red;">
Please correct the error{{ form.errors|pluralize }} below.
{% endif %}
4.路由设置
urlpatterns = [
...
url(r'^contact/$', views.contact),
]