Django(一):入门----初步了解各模块及配置

一、Django介绍,一个WEB框架。

Django的优点:

  1.自带轮子众多,方便快速开发,如AUTH,CACHE,模板

  2.天生的MVC设计模式

  3.实用的管理后台

  4.自带ORM,Template,Form,Auth核心组件

  5.简洁的URL设计

  6.周边丰富的插件 

Django的缺点:

  1.比较重,集成了众多轮子

如果自己写插件,可以使用轻量一点的框架,如Flask,Tornado(异步)

 Django组件:

  1.Model(models.py),描述数据表

    使用这个类,可以用python简单的代码来创建、检索、更新、删除数据库中的记录,而无需写原始的SQL语句。DBA完成。

  2.View(views.py),视图

    该文件包含了页面的业务逻辑;其中的函数叫做视图函数。python开发人员完成。

  3.URL(urls.py),路由

    该文件指出了什么样的URL调用什么样的视图。python开发人员完成。

  4.Template(templates目录),HTML模板

    描述了页面是如何设计的。前端人员完成。使用带基本逻辑声明的模板语言,如{%....%}。

一次Django响应流程的具体细节:http://python.jobbole.com/85203/

二、Django基础一

1.新建项目:

django-admin startproject project-name

运行项目:

python manage.py runserver host:port

注意:启动的是django内置的webserver,仅用开发测试;如有文件更新,webserver会自动reload。

目录结构: tree mysite

2.新建app:

python manage.py startapp polls

编辑polls/views.py:

from django.http import HttpResponse
def index(request):
    return HttpResponse("this is polls")

编辑mysite/urls.py:

from django.conf.urls import url
from django.contrib import admin
from ..polls.views import index

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url('^polls/$', index),
]

访问:http://127.0.0.1:8000/polls  ,ok!

3.include,拆分路由:

拆分上面的app的路由。创建并编辑polls/urls.py:

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

编辑mysite/urls.py:

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url('^polls/', include('polls.urls')),
]

4.路由命名,name='...':

urlpatterns = [
    url('^$', views.index, name='index'),
]

5.导入app

编辑app:

# polls/app.py
from django.apps import AppConfig

class PollsConfig(AppConfig):
    name = 'polls'
# mysite/settings.py 
INSTALLED_APPS = [
    'polls.apps.PollsConfig',   #name.apps.classname

6.数据库支持:

# mysite/settings.py 
# 默认使⽤用 sqlite
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
} }
# mysite/settings.pyp,使⽤mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_name',
'USER': 'user',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': 3306,
} }

MySQLdb驱动不支持python3.5,python3.5以上版本使用mysqlclient。或者mariaDB。

7.编写 App models ORM介绍 用python方法、数据结构访问db 可以兼容不同数据库

# 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)

field类型:

CharField 、TextField、DateTimeField、ForeignKey 、on_delete、 max_length、 IntegerField 、default 、blank 、null

所有field类型见 https://docs.djangoproject.com/en/1.9/ref/models/fields

8. Models Migrate:

makemigrations...生成配置文件,sqlmigrate...查看某配置文件对应的数据表结构,migrate...将变更应用到数据库

编写完数据模型需要应用到数据库,django为了能跟踪表结构的变化,增加了migrations版本控制功能,如果没有该功能每次表结构变化,就需要重新生成表结 构,重新导入数据。命令:

$ ls polls/migrations //查看polls的数据文件。如果只有__init__.py,表示没有任何数据库记录
$ python manage.py makemigrations polls //生成数据表的版本控制的文件、记录;如果不指定任何app,将针对项目的所有app
Migrations for 'polls':
0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
$ ls polls/migrations
$ python manage.py sqlmigrate polls 0001_initial //查看指定app的指定版本的数据表结构
$ python manage.py migrate //将ORM变更应用到数据库,如果不指定app,将生成或更新所有app的数据表
$ sqlite3 db.sqlite3 //进入sqlite3数据库或者python manage.py dbshell
sqlite> .tables  //在数据库中,查看数据表 $ python manage.py shell //在shell下,进入python环境。在python环境下,使用ORM对数据表进行操作
>>> from django.utils import timezone
>>> from polls.models import Question, Choice
>>> q = Question(question_text=“What's new?”, pub_date=timezone.now())
>>> q.save()
>>> q.id; q.pk; q.question_text; q.pub_date;

说明:一个class代表一张表,多对多会产生额外一张关系表

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

表名默认为:app名_小写的类名

python manage.py shell:使用python的shell模式,即可以操作数据库或其它python的交互功能

9.models增删改查,使用python方法。

python manage.py shell
from polls.models import Question, Choice

增:

q = Question(**kwargs)  //方式一,save
q.save() 
q = Question.objects.create(**kwargs)  //方式二,create

查:

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

改:

q = Question.objects.get(id=1) # 方式一,save
q.question_text = 'some text' 
q.save()
Question.objects.filter(id=1).update(question_text='Why ?')  方式二,update

删: delete方法

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

10.给models增加方法

import datetime
from django.db import models 
from django.utils import timezone

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    def __str__(self):
        return self.question_text
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)  //或timzone.timedelta(days=1)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)          
    choice_text = models.CharField(max_length=200)    
    votes = models.IntegerField(default=0)
    def __str__(self):
        return self.choice_text

