项目前准备
1.创建env环境,virtualenv --no-site-packages 文件夹名
2.激活virtualenv中的python版本,source 文件夹名/bin/activate
3.在激活状态下,安装django
第一个Blog项目
1. djangoadmin startproject mysite --创建mysite项目
2. cd mysite --切换至项目文件夹
3. python3 manage.py startapp blog --创建blog应用
4. python3 manage.py migrate --数据库创建初始表
5. python3 manage.py runserver 或
python3 manage.py runserver -- settings=mysite.settings --启动测试服务器
在应用文件夹下的models中创建
from django.contrib.auth.models import User # 导入django.扩展.认证.模型中的User
from django.db import models # 导入django.数据库中的models模型
from django.utils import timezone # 导入django.实用工具中的timezone,需要安装pip install pytz
# Create your models here.
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish')
body = models.TextField()
author = models.ForeignKey(User, related_name='blog_posts')
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
objects = models.Manager() # The default manager.
published = PublishedManager() # Our custom manager.自定义管理器
class Meta:
ordering = ('-publish',) # 查询数据库时候将以publish的倒序排序
def __str__(self):
return self.title # str()方法是当前对象默认的可读表现。Django将会在很多地方用到它例如管理站点中。
# ------------ 添加自定义models manager模型管理器-----------------
要放在Post之前
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
# -------------------------------------------------------------
在应用文件夹下admin中注册
from django.contrib import admin
from .models import Post
# Register your models here.
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'author', 'publish',
'status') # 在管理站点中的列表显示
list_filter = ('status', 'created', 'publish', 'author') # 过滤显示
search_fields = ('title', 'body') # 搜索显示
prepopulated_fields = {'slug': ('title',)} # slug自动填充,在填写title的时候,slug会自动填充为title内容
raw_id_fields = ('author',) # 显示成为搜索控件,以id形式
date_hierarchy = 'publish' # 日期层次结构
ordering = ['status', 'publish'] # admin管理界面按列表中的内容排序
admin.site.register(Post, PostAdmin) # 注册models中的模型,PostAdmin为个性化定制
创建与迁移数据表
1.python3 manage.py makemigrations
2.python3 manage.py migrate
部分settings设置
TIME_ZONE = 'Asia/Shanghai'
Django1.9以后language code 'zh-cn'就被丢弃了,使用'zh-hans'代替
使用查询集(QuerySet)
python3 manage.py shell进入shell
from django.contrib.auth.models import User
from blog.models import Post
user = User.objects.get(username='用户名')
post = Post.objects.create(author=user,title='内容',body='内容',slug='内容')
#使用create不需要使用post.save(),直接进行数据库操作
#-----------------------------------------------------------------------------
post = Post(title='Another post', slug='another-post', body='Postbody.', \
author=user)#这样使用必须使用post.save(),否则只保存在内存中,没有插入数据库
post.save()#对数据库执行操作
#更新对象字段
post.title='改变内容'
post.save()
post.delete()#删除对象
-------------------------------------------------------------------------------
使用filter()过滤、exclude()排除、order_by()排序
Post.objects.filter(publish__year=2015)#返回在2015年的对象
#返回2015年且author是'admin'的对象
Post.objects.filter(publish__year=2015, author__username='admin')
或Post.objects.filter(publish__year=2015).filter(author__username='admin')
#返回所有2015年发布的帖子但是这些帖子的题目开头不能是Why
Post.objects.filter(publish__year=2015).exclude(title__startswith='Why')
#返回所有且对title字段升序排序
Post.objects.order_by('title')
#返回所有且对title字段倒序排序
Post.objects.order_by('-title')
查询集(QuerySet)什么时候会执行
只要你喜欢,你可以连接许多的过滤给查询集(QuerySet)而且不会立马在数据库中执行直到这个查询集(QuerySet)被执行。查询集(QuerySet)只有在以下情况中才会执行:
- 在你第一次迭代它们的时候
- 当你对它们的实例进行切片:例如Post.objects.all()[:3]
- 当你对它们进行了打包或缓存
- 当你对它们调用了repr()或len()方法
- 当你明确的对它们调用了list()方法
- 当你在一个声明中测试它,例如bool(), or, and, or if
创建templates(模板文件夹)与static(静态文件夹)
- 默认创建在应用文件夹下,自定义需要在DIRS列表中定义,BASE_DIR是指mysite项目的绝对路径,可以使用完整路径
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],#如果需要自定定义位置,需要在此处列表内加入
'APP_DIRS': True,#默认在app文件夹内
'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',
],
},
},
]
STATIC_URL = '/static/'
# 当运行 python manage.py collectstatic 的时候
# STATIC_ROOT 文件夹 是用来将所有STATICFILES_DIRS中所有文件夹中的文件,以及各app中static中的文件都复制过来
# 把这些文件放到一起是为了用apache等部署的时候更方便
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
# 其它 存放静态文件的文件夹,可以用来存放项目中公用的静态文件,里面不能包含 STATIC_ROOT
# 如果不想用 STATICFILES_DIRS 可以不用,都放在 app 里的 static 中也可以
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "common_static"),
'/path/to/others/static/', # 用不到的时候可以不写这一行
)
# 这个是默认设置,Django 默认会在 STATICFILES_DIRS中的文件夹 和 各app下的static文件夹中找文件
# 注意有先后顺序,找到了就不再继续找了
STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder"
)
编辑视图文件views
from django.shortcuts import render, get_object_or_404 # 从django.快捷工具中导入render,get_object_or_404
from .models import Post # 从模型中导入Post
# Create your views here.
def post_list(request):
posts = Post.objects.all() # 提取实例Post
return render(request, 'blog/post/list.html', {'posts': posts}) # 渲染至list.html,给html文件posts对象
def post_detail(request, year, month, day, post): # year,month,day,post等参数是从urls文件中获取
post = get_object_or_404(Post, slug=post,
status='draft',
publish__year=year,
publish__month=month,
publish__day=day) # 与Post.objects.get()方法相似,get_object_or_404获取不到对象会返回404
return render(request, 'blog/post/detail.html', {'post': post})
为视图添加URL模式
在APP的文件夹下创建urls文件,惯例
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<post>[-\w]+)/$',
views.post_detail,
name='post_detail'),
]
- year:需要四位数
- month:需要两位数。不及两位数,开头带上0,比如 01,02
- day:需要两位数。不及两位数开头带上0
- post:可以由单词和连字符组成
在项目urls文件中(mysite/mysite/urls.py)中导入APP的urls文件
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/', include('blog.urls',
namespace='blog',
app_name='blog')),
]
模型(models)的标准URLs
在models中添加生成url的代码
from django.core.urlresolvers import reverse#从django.核心.解析器中导入reverse
Class Post(models.Model):
# ...
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[self.publish.year,
self.publish.strftime('%m'),
self.publish.strftime('%d'),
self.slug])
我们通过使用strftime()方法来保证个位数的月份和日期需要带上0来构建URL,也就是01,02,03,对象的get_absolute_url方法,会reverse反向的去找urls的blog空间中的post_detail的urls,根据urls会生成一个标准的url(http://127.0.0.1:8000/blog/YEAR/MONTH/DAY),然后url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<post>[-\w]+)/$',views.post_detail,name='post_detail')会处理,然后(?P<year>)会有变量year=VALUE,urls中写的views文件处理,渲染。
html文件,模板标签语言
文档位置(https://docs.djangoproject.com/en/1.8/)
templates/
blog/
base.html
post/
list.html
detail.html
base为基础部分,list.html,detail.html扩展
常用:
{% load staticfiles %}放置顶端,导入静态文件
{% static "css/文件.css" %} 以static文件夹为根,相对路径
{% for post in posts %}
{{post.filed}}
{{post.get_absolute_url}}调用models中的get_absolute_url方法,生成标准url
{% end for %}{% block content %} 在base.html中设定的填充区域,填充内容可写在其他html文件中
{% endblock %}{% extends "blog/base.html" %}继承blog/base.html 模板(template)。然后content区块(blocks)中填充内容。
{{ post.body|truncatewords:30|linebreaks }} truncatewords用来缩短内容限制在一定的字数内,linebreaks用来转换内容中的换行符为HTML的换行符。
{% include "pagination.html" with page=posts %} 导入 templates下pagination.html(相对路径), 且pagination中的变量page=posts
分页 使用django内置的paganitor来完成
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 导入django.核心.分页处理中的分页器,空页,不是整数页
def post_list(request):
object_list = Post.objects.all()
paginator = Paginator(object_list, 3)#每页显示3个对象
page = request.GET.get('page')#获取到页码
try:
posts = paginator.page(page)
except PageNotAnInteger:#如果页码不是一个整数,显示第一页
posts = paginator.page(1)
except EmptyPage:#如果页码是整数但是不存在,显示最大的页
posts = paginator.page(paginator.num_pages)
return render(request, 'blog/post/list.html', {'page': page, 'posts': posts})
以上代码工作流程:
1、打开主页-->127.0.0.1:8000/blog被urls.py中定义的规则捕获-->交由定义的views中的函数处理
2、paginator=Paginator(object_list,3),每页显示3个对象,paginator为分页处理对象:常用方法有:
paginator.count #一共有多少个对象
paginator.num_pages#最大页数
paginator.page(页码)#页码的对象
3、page=request.Get.get('page'),主页没有page参数,get的结果为None,所以page不是一个整数,posts=paginator.page(1)#返回一个Page类对象
Page对象常用方法,详细使用看源码,Page对象使用.paginator方法转回Paginator对象
def has_next(self):
return self.number < self.paginator.num_pages
def has_previous(self):
return self.number > 1
def has_other_pages(self):
return self.has_previous() or self.has_next()
def next_page_number(self):
return self.paginator.validate_number(self.number + 1)
def previous_page_number(self):
return self.paginator.validate_number(self.number - 1)
def start_index(self):
"""
Returns the 1-based index of the first object on this page,
relative to total objects in the paginator.
"""
# Special case, return zero if no items.
if self.paginator.count == 0:
return 0
return (self.paginator.per_page * (self.number - 1)) + 1
def end_index(self):
"""
Returns the 1-based index of the last object on this page,
relative to total objects found (hits).
"""
# Special case for the last page because there can be orphans.
if self.number == self.paginator.num_pages:
return self.paginator.count
return self.number * self.paginator.per_page
4、进行render,显示页面
使用基于类的视图(views)简介
编辑你的blog应用下的views.py文件,如下所示:
from django.views.generic import ListView # 从django.视图.公共 导入ListView
class PostListView(ListView):
queryset = Post.objects.all() # 使用一个特定的查询集(QuerySet)代替取回所有的对象。代替定义一个queryset属性,我们可以指定model = Post然后Django将会构建Post.objects.all() 查询集(QuerySet)给我们。
context_object_name = 'posts' #使用环境变量posts给查询结果。如果我们不指定任意的context_object_name默认的变量将会是object_list。
paginate_by = 3 #对结果进行分页处理每页只显示3个对象。
template_name = 'blog/post/list.html' #使用定制的模板(template)来渲染页面。如果我们不设置默认的模板(template),ListView将会使用blog/post_list.html。
在urls文件中,我们要调用views.PostlistView.as_view()
为了保持分页处理能工作,我们必须将正确的页面对象传递给模板(tempalte)。Django的ListView通过叫做page_obj的变量来传递被选择的页面,所以你必须编辑你的post_list_html模板(template)去包含使用了正确的变量的分页处理,如下所示:
{% include "pagination.html" with page=page_obj %}
学习来源于夜夜月翻译的django by example