2019年11月29日 星期五

[ Django ] 百香果交易行情網站設計(四) - 讓Mezzanine承接自己的意圖


Mezzanine是以Python/Django為基礎發展出來一套很不錯的內容管理系統(Content Management System)套件,只需要約五行指令就能建構很好看的類似於部落格的網站。本篇將說明如何在Mezzanine中加上百香果交易行情資訊。

若是您還不熟悉Mezzanine以及如何取得果菜市場的資訊,請先參考百香果交易行情網站設計前三篇文章,如下:

1.打開urls.py程式 ,瞭解視圖(views)程式是來自mezzanine.core.views中的direct_to_template函式。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
from __future__ import unicode_literals

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.views.i18n import set_language

from mezzanine.core.views import direct_to_template
from mezzanine.conf import settings

# Uncomment to use blog as home page. See also urlpatterns section below.
# from mezzanine.blog import views as blog_views

admin.autodiscover()

# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.

urlpatterns = i18n_patterns(
    # Change the admin prefix here to use an alternate URL for the
    # admin interface, which would be marginally more secure.
    url("^admin/", include(admin.site.urls)),
)

if settings.USE_MODELTRANSLATION:
    urlpatterns += [
        url('^i18n/$', set_language, name='set_language'),
    ]

urlpatterns += [
    # We don't want to presume how your homepage works, so here are a
    # few patterns you can use to set it up.

    # HOMEPAGE AS STATIC TEMPLATE
    # ---------------------------
    # This pattern simply loads the index.html template. It isn't
    # commented out like the others, so it's the default. You only need
    # one homepage pattern, so if you use a different one, comment this
    # one out.

    url("^$", direct_to_template, {"template": "index.html"}, name="home"),

    # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
    # ---------------------------------------------
    # This pattern gives us a normal ``Page`` object, so that your
    # homepage can be managed via the page tree in the admin. If you
    # use this pattern, you'll need to create a page in the page tree,
    # and specify its URL (in the Meta Data section) as "/", which
    # is the value used below in the ``{"slug": "/"}`` part.
    # Also note that the normal rule of adding a custom
    # template per page with the template name using the page's slug
    # doesn't apply here, since we can't have a template called
    # "/.html" - so for this case, the template "pages/index.html"
    # should be used if you want to customize the homepage's template.
    # NOTE: Don't forget to import the view function too!

    # url("^$", mezzanine.pages.views.page, {"slug": "/"}, name="home"),

    # HOMEPAGE FOR A BLOG-ONLY SITE
    # -----------------------------
    # This pattern points the homepage to the blog post listing page,
    # and is useful for sites that are primarily blogs. If you use this
    # pattern, you'll also need to set BLOG_SLUG = "" in your
    # ``settings.py`` module, and delete the blog page object from the
    # page tree in the admin if it was installed.
    # NOTE: Don't forget to import the view function too!

    # url("^$", blog_views.blog_post_list, name="home"),

    # MEZZANINE'S URLS
    # ----------------
    # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
    # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
    # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
    # WILL NEVER BE MATCHED!

    # If you'd like more granular control over the patterns in
    # ``mezzanine.urls``, go right ahead and take the parts you want
    # from it, and use them directly below instead of using
    # ``mezzanine.urls``.
    url("^", include("mezzanine.urls")),

    # MOUNTING MEZZANINE UNDER A PREFIX
    # ---------------------------------
    # You can also mount all of Mezzanine's urlpatterns under a
    # URL prefix if desired. When doing this, you need to define the
    # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
    # SITE_PREFIX = "my/site/prefix"
    # For convenience, and to avoid repeating the prefix, use the
    # commented out pattern below (commenting out the one above of course)
    # which will make use of the ``SITE_PREFIX`` setting. Make sure to
    # add the import ``from django.conf import settings`` to the top
    # of this file as well.
    # Note that for any of the various homepage patterns above, you'll
    # need to use the ``SITE_PREFIX`` setting as well.

    # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))

]

# Adds ``STATIC_URL`` to the context of error pages, so that error
# pages can use JS, CSS and images.
handler404 = "mezzanine.core.views.page_not_found"
handler500 = "mezzanine.core.views.server_error"

2.找出mezzanine.core.views中的direct_to_template函式的位置,由於在第二篇文章中,我們建置npf虛擬環境,因此我們可以在Envs\npf\Lib\site-packages\mezzanine\core目錄下,發現views.py。

