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.最後執行結果
沒有留言:
張貼留言