はじめに
以前に「見よ!これが Python製の WordPress風フルスタックCMSフレームワーク「Mezzanine(メザニン)」だ!」という記事で、Python製の WordPress風フルスタックCMSフレームワーク「Mezzanine」を紹介しましたが、今回は、その Mezzanine プロジェクトの開発環境を、Mac版 PyCharm Professional Edition で設定するための手順を書いてみます。
PyCharm Professional Edition は Homebrew-Cask でインストールしています。
<過去記事>
akiyoko.hatenablog.jp
PyCharm の初期設定は済んでいるという前提で進めます。
<過去記事>
akiyoko.hatenablog.jp
やりたいこと
- 最新版の Mezzanine プロジェクトを Vagrant サーバにインストール
- Vagrant サーバと Mac上の PyCharm とのソースコード同期設定
- リモートデバッグ設定
- Mezzanine テーマを変更
環境
<クライアント>
- Mac OS X 10.10.5
- PyCharm (Professional Edition) 5.0.4
<サーバ>
- Ubuntu 14.04 LTS(on Vagrant)
- IPアドレス:192.168.33.103
- ログインユーザ:vagrant
<Mezzanineプロジェクト>
- Django 1.9.5
- Mezzanine 4.1.0
- Cartridge 0.11.0
1. PyCharm の設定(1)
1.1. Pure Python Project を作成
PyCharm を起動し、 [Create New Project] をクリックします。
[Pure Python] を選択し、
Location | /Users/akiyoko/PycharmProjects/mezzanine_project |
Interpreter | (適当) |
を設定します。Interpreter は、後でリモート側の virtualenv のものに変更するので、ここでは適当なものを選択しておきます。
ここで、[Django] プロジェクトではなく [Pure Python] を選択した理由は、[Pure Python] プロジェクトにしておかないとリモートデバッグ機能が使えない(はずだ)からです。
1.2. Vagrant連携
[Tools] > [Vagrant] > [Init in Project Root] を選択します。
PyCharm 上で、Vagrantfile を開いて編集します。
<変更後>
config.vm.network "private_network", ip: "192.168.33.103"
[Tools] > [Vagrant] > [Up] でインスタンスを起動します。
2. Vagrantサーバの初期設定
Vagrant サーバに ssh で乗り込みます。
$ ssh vagrant@192.168.33.103
2.1. 最低限のインストール
$ sudo apt-get update $ sudo apt-get -y install python-dev git tree
2.2. MySQL をインストール
Ubuntu サーバに MySQL をインストールします。
sudo apt-get -y install mysql-server (root/rootpass) sudo apt-get -y install mysql-client libmysqlclient-dev python-mysqldb $ mysql --version mysql Ver 14.14 Distrib 5.5.47, for debian-linux-gnu (x86_64) using readline 6.3 sudo mysql_install_db ### 文字化け対策(セクションの最後に以下の設定を追加) ### http://blog.snowcait.info/2014/06/04/mariadb-utf8/ $ sudo vi /etc/mysql/my.cnf --- [mysqld] ・ ・ # ssl-ca=/etc/mysql/cacert.pem # ssl-cert=/etc/mysql/server-cert.pem # ssl-key=/etc/mysql/server-key.pem # Character set settings character-set-server = utf8 [mysqldump] ・ ・ --- $ sudo service mysql restart $ sudo mysql_secure_installation Enter current password for root (enter for none): Change the root password? [Y/n] n Remove anonymous users? [Y/n] Y Disallow root login remotely? [Y/n] Y Remove test database and access to it? [Y/n] Y Reload privilege tables now? [Y/n] Y
参考
データベース、データベースユーザを作成します。
なお、データベース名は Djangoプロジェクト名と合わせて myproject とします。
データベース名 | myproject |
データベースユーザ | myprojectuser |
データベースユーザパスワード | myprojectuserpass |
$ mysql -u root -p mysql> create database myproject character set utf8; mysql> create user myprojectuser@localhost identified by "myprojectuserpass"; mysql> grant all privileges on myproject.* to myprojectuser@localhost; mysql> flush privileges; mysql> exit
2.3. pip をインストール
Python 2.7.9 以降であれば pip がバンドルされているが、Ubuntu 14.04LTS では Python 2.7.6 が標準なので、手動でインストールします。
「sudo apt-get -y install python-pip」でインストールすると pip のバージョンが古いので、get-pip.py で最新版を入れることにします。
$ wget https://bootstrap.pypa.io/get-pip.py $ sudo -H python get-pip.py $ pip --version pip 8.1.0 from /usr/local/lib/python2.7/dist-packages (python 2.7)
2.4. virtualenv, virtualenvwrapper をインストール
### virtualenv, virtualenvwrapper をインストール $ sudo -H pip install virtualenv virtualenvwrapper ### virtualenvwrapper の設定 $ cat << EOF >> ~/.bash_profile if [ -f ~/.bashrc ]; then . ~/.bashrc fi EOF $ cat << EOF >> ~/.bashrc source /usr/local/bin/virtualenvwrapper.sh export WORKON_HOME=~/.virtualenvs EOF $ source ~/.bashrc
2.5. Mezzanineプロジェクトを作成
Overview — Mezzanine 4.1.0 documentation
に従って、Mezzanineプロジェクトのインストールをします。
### Djangoプロジェクトの virtualenv 環境を設定して activate $ mkvirtualenv myproject ### /opt/webapps 配下にプロジェクトの外箱を作成 $ sudo mkdir -p /opt/webapps/myproject $ sudo chown -R `whoami`. /opt/webapps ### イメージライブラリのインストール ### http://mezzanine.jupo.org/docs/overview.html#dependencies $ sudo apt-get -y install libjpeg8 libjpeg8-dev $ sudo apt-get -y build-dep python-imaging ### MySQLライブラリのインストール $ pip install MySQL-python ### Mezzanine プロジェクトを作成 $ cd /opt/webapps/myproject/ ### Cartridge のインストール $ pip install -U cartridge $ pip list |grep Django Django (1.9.5) $ pip list |grep Mezzanine Mezzanine (4.1.0) $ pip list |grep Cartridge Cartridge (0.11.0) ### プロジェクトのディレクトリ構造は ### myproject/ as <repository_root> also as <django_project_root> ### └─ config/ as <configuration_root> $ mezzanine-project -a cartridge config . $ tree -a /opt/webapps/myproject/ /opt/webapps/myproject/ ├── config │ ├── dev.db │ ├── __init__.py │ ├── local_settings.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── deploy │ ├── crontab.template │ ├── gunicorn.conf.py.template │ ├── local_settings.py.template │ ├── nginx.conf.template │ └── supervisor.conf.template ├── .DS_Store ├── fabfile.py ├── .gitignore ├── .hgignore ├── __init__.py ├── manage.py └── requirements.txt
2.6. Django のデータベース設定を変更
### デフォルトで用意されている config/dev.db は不要なので削除 $ rm config/dev.db ### MySQL用の設定変更 $ vi config/local_settings.py <変更前> --- DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": "dev.db", "USER": "", "PASSWORD": "", "HOST": "", "PORT": "", } } --- <変更後> --- DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "myproject", "USER": "myprojectuser", "PASSWORD": "myprojectuserpass", "HOST": "localhost", "PORT": "", } }
2.7. デモ用のレコードを投入
createdb でデモ用のレコードを投入することができます。
### migrate実行 ### --noinput オプションを付けると、デモ用の初期データ(site, superuser, 画像などのコンテンツ, etc)を自動登録 ### --nodata オプションを付けると、デモ用画像やギャラリーなどのコンテンツを static 配下に自動作成しない $ python manage.py createdb --noinput ### とりあえずデータベースをバックアップ ### http://weblabo.oscasierra.net/mysql-mysqldump-01/ ### ちなみに、リストアするときは mysql -u root -p myproject < ~/myproject_init.dump $ mysqldump --single-transaction -u root -p myproject > ~/myproject_init.dump
2.8. runserver で起動
$ python manage.py runserver 0.0.0.0:8000
http://192.168.33.103:8000/admin/
にブラウザからアクセスします。
(admin/default)
疎通がOKなら、runserver を一旦停止します。
3. PyCharm の設定(2)
3.1. デプロイ先サーバ設定
[Tools] > [Deployment] > [Options] の [Exclude items by name] に以下を設定します。
.svn;.cvs;.idea;.DS_Store;.git;.hg;.vagrant;Vagrantfile;*.pyc;*.swp;*.db;*.sock;*.pid
[Tools] > [Deployment] > [Configuration] で設定画面を開き、「+」ボタンをクリックしてサーバの設定を追加します。
Name | mezzanine_project |
Type | SFTP |
各種設定をします。
[Connection]
[Visible only for this project] にチェックを入れます。
SFTP host | 192.168.33.103 |
Port | 22 |
Root path | /([Autodetect] はクリックしない。「/home/vagrant」だとファイルを同期ダウンロードできなくなる) |
User name | vagrant |
Password | vagant([Save password] にチェックを入れる) |
[Mappings]
[Use this server as default] をクリックします。
Local path | /Users/akiyoko/PycharmProjects/mezzanine_project(デフォルトのまま) |
Deployment path | /opt/webapps/myproject |
3.2. ソースコードの同期
プロジェクトで右クリック > [Deployment] > [Download from mezzanine_project] を選択して、Vagrantサーバから PyCharm にプロジェクトをダウンロードします。
ここで、[Tools] > [Deployment] > [Automatic Upload] にチェックを入れます。
3.3. ローカル側でソースコードを Git管理
まず、不要なファイルを削除します。
Mercurialは使わないので .hgignore を Projectペイン上で削除します。
次に、PyCharm の Terminal を開きます。
まだ git config -l の設定をしていなければ、PyCharm の Terminal で以下を設定します。
$ cd ~/PycharmProjects/mezzanine_project/ $ git config --global user.name akiyoko $ git config --global user.email akiyoko@users.noreply.github.com $ git config --global color.ui auto
git init する前に、.gitignore に PyCharm 用の設定を追加しておきます。
.gitignore
*.pyc
*.pyo
*.db
.DS_Store
.coverage
local_settings.py
/static
# PyCharm
.idea/
.vagrant/
Vagrantfile
一旦コミットします。
$ git init $ git add . $ git commit -m "Initial commit"
3.4. Project Interpreter の設定
[Preferences] > [Project: mezzanine_project] > [Project Interpreter] から、[Python Interpreter] の右側の歯車アイコンをクリックし、[Add Remote] を選択します。
[Vagrant] を選択し、
Vagrant Instance Folder | /Users/akiyoko/PycharmProjects/mezzanine_project(デフォルトのまま) |
Vagrant Host URL | ssh://vagrant@127.0.0.1:2222(デフォルトのまま) |
Python interpreter path | /home/vagrant/.virtualenvs/myproject/bin/python |
を入力して、OK をクリックします。
作成した Remote Interpreter が選択されていることを確認して、[OK] をクリックします。
ここで、Python モジュールに参照エラーが出ないようにするために、[File] > [Invalidate Caches / Restart] を選択し、[Invalidate and Restart] をクリックして、PyCharm を再起動しておきます。
3.5. Run/Debug設定
Project ペインの manage.py ファイルで右クリック > [Create "manage"] を選択します。
Name | manage |
Script | manage.py |
Script parameters | runserver 0.0.0.0:8000 |
Environment variables | PYTHONUNBUFFERED=1(デフォルトのまま) |
Python interpreter | Project Default (Remote Python 2.7.6 Vagrant VM at ~/PycharmProjects/mezzanine_project (/home/vagrant/.virtualenvs/myproject/bin/python)) |
Working directory | /opt/webapps/myproject |
Path mappings - Local path | /Users/akiyoko/PycharmProjects/mezzanine_project |
Path mappings - Remote path | /opt/webapps/myproject |
ここで、「Add content roots to PYTHONPATH」と「Add source roots to PYTHONPATH」のチェックを外します。
デバッグ実行できるか確認できれば、OKです。
3.6. テンプレート設定
ここで、Mezzanine本体の templates をコピーしておきます。
Vagrant サーバ側で、
$ cd /opt/webapps/myproject/ ### Mezzanine のテンプレートをコピー $ cp -a ~/.virtualenvs/myproject/lib/python2.7/site-packages/mezzanine/core/templates . ### Cartridge のテンプレートをコピー $ cp -a ~/.virtualenvs/myproject/lib/python2.7/site-packages/cartridge/shop/templates .
を実行した後、PyCharm 上でファイルを同期(ダウンロード)します。
テンプレート(htmlファイル)が参照エラーで真っ赤に染まってしまっている場合は、[Preferences] > [Languages & Frameworks] > [Python Template Languages] から、「Template language」を「Django」に設定すれば解消するはずです。
4. テーマ変更
参考
試しに、
https://github.com/thecodinghouse/mezzanine-themes.git
の moderna テーマを入れてみます。
ローカル側で、以下を実行します。
$ cd ~/dev/ $ git clone https://github.com/thecodinghouse/mezzanine-themes.git $ cp -a mezzanine-themes/moderna ~/PycharmProjects/mezzanine_project/
コマンドでコピーしたファイルはサーバ側に自動転送されないので、[Deployment] > [Upload to mezzanine_project] で手動アップロードしておきます。
コピーしたテーマを Djangoアプリケーションとして設定するために、config/settings.py の INSTALLED_APPS の最後、および TEMPLATES/DIRS の先頭に追加します。
config/settings.py
TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [ os.path.join(PROJECT_ROOT, "moderna/templates"), os.path.join(PROJECT_ROOT, "templates") ], "APP_DIRS": True, ・ ・ ] INSTALLED_APPS = ( ・ ・ "mezzanine.twitter", # "mezzanine.accounts", # "mezzanine.mobile", "moderna", )
まとめ
Mezzanine は普通の Django プロジェクトなので、インストールやテンプレートの設定自体は Django のものと何ら変わりません。
あとはドキュメントを読むだけですね。
Mezzanine — Mezzanine 4.1.0 documentation
参考
最新版 Mezzanine インストール時のパッケージ情報
$ pip freeze beautifulsoup4==4.4.1 bleach==1.4.2 Cartridge==0.11.0 chardet==2.3.0 Django==1.9.5 django-contrib-comments==1.7.0 filebrowser-safe==0.4.3 future==0.15.2 grappelli-safe==0.4.2 html5lib==0.9999999 Mezzanine==4.1.0 MySQL-python==1.2.5 oauthlib==1.0.3 Pillow==3.2.0 PyPDF2==1.25.1 pytz==2016.3 reportlab==3.3.0 requests==2.9.1 requests-oauthlib==0.6.1 six==1.10.0 tzlocal==1.2.2 xhtml2pdf==0.0.6
各種 URLconf
config/urls.py
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 from cartridge.shop.views import order_history 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 += [ # Cartridge URLs. url("^shop/", include("cartridge.shop.urls")), url("^account/orders/$", order_history, name="shop_order_history"), # 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("^$", mezzanine.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. # url("^%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"
/home/vagrant/.virtualenvs/myproject/local/lib/python2.7/site-packages/mezzanine/urls.py
""" This is the main ``urlconf`` for Mezzanine - it sets up patterns for all the various Mezzanine apps, third-party apps like Grappelli and filebrowser. """ from __future__ import unicode_literals from future.builtins import str from django.conf.urls import include, url from django.contrib.sitemaps.views import sitemap from django.views.i18n import javascript_catalog from django.http import HttpResponse from mezzanine.conf import settings from mezzanine.core.sitemaps import DisplayableSitemap urlpatterns = [] # JavaScript localization feature js_info_dict = {'domain': 'django'} urlpatterns += [ url(r'^jsi18n/(?P<packages>\S+?)/$', javascript_catalog, js_info_dict), ] if settings.DEBUG and "debug_toolbar" in settings.INSTALLED_APPS: try: import debug_toolbar except ImportError: pass else: urlpatterns += [ url(r'^__debug__/', include(debug_toolbar.urls)), ] # Django's sitemap app. if "django.contrib.sitemaps" in settings.INSTALLED_APPS: sitemaps = {"sitemaps": {"all": DisplayableSitemap}} urlpatterns += [ url("^sitemap\.xml$", sitemap, sitemaps), ] # Return a robots.txt that disallows all spiders when DEBUG is True. if getattr(settings, "DEBUG", False): urlpatterns += [ url("^robots.txt$", lambda r: HttpResponse("User-agent: *\nDisallow: /", content_type="text/plain")), ] # Miscellanous Mezzanine patterns. urlpatterns += [ url("^", include("mezzanine.core.urls")), url("^", include("mezzanine.generic.urls")), ] # Mezzanine's Accounts app if "mezzanine.accounts" in settings.INSTALLED_APPS: # We don't define a URL prefix here such as /account/ since we want # to honour the LOGIN_* settings, which Django has prefixed with # /account/ by default. So those settings are used in accounts.urls urlpatterns += [ url("^", include("mezzanine.accounts.urls")), ] # Mezzanine's Blog app. blog_installed = "mezzanine.blog" in settings.INSTALLED_APPS if blog_installed: BLOG_SLUG = settings.BLOG_SLUG.rstrip("/") + "/" blog_patterns = [ url("^%s" % BLOG_SLUG, include("mezzanine.blog.urls")), ] urlpatterns += blog_patterns # Mezzanine's Pages app. PAGES_SLUG = "" if "mezzanine.pages" in settings.INSTALLED_APPS: # No BLOG_SLUG means catch-all patterns belong to the blog, # so give pages their own prefix and inject them before the # blog urlpatterns. if blog_installed and not BLOG_SLUG.rstrip("/"): PAGES_SLUG = getattr(settings, "PAGES_SLUG", "pages").strip("/") + "/" blog_patterns_start = urlpatterns.index(blog_patterns[0]) urlpatterns[blog_patterns_start:len(blog_patterns)] = [ url("^%s" % str(PAGES_SLUG), include("mezzanine.pages.urls")), ] else: urlpatterns += [ url("^", include("mezzanine.pages.urls")), ]
/home/vagrant/.virtualenvs/myproject/local/lib/python2.7/site-packages/mezzanine/core/urls.py
from __future__ import unicode_literals from django.conf.urls import url from django.contrib.auth import views as auth_views from mezzanine.conf import settings from mezzanine.core import views as core_views urlpatterns = [] if "django.contrib.admin" in settings.INSTALLED_APPS: urlpatterns += [ url("^password_reset/$", auth_views.password_reset, name="password_reset"), url("^password_reset/done/$", auth_views.password_reset_done, name="password_reset_done"), url("^reset/done/$", auth_views.password_reset_complete, name="password_reset_complete"), url("^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$", auth_views.password_reset_confirm, name="password_reset_confirm"), ] urlpatterns += [ url("^edit/$", core_views.edit, name="edit"), url("^search/$", core_views.search, name="search"), url("^set_site/$", core_views.set_site, name="set_site"), url("^set_device/(?P<device>.*)/$", core_views.set_device, name="set_device"), url("^asset_proxy/$", core_views.static_proxy, name="static_proxy"), url("^displayable_links.js$", core_views.displayable_links_js, name="displayable_links_js"), ]
/home/vagrant/.virtualenvs/myproject/local/lib/python2.7/site-packages/mezzanine/generic/urls.py
from __future__ import unicode_literals from django.conf.urls import url from mezzanine.generic import views urlpatterns = [ url("^admin_keywords_submit/$", views.admin_keywords_submit, name="admin_keywords_submit"), url("^rating/$", views.rating, name="rating"), url("^comment/$", views.comment, name="comment"), ]
/home/vagrant/.virtualenvs/myproject/local/lib/python2.7/site-packages/mezzanine/blog/urls.py
from __future__ import unicode_literals from django.conf.urls import url from mezzanine.blog import views from mezzanine.conf import settings # Trailing slahes for urlpatterns based on setup. _slash = "/" if settings.APPEND_SLASH else "" # Blog patterns. urlpatterns = [ url("^feeds/(?P<format>.*)%s$" % _slash, views.blog_post_feed, name="blog_post_feed"), url("^tag/(?P<tag>.*)/feeds/(?P<format>.*)%s$" % _slash, views.blog_post_feed, name="blog_post_feed_tag"), url("^tag/(?P<tag>.*)%s$" % _slash, views.blog_post_list, name="blog_post_list_tag"), url("^category/(?P<category>.*)/feeds/(?P<format>.*)%s$" % _slash, views.blog_post_feed, name="blog_post_feed_category"), url("^category/(?P<category>.*)%s$" % _slash, views.blog_post_list, name="blog_post_list_category"), url("^author/(?P<username>.*)/feeds/(?P<format>.*)%s$" % _slash, views.blog_post_feed, name="blog_post_feed_author"), url("^author/(?P<username>.*)%s$" % _slash, views.blog_post_list, name="blog_post_list_author"), url("^archive/(?P<year>\d{4})/(?P<month>\d{1,2})%s$" % _slash, views.blog_post_list, name="blog_post_list_month"), url("^archive/(?P<year>\d{4})%s$" % _slash, views.blog_post_list, name="blog_post_list_year"), url("^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/" "(?P<slug>.*)%s$" % _slash, views.blog_post_detail, name="blog_post_detail_day"), url("^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<slug>.*)%s$" % _slash, views.blog_post_detail, name="blog_post_detail_month"), url("^(?P<year>\d{4})/(?P<slug>.*)%s$" % _slash, views.blog_post_detail, name="blog_post_detail_year"), url("^(?P<slug>.*)%s$" % _slash, views.blog_post_detail, name="blog_post_detail"), url("^$", views.blog_post_list, name="blog_post_list"), ]
/home/vagrant/.virtualenvs/myproject/local/lib/python2.7/site-packages/mezzanine/pages/urls.py
from __future__ import unicode_literals from django.conf.urls import url from django.conf import settings from mezzanine.pages import page_processors, views page_processors.autodiscover() # Page patterns. urlpatterns = [ url("^admin_page_ordering/$", views.admin_page_ordering, name="admin_page_ordering"), url("^(?P<slug>.*)%s$" % ("/" if settings.APPEND_SLASH else ""), views.page, name="page"), ]
/home/vagrant/.virtualenvs/myproject/local/lib/python2.7/site-packages/cartridge/shop/urls.py
from __future__ import unicode_literals from django.conf.urls import url from mezzanine.conf import settings from cartridge.shop import views _slash = "/" if settings.APPEND_SLASH else "" urlpatterns = [ url("^product/(?P<slug>.*)%s$" % _slash, views.product, name="shop_product"), url("^wishlist%s$" % _slash, views.wishlist, name="shop_wishlist"), url("^cart%s$" % _slash, views.cart, name="shop_cart"), url("^checkout%s$" % _slash, views.checkout_steps, name="shop_checkout"), url("^checkout/complete%s$" % _slash, views.complete, name="shop_complete"), url("^invoice/(?P<order_id>\d+)%s$" % _slash, views.invoice, name="shop_invoice"), url("^invoice/(?P<order_id>\d+)/resend%s$" % _slash, views.invoice_resend_email, name="shop_invoice_resend"), ]
- Mezzanine packages