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
from .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) 收藏 举报