django使用总结

本文详细介绍了使用Django框架进行项目开发的全过程,从需求分析到功能实现,涵盖HTML基础、页面美化、模板制作、数据库操作、分页、用户注册、文章创建、富文本编辑、校验器使用、CBV与FBV的区别、时间处理、GET/POST/CSRF概念、URL管理、jQuery与JSON介绍等多个方面,深入浅出地展示了Django项目开发的各个环节。
摘要由CSDN通过智能技术生成

1. 对于任一django项目,拿到功能需求时都要思考的问题

1)去数据库里存什么
2)制作什么样的页面
3) 定义什么样的URL
4)页面与数据库之间的信息交换方式
5)时间如何考虑
6)数据库中方法被调用时显示方式
7)在Admin后台中的显示

2. HTML入门

2.1 文字类:h1~h6,p,a,label,span

<h1>一级标题</h1>
<h2>二级标题</h2>
<h3>三级标题</h3>
<h4>四级标题</h4>
<h5>五级标题</h5>
<h6>六级标题</h6>
<span></span>
<label></label>
<p></p>
<a href=""></a>

对于div,span,label的区别,可参阅:

http://www.cnblogs.com/cmslby/p/5945059.html

简单来说,div是框架,可以包括span,span是组合文档的元素,label主要用来绑定表单元素.

2.2 组件类:table,input,form,button,textarea

<table>
    <thead>
        <th></th>
        <th></th>
        <th></th>
    </thead>
    <tbody>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </tbody>
</table>
<form>
    <label></label>
    <input type='text' />
    <br />
    <select>
        <option></option>
        <option></option>
    </select>
    <textarea rows='10',cols='30'></textarea>
    <button></button>
</form>

2.3 布局类:div,br

<div id='outer'>
    <div id='inner'>
        <input type='text'>
    </div>
    <div id='inner2'>
        <button></button>
    </div>
</div>

3.页面美化

3.1 CSS
CSS代码以三种方式代入进html文件中
方式1:特指特定的一个节点
方式2:选取一类节点
方式3:节点类型限制
方式4:层级限制
方式5:并集选取
3.2 bootstrap
步骤1:前往bootstrap官网下载文件,找到bootsrap.min.css文件并放入至django中的static文件夹下;
步骤2:在settings.py中注册静态文件路径

STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR,"static"),) #BASE_DIR,项目所在目录

步骤3:在template模板中写入

<link rel="stylesheet" href="/static/bootstrap.min.css"/>

步骤4:前往bootstrap官网查看中意的样式然后拷贝进代码中并匹配自己的代码即可.

4.页面布局

4.1 页面布局的概念
页面中先定义行(row),然后定义列(colum);
一行分为12份
xs:小屏幕,md:中屏幕,

5.基础模板的制作

基础模板类似于基本页面,代码为:

<div class="container">
    # code
    {% block content %}
    {% endblock %}
    # code
</div>

子模板代码为:

{% extends 'base.html' %}
{% block content %}
# code
{% endblock %}

6. 数据存入数据库

6.1 示例代码

from django.contrib.auth.models import User
from django.db import models
from blocks.models import Block
import pytz

BEIJING_TZ = pytz.timezone('Asia/Shanghai')

class Article(models.Model):
    owner = models.ForeignKey(User, verbose_name='作者')
    block = models.ForeignKey(Block, verbose_name='版块ID')
    title = models.CharField('模块名称', max_length=100)
    content = models.CharField('模块描述', max_length=400000)
    status = models.IntegerField('状态', choices=((0, '正常'), (1, '删除'),(10, '精华')))

    create_timestamp = models.DateTimeField('创建时间', auto_now_add=True)
    last_update_timestamp = models.DateTimeField('修改时间', auto_now=True)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = '文章'