3.打開mezzanine.core.views.pypy在第67-77行,就可以看到direct_to_template函式。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from __future__ import absolute_import, unicode_literals
from future.builtins import int, open, str

import os
import mimetypes

from json import dumps

from django.template.response import TemplateResponse

try:
    from urllib.parse import urljoin, urlparse
except ImportError:
    from urlparse import urljoin, urlparse

from django.apps import apps
from django.contrib import admin
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admin.options import ModelAdmin
from django.contrib.staticfiles import finders
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.http import (HttpResponse, HttpResponseServerError,
                         HttpResponseNotFound)
from django.shortcuts import redirect
from django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.csrf import requires_csrf_token

from mezzanine.conf import settings
from mezzanine.core.forms import get_edit_form
from mezzanine.core.models import Displayable, SitePermission
from mezzanine.utils.views import is_editable, paginate
from mezzanine.utils.sites import has_site_permission
from mezzanine.utils.urls import next_url


mimetypes.init()


@staff_member_required
def set_site(request):
    """
    Put the selected site ID into the session - posted to from
    the "Select site" drop-down in the header of the admin. The
    site ID is then used in favour of the current request's
    domain in ``mezzanine.core.managers.CurrentSiteManager``.
    """
    site_id = int(request.GET["site_id"])
    if not request.user.is_superuser:
        try:
            SitePermission.objects.get(user=request.user, sites=site_id)
        except SitePermission.DoesNotExist:
            raise PermissionDenied
    request.session["site_id"] = site_id
    admin_url = reverse("admin:index")
    next = next_url(request) or admin_url
    # Don't redirect to a change view for an object that won't exist
    # on the selected site - go to its list view instead.
    if next.startswith(admin_url):
        parts = next.split("/")
        if len(parts) > 4 and parts[4].isdigit():
            next = "/".join(parts[:4])
    return redirect(next)


def direct_to_template(request, template, extra_context=None, **kwargs):
    """
    Replacement for Django's ``direct_to_template`` that uses
    ``TemplateResponse`` via ``mezzanine.utils.views.render``.
    """
    context = extra_context or {}
    context["params"] = kwargs
    for (key, value) in context.items():
        if callable(value):
            context[key] = value()
    return TemplateResponse(request, template, context)


@staff_member_required
def edit(request):
    """
    Process the inline editing form.
    """
    model = apps.get_model(request.POST["app"], request.POST["model"])
    obj = model.objects.get(id=request.POST["id"])
    form = get_edit_form(obj, request.POST["fields"], data=request.POST,
                         files=request.FILES)
    if not (is_editable(obj, request) and has_site_permission(request.user)):
        response = _("Permission denied")
    elif form.is_valid():
        form.save()
        model_admin = ModelAdmin(model, admin.site)
        message = model_admin.construct_change_message(request, form, None)
        model_admin.log_change(request, obj, message)
        response = ""
    else:
        response = list(form.errors.values())[0][0]
    return HttpResponse(response)


def search(request, template="search_results.html", extra_context=None):
    """
    Display search results. Takes an optional "contenttype" GET parameter
    in the form "app-name.ModelName" to limit search results to a single model.
    """
    query = request.GET.get("q", "")
    page = request.GET.get("page", 1)
    per_page = settings.SEARCH_PER_PAGE
    max_paging_links = settings.MAX_PAGING_LINKS
    try:
        parts = request.GET.get("type", "").split(".", 1)
        search_model = apps.get_model(*parts)
        search_model.objects.search  # Attribute check
    except (ValueError, TypeError, LookupError, AttributeError):
        search_model = Displayable
        search_type = _("Everything")
    else:
        search_type = search_model._meta.verbose_name_plural.capitalize()
    results = search_model.objects.search(query, for_user=request.user)
    paginated = paginate(results, page, per_page, max_paging_links)
    context = {"query": query, "results": paginated,
               "search_type": search_type}
    context.update(extra_context or {})
    return TemplateResponse(request, template, context)


