Django 2的安装
首先确定安装了 Python 3.4及以上版本,亦可使用 virtualenv 或 virtualenvwrapper
1 2 3 4 5 6 7 |
pip install Django==2.0.5 django-admin startproject mysite cd mysite python manage.py migrate python manage.py runserver |
访问http://127.0.0.1:8000/可得到如下页面:
1 2 |
# 可指定端口和配置文件 python manage.py runserver 127.0.0.1:8001 --settings=mysite.settings |
博客项目开发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
python manage.py startapp blog # models.py from django.db import models from django.utils import timezone from django.contrib.auth.models import User 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') author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts') body = models.TextField() 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') class Meta: ordering = ('-publish',) def __str__(self): return self.title # settings.py INSTALLED_APPS = [ ... 'blog.apps.BlogConfig' ] python manage.py makemigrations blog # 查看 SQL python manage.py sqlmigrate blog 0001 # 创建数据库 python manage.py migrate # Django 后台 # 创建用户 python manage.py createsuperuser # 运行 python manage.py runserver # 登录入口 http://127.0.0.1:8000/admin/ # admin.py from .models import Post admin.site.register(Post) |
1 2 3 4 5 6 7 8 9 10 |
# 优化后台页面 @admin.register(Post) 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',)} raw_id_fields = ('author',) date_hierarchy = 'publish' ordering = ('status', 'publish') |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# Python Shell python manage.py shell # 获取用户并保存一篇文章 >>> from django.contrib.auth.models import User >>> from blog.models import Post >>> user = User.objects.get(username='alan') >>> post = Post(title='Another Post', slug='another-post', body='Post body',author=user) >>> post.save() # 也可使用Post.objects.create() # 其它用法: Post.objects.all() Post.objects.filter(publish__year=2019, author__username='alan') Post.objects.order_by('-title') post = Post.objects.get(id=1) post.delete() # 设置模型管理器,默认为 objects # models.py class PublishedManager(models.Manager): def get_queryset(self): return super(PublishedManager, self).get_queryset().filter(status='published') class Post(models.Model): ... objects = models.Manager() published = PublishedManager() # 测试 python manage.py shell Post.published.filter(title__startswith='D') # views.py from django.shortcuts import render, get_object_or_404 from .models import Post def post_list(request): posts = Post.published.all() return render(request, 'blog/post/list.html', {'posts': posts}) def post_detail(request, year, month, day, post): post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month, publish__day=day) return render(request, 'blog/post/detail.html', {'post': post}) # 创建 urls.py,用于将 url 与 view 进行对应 from django.urls import path from . import views app_name = 'blog' urlpatterns = [ # post views path('', views.post_list, name='post_list'), path('<int:year>/<int:month>/<int:day>/<slug:post>/', views.post_detail, name='post_detail') ] # mysite/urls.py 包含 blog 应用的 url 设置 from django.urls import path, include urlpatterns = [ ... path('blog/', include('blog.urls', namespace='blog')) ] # models.py 模型 Canonical URL from django.urls import reverse class Post(models.Model): ... def get_absolute_url(self): return reverse('blog:post_detail', args=[self.publish.year, self.publish.month, self.publish.day, self.slug ]) # 创建模板文件(blog 目录下),当前 blog目录下结构如下: blog/ ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── static │ └── css │ └── blog.css ├── templates │ └── blog │ ├── base.html │ └── post │ ├── detail.html │ └── list.html ├── tests.py ├── urls.py └── views.py |
添加翻页功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# views.py from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def post_list(request): '''Test Books are active by default''' object_list = Post.published.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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# views.py from django.views.generic import ListView class PostListView(ListView): queryset = Post.published.all() context_object_name = 'posts' paginate_by = 3 template_name = 'blog/post/list.html' # urls.py urlpatterns = [ path('', views.PostListView.as_view(), name='post_list'), path('<int:year>/<int:month>/<int:day>/<slug:post>/', views.post_detail, name='post_detail'), ] |
项目代码参见 GitHub 仓库