说明:
1. __str__ 和 __unicode__    2. timezone 带来的 datetime aware 和 naive问题
运行查看:

$ python manage.py shell 
>>> from polls.models import Question, Choice 
>>> from django.utils import timeozne 
>>> q = Question.objects.create(question_text="How are you ?", pub_date=timezone.now()) 
>>> q <Question: How are you ?
> >>> q.was_published_recently()  # True
>>> d = timezone.now() - timezone.timedelta(days=3)
>>> q = Question.objects.create(question_text="where?", pub_date=d)
>>> q.was_published_recently() # False

 三、django基础二

1.View中使用Model。示例,需求列出最近5个问题

from .models import Question
from django.http import HttpResponse

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]  //order_by()根据某字段排序;字段前带-,倒序
    output = ','.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

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

#polls/views.py
def detail(request, pk):
    return HttpResponse('your are looking at question: {}'.format(pk))

def results(request, question_id):
    response = "You are looking results of questions: {}".format(question_id)
    return HttpResponse(response)

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

 2.模板template :涉及HTML的部分,前端部分

  Context中的对象必须是字典,格式固定为:  Context({ 'key': value })

  1.渲染模板

django内置了自己的模板引擎,和jinja很像,使用简单。模板template的变量,用两个{{ 变量名 }}引用。

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

注意:小数点变量的后半部分指的可能是:1.字典的key,2.属性,3.方法,4.列表 /元组,并按以上顺序查找,示例:

person = {'name': 'jerry'}  #字典
Template('name is {{person.name}}').render(Context({'person': person}))  # 'name is jerry'

class Person:
     def __init__(self, name):
          self.name = name
person = Person('jerry')   #属性
Template('name is {{person.name}}').render(Context({'person': person}))   # 'name is jerry'

class Person:
     def name(self):
          return 'jerry'
person = Person()   #方法
Template('name is {{person.name}}').render(Context({'person': person}))   # 'name is jerry'

person = ['jerry', 'harry']   #列表/元组
Template('name is {{person.0}}').render(Context({'person': person}))   # 'name is jerry'

2.模板引擎还支持过滤器和循环判断
For循环标签,{% for 条件 %}.....{% endfor %}:

{% for person in person_list %} 
<li> {{ person.name }} </li> 
{% endfor %}
t = Template("""{% for person in person_list %} <li> {{ person.name }}</li> { % endfor %}""")
person_list = [{'name': 'jerry'}, {'name': 'harry'}]
t.render(Context({'person_list': person_list}))

if判断标签,{% if 条件 %}.....{% endif %}:

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

过滤器,{{  ....|...  }}, |前面变量的值传递给后面的变量:

{{ now | date:”F j,Y” }} 
{{ name | length }}
Template('name length is {{ name|length }}').render(Context({'name': 'jerry'}))   #返回'name length is 5'
Template('Today is {{ now|date:"F j,Y"}}').render(Context({'now': now}))   #'Today is June 15,2017'

3.使用模板

django默认会去app_name/templates下寻找模板,这是settings中的默认设置,默认会去app_name/static中寻找静态文件(css, js, jpg) 

version 1 :在views.py中,用模板改写上面的index视图函数:

from django.http import HttpResponse
from django.template import Template, Context
f
rom .models import Question
def
index(request): latest_question_list = 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))

version2:将模板和视图函数拆分,用loader.get_templat()函数调用模板:

# polls/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
from django.http import HttpResponse
def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] template = loader.get_template('polls/index.html') context = { 'latest_question_list': latest_question_list } return HttpResponse(template.render(context))

version3:简化index视图函数,去掉Template(...).render(Context({...}))和loader方法,用render函数替代;render函数返回的是response;render函数,调用了模板,并处理了context:

# polls/templates/polls/index.html
#
polls/views.py from django.shortcuts import render def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5]
   # template = loader.get_template('polls/index.html') context
= { 'latest_question_list': latest_question_list }
   # return
HttpResponse(template.render(context)) return render(request, 'polls/index.html', context)

在老版本中使用render_to_response,在新版本中已作废,使用render代替。

4.设置公用模板 templates和static