@staff_member_required
def static_proxy(request):
    """
    Serves TinyMCE plugins inside the inline popups and the uploadify
    SWF, as these are normally static files, and will break with
    cross-domain JavaScript errors if ``STATIC_URL`` is an external
    host. URL for the file is passed in via querystring in the inline
    popup plugin template, and we then attempt to pull out the relative
    path to the file, so that we can serve it locally via Django.
    """
    normalize = lambda u: ("//" + u.split("://")[-1]) if "://" in u else u
    url = normalize(request.GET["u"])
    host = "//" + request.get_host()
    static_url = normalize(settings.STATIC_URL)
    for prefix in (host, static_url, "/"):
        if url.startswith(prefix):
            url = url.replace(prefix, "", 1)
    response = ""
    (content_type, encoding) = mimetypes.guess_type(url)
    if content_type is None:
        content_type = "application/octet-stream"
    path = finders.find(url)
    if path:
        if isinstance(path, (list, tuple)):
            path = path[0]
        if url.endswith(".htm"):
            # Inject <base href="{{ STATIC_URL }}"> into TinyMCE
            # plugins, since the path static files in these won't be
            # on the same domain.
            static_url = settings.STATIC_URL + os.path.split(url)[0] + "/"
            if not urlparse(static_url).scheme:
                static_url = urljoin(host, static_url)
            base_tag = "<base href='%s'>" % static_url
            with open(path, "r") as f:
                response = f.read().replace("<head>", "<head>" + base_tag)
        else:
            try:
                with open(path, "rb") as f:
                    response = f.read()
            except IOError:
                return HttpResponseNotFound()
    return HttpResponse(response, content_type=content_type)


def displayable_links_js(request):
    """
    Renders a list of url/title pairs for all ``Displayable`` subclass
    instances into JSON that's used to populate a list of links in
    TinyMCE.
    """
    links = []
    if "mezzanine.pages" in settings.INSTALLED_APPS:
        from mezzanine.pages.models import Page
        is_page = lambda obj: isinstance(obj, Page)
    else:
        is_page = lambda obj: False
    # For each item's title, we use its model's verbose_name, but in the
    # case of Page subclasses, we just use "Page", and then sort the items
    # by whether they're a Page subclass or not, then by their URL.
    for url, obj in Displayable.objects.url_map(for_user=request.user).items():
        title = getattr(obj, "titles", obj.title)
        real = hasattr(obj, "id")
        page = is_page(obj)
        if real:
            verbose_name = _("Page") if page else obj._meta.verbose_name
            title = "%s: %s" % (verbose_name, title)
        links.append((not page and real, {"title": str(title), "value": url}))
    sorted_links = sorted(links, key=lambda link: (link[0], link[1]['value']))
    return HttpResponse(dumps([link[1] for link in sorted_links]))


@requires_csrf_token
def page_not_found(request, *args, **kwargs):
    """
    Mimics Django's 404 handler but with a different template path.
    """
    context = {
        "STATIC_URL": settings.STATIC_URL,
        "request_path": request.path,
    }
    t = get_template(kwargs.get("template_name", "errors/404.html"))
    return HttpResponseNotFound(t.render(context, request))


@requires_csrf_token
def server_error(request, template_name="errors/500.html"):
    """
    Mimics Django's error handler but adds ``STATIC_URL`` to the
    context.
    """
    context = {"STATIC_URL": settings.STATIC_URL}
    t = get_template(template_name)
    return HttpResponseServerError(t.render(context, request))

4.找出npf/moderna/views.py,只有一行指令。

1
2
3
from django.shortcuts import render

# Create your views here.

5.把步驟3的程式第67-77行,複製到步驟4的程式


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from django.shortcuts import render
from django.template.response import TemplateResponse

# Create your views here.

def direct_to_template(request, template, extra_context=None, **kwargs):
    """
    Replacement for Django's ``direct_to_template`` that uses
    ``TemplateResponse`` via ``mezzanine.utils.views.render``.
    """
    context = extra_context or {}
    context["params"] = kwargs
    for (key, value) in context.items():
        if callable(value):
            context[key] = value()
    return TemplateResponse(request, template, context)

6.修改urls.py程式,導引到自己的視圖程式的函式。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
from __future__ import unicode_literals

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.views.i18n import set_language

from moderna.views import direct_to_template
from mezzanine.conf import settings

# Uncomment to use blog as home page. See also urlpatterns section below.
# from mezzanine.blog import views as blog_views

admin.autodiscover()

# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.

urlpatterns = i18n_patterns(
    # Change the admin prefix here to use an alternate URL for the
    # admin interface, which would be marginally more secure.
    url("^admin/", include(admin.site.urls)),
)