6.2 数据库类的继承
从django.db中引入models,后面每一张数据表都会继承models
6.3 数据库中的数据类型
数据库中有如下类型:
1) CharField,字符类型
最常用的一种类型,存储字符串数据。
2) IntegerField,数字类型
存储数字,也可以如上图代码,存储类似与selectbox的内容
3) DateTimeField,时间类型
存储时间,其中在属性中设置auto_now_add=True 一般代表文章的创建时间,此时间不会变化,auto_now=True一般代表文章的最后更新时间,此时间会随着数据库被修改而变化。
6.4 数据库中的外键
数据库中的外键相当于数据库中每一张表的联系,比如文章的数据库需要连接到版块信息中,常用的外键如下:
1) ForeignKey,外键
代表此表与另外一张表建立了外键的联系,ForeignKey内部存储的实际上是int类型,即另外一张表的id.
2) OnetooneField:一对一关系
3) ManytoManyField:多对多关系
4) OnetoManyField:一对多关系

7. 版块应用的创建

7.1 建立版块application

1) 在terminal中进入manage.py所在目录下;
2) 利用python manage.py startapp +app名称(block)建立block这个app;

7.2 在settings.py中注册这个app
注意:后续章节会对app进行汉化,因此注册名称会发生变化。

INSTALLED_APPS = [
    # ...
    'blocks.apps.BlocksConfig',
    # ...
]

7.3 在models.py中建立block
7.3.1 创建版块数据表前的思考

  • 设想数据结构:需要版块名称,版块描述,版块所属管理员,版块状态;
  • 必要的补充信息:被调用时返回的名称,在admin后台的汉化,时间的引入(此表不需要),外键的引用(此表不需要);

7.3.2 代码分解

from django.db import models


class Block(models.Model):
    name = models.CharField('模块名称', max_length=100)
    desc = models.CharField('模块描述', max_length=100)
    manager_name = models.CharField('模块管理员名称', max_length=100)
    status = models.IntegerField('状态', choices=((0, '正常'), (1, '删除')))

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '版块'
        verbose_name_plural = '版块'
  • 导入django.db.models
  • 建立数据表Block,继承models.Model
  • 按照设想的数据结构,建立:
    • 版块名称name(CharField类型,中文名称,最大长度);
    • 版块描述desc(CharField,中文名称,最大长度);
    • 管理员名称manager_name(CharField,中文名称,最大长度);
    • 版块状态status(InterField,中文名称,选择信息)
  • 被调用时的名称str:版块名称name
  • 在admin后台显示:verbose_name和verbose_name_plural都是“版块”

7.3.3 后台数据库中的显示

数据库会建立一张blocks_block的数据表,其中blocks为app名称,models中建立的表名,数据库会自动生成一列id列,此列一般被ForeignKey引用。

7.4 数据表在views中的引用
7.4.1 在views中导入数据表

from blocks.models import Block

7.4.2 定义函数及调用数据库数据,将数据传递至template

def index(request):
    block_infos = Block.objects.all().filter(status=0).order_by('-id')
    if request.user.is_authenticated():
        msg_cnt = Usermessage.objects.filter(status=0, owner=request.user).count()
    else:
        msg_cnt = 0
    return render(request, "index.html",{
  'blocks':block_infos, 'msg_cnt': msg_cnt})

7.5 数据表在templates中的显示
在页面中使用for循环的语法是{% for b in blocks%};
通过b.id ,b.name及{ { }}语法调用blocks表中的数据;

    <div class="col-xs-12 col-md-10">
        {% for b in blocks %}
            <div class="panel panel-default">
                <div class="panel-heading">
                    <a href="/article/list/{
   { b.id }}" style="font-size: 15px">{
   { b.name }}</a>
                    <span class="pull-right">{
   { b.manager_name }}</span>
                </div>
                <div class="panel-body">{
   { b.desc }}</div>
            </div>
        {% endfor %}
    </div>

7.6 页面的显示效果
这里写图片描述

- 8.文章列表的创建

8.1 创建前的思考

  • 去数据库里什么:只是作为各版块中每一篇文章的显示功能,不涉及具体数据库操作;

  • 定义一个什么样的页面:包含导航功能,显示目前所处路径,包含一个table,显示文章标题,文章内容概要,文章作者,创建时间,最后修改时间

  • 页面切换:版块概要页面文章列表页面文章详情页面或创建文章页面

  • 时间管理:不涉及时间的管理

  • 汉化功能:不涉及汉化功能;

  • 其他功能:在文章太多的情况下,分页功能;

8.2 编写文章列表views
8.2.1 引入相关数据库

  • 版块数据表Block
