【Django】Django框架基础详述(二)

1、模板Template

(1)模板Template使用
django内置了自己的模板引擎,和jinja很像,使用简单。

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

(2)点号的使用

>>> t = Template('Person is {{ person.name }}')
>>> person = {'name': 'guang'}								# 点号用于字典
>>> t.render(Context({'person': person}))
	'Person is guang'
>>> class Person:
...     def __init__(self, name):
...         self.name = name  								# 点号用于属性
>>> person = Person('hongwei'}
>>> t.render(Context({'person': person}))
	'Person is hongwei'
>>> class Person:
		pass
>>> p = Person()
>>> p.name = 'guanghongwei'									# 点号用于属性
>>> t.render(Context({ 'person': p}))
	'Person is guanghongwei'
>>> p.name = lambda: 'guanggg'								# 点号用于方法
>>> p.name
	<function __main__.<lambda>>
>>> p.name()
	'guanggg'
>>> t.render(Context({ 'person': p }))
	'Person is guanggg'
>>> class Person:
...     def name(self):										# 点号用于方法
...         return 'guanghongwei'
>>> person = Person()
>>> t.render(Context({ 'person': person }))
	'Person is guanghongwei'
>>> person = ['guang', 'hongwei']							# 点号用于列表
>>> t = Template('Person is {{ person.0 }}')
>>> t.render(Context({ 'person': person}))
	'Person is guang'
>>> person = ('guang', 'hongwei')							# 点号用于元组
>>> t = Template('Person is {{ person.1 }}')
>>> t.render(Context({ 'person': person}))
	'Person is hongwei'

点号表示的变量查找是有顺序的:字典 --> 属性 --> 方法 --> 列表/元组。
点号表示的函数和方法是不能带任何参数的。
(3)For循环

>>> t = Template('''{% for person in person_list %}
					<li> {{ person.name }} </li>
					{% endfor %}''')
>>> person_list = [{'name': 'guang'}, {'name': 'mage'}]
>>> c = Context(person_list)
>>> t.render(c)
	'\n<li> guang </li>\n\n<li> mage </li>\n'
>>> person = [{'name': 'guang'}, {'name': 'mage'}]
>>> c = Context({'person_list': person})
>>> t.render(c)
	'\n<li> guang </li>\n\n<li> mage </li>\n'

(4)if判断

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

(5)内置过滤器

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

>>> t = Template('Today is {{ now | date:"F j, Y" }}
>>> now = timezone.now()
>>>t.render(Context({ 'now': now }))
   'Today is January 21, 2020'
# 相当于调用如下函数:
def date(datetime, format)

>>> t = Template('My name length is {{ name | length }}')
>>> c = Context({'name': 'guang'})
>>> t.render(c)
	'My name length is 5'
# 相当于调用如下函数:
def length(text):
	return len(text)

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

# polls/views.py
from django.template import Template, Context

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

version 2

# 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

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

version 3

# polls/templates/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.shortcuts import render

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

说明:version 3中,

  • render:新版本Django函数,第一个参数必须为request
  • render_to_response:老版本Django函数,不需要request参数

(7)设置公用 templates 和 static

# mysite/settings.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
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'),
]

(8)去掉url和static硬编码

# polls/templates/polls/index.html
{% load static %}

{# <img src="/static/django.png"> #}
<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> #}
  <li><a href="{% url 'detail' question.id %}">{{ question.question_text }} </a></li>
  {% endfor %}
</ul>
{% endif %}

(9)url 反解析

  • 正解析: url -> view
  • 反解析: view name -> url
>>> from django.shortcuts import reverse
>>> reverse('detail', kwargs={'question_id': '1'})
'/polls/1/
>>> reverse('detail', args=(123,))
'/polls/123/

说明:

  • reverse
  • reverse_lazy

(10)url命名空间

  • app namespace
  • instance namespace

1)app namespace
app级别的,名称可以重复。
定义方法1:

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

定义方法2:

# mysite/urls.py

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

2)instance namespace
instance级别,名称不可以重复。
定义:

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

3)测试
修改templates代码:

# polls/templates/polls/index.html
{% load static %}

{# <img src="/static/django.png"> #}
<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> #}
  <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }} </a></li>
  {% endfor %}
</ul>
{% endif %}
>>> from django.urls import reverse
>>> reverse('polls:detail', kwargs={'question_id': 1})

什么时候用 app namespace?什么时候用 instance namespace?
一般情况下使用 app namespace,如果你的app有多个include,则使用instance namespace。

[
    urls('^polls/', include('polls.view_urls')),
    urls('^api/polls/', include('polls.api_urls')),
]

2、form处理

# 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">
{% 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/views.py

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from .models import Choice, Question

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

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

def results(request, question_id):
	response = "You are looking at results of question {}".format(question_id)
	return HttpResponse(response)
	
def vote(request, question_id):
    question = get_object_or_404(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 Choice.DoesNotExist:
            # Redisplay the question voting form.
            return render(request, 'polls/detail.html', {
                'question': question,
                'error_message': "You didn't select a choice.",
            })
        else:
            selected_choice.votes += 1
            selected_choice.save()
            # Always return an HttpResponseRedirect after successfully dealing
            # with POST data. This prevents data from being posted twice if a
            # user hits the Back button.
            return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))
    else:
    	return HttpResponse('Your post question id: %s' % question.id)

说明:

  • request.POST:返回QueryDict。
  • csrf_token:form里使用,防止跨站攻击,默认启用该中间件。
  • getlist:多选框或下拉列表获得一个list,get只能得到第一个值。
  • request.FILES:上传文件时获取form中的内容。
  • request.GET:返回QueryDict,获取的是提交的url中的参数和get请求提交的内容。
  • Choice.DoesNotExist:GET不能获取内容的话,报该异常。
  • HttpResponseRedirect:重定向,表单post后需要重定向到另一个页面,防止用户重复提交。
  • get_object_or_404:得到对象返回对象,得不到返回404异常。
  • get_list_or_404:objects.filter获取不到list,返回404异常。
  • redirect
>>> from django.shortcuts import redirect
>>> redirect('http://www.qq.com')
<HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="http://www.qq.com">
  • request
    • META HTTP_REFERER, HTTP_USER_AGENT, REMOTE_ADDR
    • schema method COOKIES FILES
    • path, get_host, get_full_path, is_secure

3、results页面

#polls/views.py
from django.shortcuts import get_object_or_404, render

def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})
    
    
#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>    
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页