if settings.USE_MODELTRANSLATION:
    urlpatterns += [
        url('^i18n/$', set_language, name='set_language'),
    ]

urlpatterns += [
    # We don't want to presume how your homepage works, so here are a
    # few patterns you can use to set it up.

    # HOMEPAGE AS STATIC TEMPLATE
    # ---------------------------
    # This pattern simply loads the index.html template. It isn't
    # commented out like the others, so it's the default. You only need
    # one homepage pattern, so if you use a different one, comment this
    # one out.

    url("^$", direct_to_template, {"template": "index.html"}, name="home"),

    # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
    # ---------------------------------------------
    # This pattern gives us a normal ``Page`` object, so that your
    # homepage can be managed via the page tree in the admin. If you
    # use this pattern, you'll need to create a page in the page tree,
    # and specify its URL (in the Meta Data section) as "/", which
    # is the value used below in the ``{"slug": "/"}`` part.
    # Also note that the normal rule of adding a custom
    # template per page with the template name using the page's slug
    # doesn't apply here, since we can't have a template called
    # "/.html" - so for this case, the template "pages/index.html"
    # should be used if you want to customize the homepage's template.
    # NOTE: Don't forget to import the view function too!

    # url("^$", mezzanine.pages.views.page, {"slug": "/"}, name="home"),

    # HOMEPAGE FOR A BLOG-ONLY SITE
    # -----------------------------
    # This pattern points the homepage to the blog post listing page,
    # and is useful for sites that are primarily blogs. If you use this
    # pattern, you'll also need to set BLOG_SLUG = "" in your
    # ``settings.py`` module, and delete the blog page object from the
    # page tree in the admin if it was installed.
    # NOTE: Don't forget to import the view function too!

    # url("^$", blog_views.blog_post_list, name="home"),

    # MEZZANINE'S URLS
    # ----------------
    # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
    # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
    # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
    # WILL NEVER BE MATCHED!

    # If you'd like more granular control over the patterns in
    # ``mezzanine.urls``, go right ahead and take the parts you want
    # from it, and use them directly below instead of using
    # ``mezzanine.urls``.
    url("^", include("mezzanine.urls")),

    # MOUNTING MEZZANINE UNDER A PREFIX
    # ---------------------------------
    # You can also mount all of Mezzanine's urlpatterns under a
    # URL prefix if desired. When doing this, you need to define the
    # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
    # SITE_PREFIX = "my/site/prefix"
    # For convenience, and to avoid repeating the prefix, use the
    # commented out pattern below (commenting out the one above of course)
    # which will make use of the ``SITE_PREFIX`` setting. Make sure to
    # add the import ``from django.conf import settings`` to the top
    # of this file as well.
    # Note that for any of the various homepage patterns above, you'll
    # need to use the ``SITE_PREFIX`` setting as well.

    # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))

]

# Adds ``STATIC_URL`` to the context of error pages, so that error
# pages can use JS, CSS and images.
handler404 = "mezzanine.core.views.page_not_found"
handler500 = "mezzanine.core.views.server_error"

7.在視圖程式中,撰寫讀取百香果交易行情的程式。(請參閱百香網誌:使用Python和Django設計百香果農產品交易行情網站)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from django.shortcuts import render
from django.template.response import TemplateResponse

# Create your views here.
import requests
import json

def direct_to_template(request, template, extra_context=None, **kwargs):
    """
    Replacement for Django's ``direct_to_template`` that uses
    ``TemplateResponse`` via ``mezzanine.utils.views.render``.
    """
    context = extra_context or {}
    context["params"] = kwargs
    
    for (key, value) in context.items():
        print (key, value)
        if callable(value):
            context[key] = value()
            
    r = requests.get('http://data.coa.gov.tw/Service/OpenData/FromM/FarmTransData.aspx')
    fruits = json.loads(r.text)
    rows = []
    for row in fruits:
        if '百香果' in row['作物名稱']:
            rows.append(row)

    return TemplateResponse(request, template, locals())
#    return TemplateResponse(request, template, context)

8.在樣版程式中選擇適當位置,插入百香果交易行情的模版程式。(請參閱百香網誌:使用Python和Django設計百香果農產品交易行情網站)


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
{% extends "base.html" %}
{% load i18n  mezzanine_tags staticfiles%}
{% block meta_title %}{% trans "Home" %}{% endblock %}
{% block title %}{% trans "Home" %}{% endblock %}
{% block breadcrumb_wrapper %}
{% endblock %}