from blocks.models import Block
  • 文章数据表
from .models import Article

8.2.2 编写views函数

def article_list(request, block_id):
    block_id = int(block_id)
    blocks = Block.objects.get(id=block_id)
    page_no = int(request.GET.get('page_no','1'))
    all_articles = Article.objects.filter(block=blocks,status=0).order_by('-id')
    page_articles,pagination_data = paginate_queryset(all_articles, page_no)
    return render(request, 'article_list.html', {
  'blocks':blocks,
                                                 'articles':page_articles,
                                                 'pagination_data': pagination_data})
  • 从网页上获取当前所属版块id(block_id=int(block_id))
  • 根据版块id获取Block数据表中数据(blocks=Block.objects.get(id=block_id)
  • 获取文章:满足状态正常(status=0)且属于当前版块(block=blocks)的文章(all_artilces=Arcitle.objects.filter(block=blocks,status=0).order_by(‘-id’))
  • 将文章进行分页(分页的实现一节)
  • 返回模板,代入版块数据,文章分页及文章数据

8.2.3 编写文章列表template
8.2.3.1 文章列表导航功能的模板

    <ol class="breadcrumb">
        <li><a href="/">主页</a></li>
        <li class="active">{
   { blocks.name }}</li>
    </ol>

9.2.3.2 “创建文章”按钮的制作

    <a href="/article/create/{
   { blocks.id }}" type="button" class="btn btn-primary">发表文章</a>

8.2.3.3 文章列表的显示

    <table class="table table-bordered">
        <thead>
            <tr>
                <th>标题</th>
                <th>作者</th>
                <th>创建时间</th>
                <th>最后更新时间</th>
            </tr>
        </thead>
        <tbody>
            {% for article in articles %}
                <tr>
                    <td><a href="/article/articledetail/{
   { article.id }}">{
   { article.title }}</a></td>
                    <td>{
   { article.content }}</td>
                    <td>{
   { article.create_timestamp|date:'Y-m-d P' }}</td>
                    <td>{
   { article.last_update_timestamp|date:'Y-m-d P' }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
  • 使用for语句,显示所有文章;
  • 在文章标题设置连接,当点击文章标题,可以进入文章详情页面;
  • 时间的格式化处理,将数据库中的时间以特定格式显示出来(|date:’Y-m-d P’);

8.2.3.4 分页功能的引入

    {% include 'component/paginator.html' %}

详细讲解见“分页的实现”一节
8.3 文章列表页面的显示效果
这里写图片描述

9. 分页的实现

9.1 分页的本质
获取所有文章,将所有文章按照指定数量进行分隔,当页面调取哪一块数据,分页器返回相应数据。
这里写图片描述
9.2 django提供的分页工具
Django分页工具:django.core.paginator.Paginator

from django.core.paginator import Paginator
all_articles = Articles.objects.all().filter(status=0).order_by("-id")
p = Paginator(all_articles,ARTICLE_COUNT_1PAGE)
page = p.page(page_no)
artilces_objs = page.object_list

9.3 分页功能的页面分解
这里写图片描述
分页总共涉及到7个变量,详见下表:
这里写图片描述

10.4 分页功能代码编写

from django.core.paginator import Paginator


def paginate_queryset(objs, page_no, cnt_per_page=5, half_show_length=5):
    p = Paginator(objs, cnt_per_page)   #分页功能的实例化
    if page_no > p.num_pages:   #判断页数是否超过最大页数
        page_no = p.num_pages
    if page_no <= 0:    #判断页数是否小于最小页数
        page_no = 1
    page_links = [i for i in range(page_no - half_show_length, page_no + half_show_length + 1)
                  if i > 0 and i <= p.num_pages]
    page = p.page(page_no)
    previous_link = page_links[0] - 1
    next_link = page_links[-1] + 1
    pagination_data = {
  'has_previous': previous_link>0, #有前页在views中做计算
                       'has_next': next_link <= p.num_pages,    #有后页在views中做计算
                       'previous_link': previous_link,
                       'next_link': next_link,
                       'page_cnt': p.num_pages,
                       'current_no': page_no,
                       'page_links': page_links}
    return (page.object_list, pagination_data)

1) 不仅在文章列表用到分页功能,后续评论功能也会用到分页,因此将分页功能提取可复用的代码,因此新建paginator.py文件。
2) 导入django分页器from django.core.paginator import Paginator
3) 定义分页函数,参数包含objs(文章的列表数据),page_no(当前页面),count_per_page(每页的文章数量),half_show_length(页面上显示的页码范围);
4) 在10.3中讲到分页页面总共有7个变量,这7个变量都可以通过2个变量(count_per_page,half_show_length)来进行计算
这里写图片描述