创建mysite/templates公共模板目录,放在外层;设置公共模板,设置其中的DIRS:

# mysite/settings.py
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], #修改此处,表示 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', ], }, }, ]

创建mysite/static公共目录,放在外层;设置公共static:

# mysite/settings.py
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]

5.去掉url和static的硬编码部分,使用内置标签url,static。

创建polls/static目录,和django.png图片。

{% load static %}  #加载static标签
#
<img src="/static/django.png"> <img src="{% static 'django.png' %}"> # src=“{% static '静态文件' %}” {% if latest_question_list %} <ul> {% for question in latest_question_list %} #<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> <li><a href="{% url 'detail' question.id %}/">{{ question.question_text }}</a></li> # href="{% url 'url_name' url的参数 %}" {% endfor %} </ul> {% endif %}

6.url 反解析

正解析: url -> view

反解析: url name -> url    reverse(url_name, args, kwargs)

以 url('(?P<question_id>[0-9]+)/$', views.detail, name='detail'), 为示例

from django.shortcuts import reverse
reverse(
'detail', kwargs={'question_id': '1'})  # 返回url路径:polls/1
reverse('detail', args=(1, ))  # 返回url路径: polls/1
reverse(
'detail') # 提示['polls/(?P<question_id>[0-9]+)/$']

说明:
reverse ,reverse_lazy
7.url命名空间 ,在urls.py中定义

定义, app_name=命名空间的名称;引用,命名空间的名称:视图函数名称 ;app级别的,名称可以重复

定义方法1

# polls/urls.py 
.... 
app_name = 'polls'

定义方法2:

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

 命名空间分为:app命名空间,instance命名空间。instance命名空间用得较少,当app有多个include时,则使用instance spacename。

 8.form处理

1).编写前端html:

# polls/templates/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"}   #action提交到哪里
      {% csrf_token %}  #对table的安全防护
      {% 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>   #lable的作用:在选择的时侯,可以选择整个label,即可选中选项
      {% endfor %}
<input type="submit" value="Vote" />
</form>

2).后端

编写detail视图函数:

# poll/views.py

def detail(request, question_id):
    question = get_object_or_404(Question, id=question_id)
    return render(request,'polls/detail.html', {'question': question})

添加选项、用管理器反查关联表:

#添加选项:
from
polls.models import * q = Question.objects.first() Choice.objects.create(question=q, choice_text='Yes') Choice.objects.create(question=q, choice_text='No')
#根据question,查询有哪些选项:
q.choice_set.all()
#查看某question选项的排序:
q.choice_set.order_by('votes')
q.choice_set.order_by('-votes')
#根据选项,反查对应的question:
c = Choice.objects.first() # c为<Choice: Yes>
c.question # 根据选项,查询对应的question
c.id  # 查询选项的id
c.question.id #查询选项对应的问题的id
c = Choice.objects.filter(question_id=1) # 根据question的id查询选项,c为<QuerySet [<Choice: Yes>, <Choice: No>]>
c[0].question #返回对应的question:<Question: name?>
c[0].id #返回3

以上示例中的choice_set是表choice的管理器,默认名称为: 定义外键的表的表名_set。可以在创建外键的时侯,改为其它名字,其字段为: relate_name=“管理器名字”

class Choice(models.Model):
    question = models.ForeignKey(Question, related_name='choices', on_delete=models.CASCADE)
.......

编写vote视图函数,保存用户的选项:

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    print(request.method)
    if request.method == 'POST':
        choice_id = request.POST.get('choice', 0)
        try:
            selected_choice = question.choice_set.get(pk=choice_id)
        except Choice.DoesNotExist:
            return render(request, 'polls/detail.html', {
                'question': question,
                'error_message': "You didn't select a choice."
            })
        else:
            selected_choice.votes += 1
            selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id, )))
    else:
        return HttpResponse("Your post question_id : %s" % question.id)

HttpResponseRedirect,重定向;是对Response的封装,它不允许用户后退后,再重复提交选项。redirect函数,与之相同。

from django.shortcuts import HttpResponseRedirect, redirect
HttpResponseRedirect('http://wwww.baidu.com')
redirect('http://www.baidu.com')
# 两者返回的结果一样:<HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="http://wwww.baidu.com">

request.POST,是一个字典;csrf_token,安全,防跨站攻击;getlist,获取列表的全部的元素;request.GET,获取请求的查询参数;get_object_or_404、get_list_or_404;

3.results页面:

前端:

# polls/templates/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:detail' question.id %}">Vote again?</a>

后端:

# polls/views.py
def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

 

 

 

 

 

 

 

 

 

 

 

 

 

  

posted on 2014-06-15 11:47  myworldworld  阅读(235)  评论(0)    收藏  举报

导航