{% block title_wrapper %}
{% endblock %}

{% block breadcrumb_menu %}
<li class="active">{% trans "Home" %}</li>
{% endblock %}


{% block all_content %}
<section id="{% block section_id %}featured{% endblock %}">
{% block left_wrapper %}
{% endblock %}


{% block main_wrapper %}
<div class="col-md-{% block main_col_size %}none{% endblock %} {% block main_class %}{% endblock %}">
{% block main %}


<!-- start slider -->
 <div class="container">
  <div class="row">
   <div class="col-lg-12">
 <!-- Slider -->
        <div id="main-slider" class="flexslider">
            <ul class="slides">
              <li>
                <img src="{% static "img/slides/1.jpg" %}" alt="" />
                <div class="flex-caption">
                    <h3>Modern Design</h3> 
     <p>Duis fermentum auctor ligula ac malesuada. Mauris et metus odio, in pulvinar urna</p> 
     <a href="#" class="btn btn-theme">Learn More</a>
                </div>
              </li>
              <li>
                <img src="{% static "img/slides/2.jpg" %}" alt="" />
                <div class="flex-caption">
                    <h3>Fully Responsive</h3> 
     <p>Sodales neque vitae justo sollicitudin aliquet sit amet diam curabitur sed fermentum.</p> 
     <a href="#" class="btn btn-theme">Learn More</a>
                </div>
              </li>
              <li>
                <img src="{% static "img/slides/3.jpg" %}" alt="" />
                <div class="flex-caption">
                    <h3>Clean & Fast</h3> 
     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit donec mer lacinia.</p> 
     <a href="#" class="btn btn-theme">Learn More</a>
                </div>
              </li>
            </ul>
        </div>
 <!-- end slider -->
   </div>
  </div>
 </div> 

{% endblock %}
</div>
{% endblock %}
{% block right_wrapper %}
{% endblock %}
</section>
<section class="callaction">
 <div class="container">
  <div class="row">
   <div class="col-lg-12">
    <div class="big-cta">
     <div class="cta-text">
      <h2><span>Moderna</span> Free Mezzanine Business theme</h2>
{% for row in rows %}
{% if forloop.first %}
<table style='width:100%' border='1'>
<caption><h2>百香果市場交易情形</h2></caption>
<tr><th>交易日期</th><th>作物代號</th><th>作物名稱</th><th>市場代碼</th><th>市場名稱</th><th>上價</th><th>中價</th><th>下價</th><th>平均價</th><th>交易量</th></tr>
{% endif %}
<tr>
<td><center>{{ row.交易日期 }}</center></td>
<td><center>{{ row.作物代號 }}</center></td>
<td><center>{{ row.作物名稱 }}</center></td>
<td><center>{{ row.市場代號 }}</center></td>
<td><center>{{ row.市場名稱 }}</center></td>
<td><center>{{ row.上價 }}</center></td>
<td><center>{{ row.中價 }}</center></td>
<td><center>{{ row.下價 }}</center></td>
<td><center>{{ row.平均價 }}</center></td>
<td><center>{{ row.交易量 }}</center></td>
</tr>
{% if forloop.last %}
</table>
{% endif %}
{% endfor %}
     </div>
    </div>
   </div>
  </div>
 </div>
 </section>