5) 程序返回值为当前页的所有数据(列表格式),打包的页面数据(是否有前一页(has_previous),是否有后一页(has_next),前一页(previous_link),后一页(next_link),页数总计(page_cnt),当前页(current_no),页数列表(page_links))
9.5 分页的模板

    <nav aria-label="Page navigation">
        <ul class="pagination">
            {% if pagination_data.has_previous  %}  {# 判断是否有前一页 #}
                <li ><a aria-hidden="true" href="?page_no=1">首页</a></li>    {# 首页按钮 #}
                <li >   {# 前一页标志及链接 #}
                    <a aria-hidden="true" href="?page_no={
   { pagination_data.previous_link }}" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span></a>
                </li>
            {% endif %}
            {% for page in pagination_data.page_links %}
                {% ifequal page pagination_data.current_no %}   {# 判断页面与当前页面是否一致 #}
                    <li class="active"><a href="?page_no={
   { page }}">{
   { page }}</a></li>
                {% else %}
                    <li><a href="?page_no={
   { page }}">{
   { page }}</a></li>
                {% endifequal %}
            {% endfor %}
            {% if pagination_data.has_next %}   {# 判断是否有后一页 #}
                <li>    {# 后一页标志及链接 #}
                  <a aria-hidden="true" href="?page_no={
   { pagination_data.next_link }}" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span></a>
                </li>
                <li><a aria-hidden="true" href="?page_no={
   { pagination_data.page_cnt }}">尾页</a></li>    {# 尾页按钮 #}
            {% endif %}
      </ul>
    </nav>

分页模板主要分为三部分,第一是是否有前一页的判断及显示前一页,第二是显示页面范围并active当前页,第三是是否有后一页的判断。
分页的模板可以去bootstrap网站寻找,如下:
这里写图片描述
9.6 分页功能的应用
分页功能在文章列表页面得到了应用,下面是实际代码。
9.6.1 分页功能的引入

from utils.paginator import paginate_queryset

9.6.2 功能的实现

def article_list(request, block_id):
    block_id = int(block_id)
    blocks = Block.objects.get(id=block_id)
    page_no = int(request.GET.get('page_no','1'))
    all_articles = Article.objects.filter(block=blocks,status=0).order_by('-id')
    page_articles,pagination_data = paginate_queryset(all_articles, page_no)
    return render(request, 'article_list.html', {
  'blocks':blocks,
                                                 'articles':page_articles,
                                                 'pagination_data': pagination_data})

要点:先从template中获取当前页面(page_no)及从models中获取所有文章(all_articles),然后将这两个数据传递至分页函数paginate_queryset中(每页显示文章数量count_per_page及页面上显示的页码范围half_show_length都已设定默认值(count_per_page=5,half_show_length=5)),由于函数返回了两个变量,一个是每页显示的文章(page.queryset),另外一个是分页相关数据(pagination_data),因此设置两个变量进行接收,将这两个变量直接传回至template中
9.6.3 功能的页面

    <table class="table table-bordered">
        <thead>
            <tr>
                <th>标题</th>
                <th>作者</th>
                <th>创建时间</th>
                <th>最后更新时间</th>
            </tr>
        </thead>
        <tbody>
            {% for article in articles %}
                <tr>
                    <td><a href="/article/articledetail/{
   { article.id }}">{
   { article.title }}</a></td>
                    <td>{
   { article.content }}</td>
                    <td>{
   { article.create_timestamp|date:'Y-m-d P' }}</td>
                    <td>{
   { article.last_update_timestamp|date:'Y-m-d P' }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    {% include 'component/paginator.html' %}

利用for函数遍历所有文章,利用table样式进行显示;
引入paginator.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值