zoukankan      html  css  js  c++  java
  • Django基础和基本使用

    Django基础

    Django是Python下的一款著名的Web框架 

     

    框架

    任何语言进入到高级部分时,会有认证、session、http、连接数据库等等功能操作,没有框架时需要自己实现

     框架 是整个或部分系统的可重用设计,表现为一组抽象组件及组件实例间交互的方法;

     

    Django优点

    • 自带轮子众多,方便快速开发 如Auth,Cache,模板等

    • 天生的MVC设计模块

    • 实用的后台管理

    • 自带ORM,Template,Form,Auth核心组件

    • 简洁的url设计

    • 周边插件丰富

    Django缺点

    • 同步阻塞

    和其他Web框架对比

    • Flask:小而精

    • Tornado:基于事件,异步

    Django设计哲学

    • 大而全

    • 快速开发

     

    Django历史

    最初开发者:Adrian和Simon

    开发背景:World Online维护几个新闻站点,要求快速发布新闻,快速建立其他新闻站点(快速开发,数据驱动)

    开源时间:2005年夏天 World Online小组宣布开源

    官方网站:https://www.djangoproject.com

    文档地址:https://docs.djangoproject.com/en/1.11/

     

    Django安装

    使用版本 Django 1.11  Python3.5.2

    pip  install  -i  https://pypi.doubanio.com/simple/  --trusted-host pypi.doubanio.com django
    python -c "import django; print(django.get_version())"

    需求:web页面要求列出最新10本书

    Django Model - models.py

    用一个Python类来描述数据表,我们称之为模型(model)

    运用这个类,你可以通过简单的Python代码来创建、检索、更新、删除数据库中的记录而无需写一条又一条的SQL语句

    这就是传说中的ORM(Object Relation Mapping)  

    # 数据

    from django.db import models
    
    class Book(models.Model):
        name = models.CharField(max_length=50)
        pub_date = models.DateField()

    Django View - view.py

    View 包含了项目的业务逻辑,我们称之为视图,也是我们开发过程中主要编写的内容

    # 算法

    from django.shortcuts import render
    from models import Book
    
    def latest_books(request):
       book_list = Book.objects.order_by('-pub_date')[:10]
       return render(request, 'latest_books.html', {'book_list': book_list})

    Django UrlConf - urls.py

    指出了什么样的URL调用什么样的视图,如 /latest/  调用  latest_books()这个函数

    如果你的域名是 example.com,任何人浏览 http://example.com/latest/ 将会调用latest_books()这个函数的返回结果给用户

    # 路径

    from django.conf.urls import url
    import views
    
    urlpatterns = [
        url(r'^latest/$', views.latest_books),
    ]

    Django Template

    简单来说就是html模板,它描述了项目的界面结构。模板引擎也内置了一些tag

    #  前端展示

    <ul>
    {% for book in book_list%}
        <li>{{ book.name }}</li>
    {% endfor %}
    </ul>

    基本相应流程

     

    Django基本使用

     

    需求:

    •  查看所有问题

    • 可以让用户投票

    • 可以查看投票结果

    一   项目 Project

    1. 新建项目

    django-admin startproject mysite

    2. 运行项目

    python manage.py runserver 0.0.0.0:8000
    • 启动的是django内置的webserver,仅用于开发测试

    • 更改py文件后server会自动reload

    3. Django项目目录结构

    mysite
    |--manage.py  # 管理工具:运行项目、迁移数据
    |--mysite     # 项目配置信息目录
    |--urls       # 项目urls入口,分发
    |--wsgi       # wsgi部署

    4.  Hello World实现

    from django.conf.urls import url
    from django.contrib import admin
    from django.http import HttpResponse
    
    
    def index(request):
        return HttpResponse('This is index page')
    
    
    def hello(request):
        return HttpResponse('Hello World')
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^$', index),
        url(r'^hello/$', hello),
    ]
    • urlpatterns

    • url函数(regex, view, kwargs=None, name=None)

    • 注意是view function object而不是执行函数

    • 前面的/和 和后面/

    • 项目入口 urls

    • request view第一个参数永远是request(不探讨CBV)

    • HttpResponse (view永远返回一个Response对象,显示或隐式)

    二   Django App

    1. 与project的关系和区别

    • project 公司  app 公司team;project用于配置 app用于实现

    • app中才能使用model

    • app设计是可以插拔的,app不一定在project目录中,app之间尽量不要耦合太多

    2. 新建app

    python manage.py startapp polls

    3.  App 目录结构

    polls          # app目录
    |--admin.py    # 内置后台管理配置  
    |--apps        # app配置 
    |--migrations  # ORM版本控制,迁移的各类数据
    |--models.py   # 数据模型定义,只有app才有
    |--test.py     # 单元测试
    |--views.py    # app的views函数

    4. 项目关联app,配置project settings 导入app

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'polls',
    ]

    5. 编写app view

    from django.shortcuts import render, HttpResponse, redirect
    
    def index(request):
        return HttpResponse('This is index page')
    
    def hello(request):
        return HttpResponse('Hello World')

    6. 编写urls

    app urls 注册到 项目urls中,各app之间项目独立,分发思想

    from django.conf.urls import url, include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^polls/', include('polls.urls'))
    ]

    polls/urls.py 默认是不存在的,需要创建

    from django.conf.urls import url
    from polls import views
    
    urlpatterns = [
        url(r'^$', views.index),
        url(r'^hello/', views.hello)
    ]

    三   Django 使用数据库

    支持的数据库

    • SQLite

    • MySQL(MariaDB)

    • PostgreSQL

    • Oracle

    设置使用数据库

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql', #数据库引擎
            'NAME': 'db_name',                    #数据库名
            'USER': 'root',                       #用户名
            'PASSWORD': 'root',                   #密码
            'HOST': 'localhost',                  #数据库主机,默认为localhost
            'PORT': '3306',                       #数据库端口,MySQL默认为3306
            'OPTIONS': {
                'autocommit': True,
            },
        }
    }

    Python 3.5+不支持MySQLdb驱动,可选方案:

    • pymysql,python写的,速度慢,在站点__init__.py文件中,添加代码 import pymysql; pymysql.install_as_MySQLdb() 

    • mysqlclient fork的 mysqldb支持python3.3+速度快,官方推荐 https://pypi.python.org/pypi/mysqlclient/

    • 在对db没有要求的情况下,postgre或许是个更好的选择  https://docs.djangoproject.com/en/1.11/ref/databases/

     

    编写App models

    ORM用python方法、数据结构访问db,不用写SQL

    可以兼容不同数据库

    # polls/models.py
    from django.db import models
    
    class Question(models.Model):
        question_text = models.CharField(max_length=200)
        pub_date = models.DateTimeField('date published')
    
    class Choice(models.Model):
        question = models.ForeignKey('Question', on_delete=models.CASCADE)
        choice_text = models.CharField(max_length=200)
        votes = models.IntegerField(default=0)

    说明

    • models.Model   继承父类的属性和方法,继承优势

    • CharField         varchar()

    • DateTimeField datetime 

    • IntegerField     int

    • ForeignKey      一对多关系   question_id

    • on_delete       是否级联删除

    • max_length

    • default

    • blank

    • null 

     

    Models Migrate

    编写完数据模型需要应用到数据库,Django为了能跟踪表结构的变化,增加了migrations版本控制功能

    如果没有该功能,每次表结构发生变化,就需要重新生成表结构,重新导入数据

     

    python manage.py makemigrations

    python manage.py migrate

    python manage.py shell

    • 一个class代表一张表(多对多会产生额外一张关系表)

    • 默认主键为id,也可以自定义主键

    • 表名默认为 app名称_类名.lower(),可以重写

     

    Models增删改查

    增:

    q = models.Question(**kwargs)
    q.save()
    
    q = models.Question.objects.create(**kwargs)

    查:

    models.Question.objects.all()    # 查询所有
    models.Question.objects.filter(question_text="What's up?")
    models.Question.objects.get(id=1)

    改:

    q = models.Question.objects.get(id=1)
    q.question_text = "some text"
    q.save()
    
    models.Question.objects.filter(id=1).update(question_text="Why?")

    删:

    q = models.Question.objects.get(id=1)
    q.delete()
    
    models.Question.objects.get(id=1).delete()
    models.Question.objects.all().delete()

     说明:

    • def __unicode__(self):pass

    • __str__ = __unicode__

    • timezone带来的问题

     

    View中使用Model

    需求列出最近5个问题

    def index(request):
        latest_question_list = models.Question.objects.order_by('-pub_date')[:5]
        output = ','.join([q.question_text for q in latest_question_list ])
        return HttpResponse(output)

    完成详情,提供投票,显示投票结果

    # polls/views.py
    def detail(request, question_id):
        return HttpResponse('You are looking at question {}'.format(question_id))
    
    def results(request, question_id):
        return HttpResponse('You are looking at results of question {}'.format(question_id))
    
    def vote(request, question_id):
        return HttpResponse('You are voting on question {}'.format(question_id))
    
    # polls/urls.py
    urlpatterns = [
        url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
        url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
        url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
    ]

    说明

    • (?P<question_id>[0-9]+)---->关键字参数传入views函数中;对应()位置参数形式传入views函数中

    •  detail(request, question_id)

    • args, kwargs 总是 字符串

     

    四   模板Template

    Django内置了自己的模板引擎,和jinja很像,使用简单

    >>> from django.template import Template, Context
    >>> t = Template("My name is {{ name }}")
    >>> c = Context({"name":"Jonathan"})
    >>> t.render(c)

    模板使用变量,小数点新式

    • 字典

    • 属性

    • 方法,无参数 

    • 列表/元组,list1.0

     

    模板引擎还支持过滤器和循环判断

    for循环

    {% for person in person_list%}
    <li>{{ person.name }}</li>
    {% endfor%}

    if判断

    {% if max > 10%}
    <li>最大值 {{ max }}</li>
    {% else %}
    <li>最大值10</li>
    {% endif%}

    过滤器,本质函数

    {{ now | date:"F j,Y"}}
    {{ name | length}}

    View中使用模板

    Django默认会去app/templates下寻找模板,默认会去app/static中寻找静态文件(css, js, jpg)

    模板+上下文--->渲染--->HTML文档

    version 1:

    def index(request):
        latest_question_list = models.Question.objects.order_by('-pub_date')[:5]
        template = Template("""
        <img src="/static/django.png">
        {% if latest_question_list %}
        <ul>
        {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
        {% endfor %}
        </ul>
        {% endif%}
        """)
        context = Context({'latest_question_list':latest_question_list})
        return HttpResponse(template.render(context))

     version 2:

    # templates/polls/index.html
    < img src = "/static/django.png" >
    { % if latest_question_list %}
    < ul >
    { % for question in latest_question_list %}
    < li > < a href = "/polls/{{ question.id }}/" > {{question.question_text}} < / a > < / li >
    { % endfor %}
    < / ul >
    { % endif %}
    
    # polls/views.py
    from django.template import loader
    def index(request):
        latest_question_list = models.Question.objects.order_by('-pub_date')[:5]
        template = loader.get_template('polls/index.html')
        context = Context({'latest_question_list':latest_question_list})
        return HttpResponse(template.render(context))

    version 3:

    from django.shortcuts import render
    
    def index(request):
        latest_question_list = models.Question.objects.order_by('-pub_date')[:5]
        context = Context({'latest_question_list':latest_question_list})
        return render(request, 'polls/index.html', context)

    设置公用 templates和static

    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',
                ],
            },
        },
    ]
    
    STATIC_URL = '/static/'
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),
    )

    去掉url和static硬编码

    if、 for、 url 模板默认tag,static 不是,需要{% load static %}

    {% load static %}
    
    <img src="{% static 'django.png' %}">
     {% if latest_question_list %}
     <ul>
     {% for question in latest_question_list %}
     <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
     {% endfor %}
     </ul>
    {% endif %}

    url 反解析

    正解析:url -> view

    反解析:view name -> url

    说明:

    reverse

    reverse_lazy 

    url命名空间

    app namespace

    定义方法一

    # polls/urls.py
    
    app_name = 'polls'

    定义方法二

    # mysite/urls.py
    
    url(r'^polls/', include('polls.urls', app_name='polls')

    instance namespace

    定义

    # mysite/urls.py
    
    url(r'^polls/', include('polls.urls', namespace='polls')

    测试

    或者

    reverse('polls:detail', args(1,))

     

    通常使用app namespace,如果app有多个include,api_urls和view_urls则使用instance namespace

     

    五    form 处理

    1.  vote页面

    # polls/detail.html
    
    <h1>{{ question.question_text }}</h1>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    
    <form action="{% url 'polls:vote' question.id %}" method="post">
    {% csrf_token %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}"/>
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br/>
    {% endfor %}
    <input type="submit" value="Vote"/>
    </form>
    
    # polls/view.py
    
    from django.shortcuts import render, get_object_or_404, reverse
    from django.http import HttpResponseRedirect, HttpResponse
    from polls import models
    
    def vote(request, question_id):
        question = get_object_or_404(models.Question, pk=question_id)
    
        if request.method == 'POST':
            choice_id = request.POST.get('choice', 0)
            try:
                selected_choice = question.choice_set.get(pk=choice_id)
            except models.Choice.DoesNotExist:
                return render(request, 'polls/detail.html',{
                    'question': question,
                    'error_message': "没有选择选项"
                })
            else:
                selected_choice.votes += 1
                selected_choice.save()
                return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
    
        elif request.method == 'GET':
            return render(request, 'polls/detail.html',{
                'question': question,
                'error_message': None
            })

    说明:

    request.POST 取用户form表单提交的数据;兼容request.GET

    csrf_token  每个表单生成一个标识值,中间件验证

    request.FILES  取文件

    request.GET

    models.Choice.DoesNotExist  继承了models.Model;或导入DoesNotExist类

    HttpResponseRedirect   快捷键 redirect

    get_object_or_404

    get_list_or_404

    request

      MEAT, HTTP_REFERER,  HTTP_USER_AGENT, REMOTE_ADDR

      schema, method, COOKIES, FILES

      path, get_host, get_full_path, is_secure

    2.  results 页面

    # polls/views.py
    
    from django.shortcuts import render, get_object_or_404
    def results(request, question_id):
        question = get_object_or_404(models.Question, pk=question_id)
        return render(request, 'polls/results.html',{'question': question})
    
    # polls/results.html
    <h1>{{ question.question_text }}</h1>
    <ul>
        {% for choice in question.choice_set.all %}
            <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes| pluralize }}</li>
        {% endfor %}
    </ul>
    <a href="{% url 'polls:vote' question.id %}">Vote again?</a>
  • 相关阅读:
    Java Web 047: 处理商品列表的查询
    Java Web 047:开发商品列表的模板页
    Java Web 046: 处理登录成功后的跳转
    Java Web 045: 处理登录请求
    Java Web 044: 处理注册响应
    Java Web 043: 处理注册请求
    Java Web 042: 创建UserDao控制user的相关数据库操作
    Java Web 041: 创建数据模型和模拟数据库
    Java Web 03: MVC分层架构 / JavaEE分层架构 (图解)
    Java Web 02: 单例模式
  • 原文地址:https://www.cnblogs.com/jonathan1314/p/7453480.html
Copyright © 2011-2022 走看看