<section id="content">
 <div class="container">
  <div class="row">
   <div class="col-lg-12">
    <div class="row">
     <div class="col-lg-3">
      <div class="box">
       <div class="box-gray aligncenter">
        <h4>Fully responsive</h4>
        <div class="icon">
        <i class="fa fa-desktop fa-3x"></i>
        </div>
        <p class="">
         Voluptatem accusantium doloremque laudantium sprea totam rem aperiam.
        </p>
         
       </div>
       <div class="box-bottom">
        <a href="#">Learn more</a>
       </div>
      </div>
     </div>
     <div class="col-lg-3">
      <div class="box">
       <div class="box-gray aligncenter">
        <h4>Modern Style</h4>
        <div class="icon">
        <i class="fa fa-pagelines fa-3x"></i>
        </div>
        <p>
         Voluptatem accusantium doloremque laudantium sprea totam rem aperiam.
        </p>
         
       </div>
       <div class="box-bottom">
        <a href="#">Learn more</a>
       </div>
      </div>
     </div>
     <div class="col-lg-3">
      <div class="box">
       <div class="box-gray aligncenter">
        <h4>Customizable</h4>
        <div class="icon">
        <i class="fa fa-edit fa-3x"></i>
        </div>
        <p>
         Voluptatem accusantium doloremque laudantium sprea totam rem aperiam.
        </p>
         
       </div>
       <div class="box-bottom">
        <a href="#">Learn more</a>
       </div>
      </div>
     </div>
     <div class="col-lg-3">
      <div class="box">
       <div class="box-gray aligncenter">
        <h4>Valid HTML5</h4>
        <div class="icon">
        <i class="fa fa-code fa-3x"></i>
        </div>
        <p>
         Voluptatem accusantium doloremque laudantium sprea totam rem aperiam.
        </p>
         
       </div>
       <div class="box-bottom">
        <a href="#">Learn more</a>
       </div>
      </div>
     </div>
    </div>
   </div>
  </div>
  <!-- divider -->
  <div class="row">
   <div class="col-lg-12">
    <div class="solidline">
    </div>
   </div>
  </div>
  <!-- end divider -->
  <!-- Portfolio Projects -->
  <div class="row">
   <div class="col-lg-12">
    <h4 class="heading">Recent Works</h4>
    <div class="row">
     <section id="projects">
     <ul class="portfolio" id="thumbs">
      <!-- Item Project and Filter Name -->
      <li data-type="web" data-id="id-0" class="col-lg-3 design">
      <div class="item-thumbs">
      <!-- Fancybox - Gallery Enabled - Title - Full Image -->
      <a href="{% static "img/works/1.jpg" %}" title="Work 1" data-fancybox-group="gallery" class="hover-wrap fancybox">
      <span class="overlay-img"></span>
      <span class="overlay-img-thumb font-icon-plus"></span>
      </a>
      <!-- Thumb Image and Description -->
      <img alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis elementum odio. Curabitur pellentesque, dolor vel pharetra mollis." src="{% static "img/works/1.jpg" %}">
      </div>
      </li>
      <!-- End Item Project -->
      <!-- Item Project and Filter Name -->
      <li data-type="icon" data-id="id-1" class="item-thumbs col-lg-3 design">
      <!-- Fancybox - Gallery Enabled - Title - Full Image -->
      <a href="{% static "img/works/2.jpg" %}" title="Work 2" data-fancybox-group="gallery" class="hover-wrap fancybox">
      <span class="overlay-img"></span>
      <span class="overlay-img-thumb font-icon-plus"></span>
      </a>
      <!-- Thumb Image and Description -->
      <img alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis elementum odio. Curabitur pellentesque, dolor vel pharetra mollis." src="{% static "img/works/2.jpg" %}">
      </li>
      <!-- End Item Project -->
      <!-- Item Project and Filter Name -->
      <li data-type="illustrator" data-id="id-2" class="item-thumbs col-lg-3 photography">
      <!-- Fancybox - Gallery Enabled - Title - Full Image -->
      <a href="{% static "img/works/3.jpg" %}" title="Work 3" data-fancybox-group="gallery" class="hover-wrap fancybox">
      <span class="overlay-img"></span>
      <span class="overlay-img-thumb font-icon-plus"></span>
      </a>
      <!-- Thumb Image and Description -->
      <img alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis elementum odio. Curabitur pellentesque, dolor vel pharetra mollis." src="{% static "img/works/3.jpg" %}">
      </li>
      <!-- End Item Project -->
      <!-- Item Project and Filter Name -->
      <li data-type="illustrator" data-id="id-2" class="item-thumbs col-lg-3 photography">
      <!-- Fancybox - Gallery Enabled - Title - Full Image -->
      <a href="{% static "img/works/4.jpg" %}" title="Work 4" data-fancybox-group="gallery" class="hover-wrap fancybox">
      <span class="overlay-img"></span>
      <span class="overlay-img-thumb font-icon-plus"></span>
      </a>
      <!-- Thumb Image and Description -->
      <img alt="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus quis elementum odio. Curabitur pellentesque, dolor vel pharetra mollis." src="{% static "img/works/4.jpg" %}">
      </li>
      <!-- End Item Project -->
     </ul>
     </section>
    </div>
   </div>
  </div>

 </div>
 </section>

{% endblock %}

10.最後執行結果

沒有留言:

張貼留言