├── .circleci
└── config.yml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── assets
├── django-bulma-logo.png
└── django-bulma-logo.svg
├── bulma
├── __init__.py
├── apps.py
├── management
│ ├── __init__.py
│ └── commands
│ │ ├── __init__.py
│ │ ├── bulma.py
│ │ └── copy_bulma_static_into_project.py
├── static
│ └── bulma
│ │ ├── css
│ │ ├── style.css
│ │ ├── style.css.map
│ │ └── style.min.css
│ │ └── sass
│ │ ├── .gitignore
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ └── style.sass
├── templates
│ ├── _layouts
│ │ └── one-column-center.html
│ ├── base.html
│ ├── bulma
│ │ ├── base.html
│ │ └── forms
│ │ │ ├── field.html
│ │ │ ├── form.html
│ │ │ └── formset.html
│ ├── pagination.html
│ └── registration
│ │ ├── base.html
│ │ ├── logged_out.html
│ │ ├── login.html
│ │ ├── password_change_done.html
│ │ ├── password_change_form.html
│ │ ├── password_reset_complete.html
│ │ ├── password_reset_confirm.html
│ │ ├── password_reset_done.html
│ │ ├── password_reset_email.html
│ │ └── password_reset_form.html
├── templatetags
│ ├── __init__.py
│ └── bulma_tags.py
└── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── forms.py
│ ├── test_commands.py
│ ├── test_inputs.py
│ ├── test_templates.py
│ └── utils.py
├── poetry.lock
├── pyproject.toml
├── showcase
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20180226_1645.py
│ └── __init__.py
├── models.py
├── templates
│ └── showcase
│ │ ├── form.html
│ │ └── paginated_list.html
├── urls.py
└── views.py
├── test_project
├── __init__.py
├── manage.py
├── settings.py
├── templates
│ ├── base.html
│ └── home.html
├── urls.py
└── wsgi.py
└── tox.ini
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Python CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-python/ for more details
4 | #
5 | version: 2
6 |
7 | shared: &shared
8 | steps:
9 | - checkout
10 |
11 | - run:
12 | name: install node & npm
13 | command: |
14 | sudo apt-get -yqq --allow-releaseinfo-change update && sudo apt-get install -yqq nodejs npm
15 |
16 | # Download and cache dependencies
17 | - restore_cache:
18 | keys:
19 | - v1-dependencies-{{ checksum "poetry.lock" }}
20 | # fallback to using the latest cache if no exact match is found
21 | - v1-dependencies-
22 |
23 | - run:
24 | name: install dependencies
25 | command: |
26 | poetry install
27 |
28 | - save_cache:
29 | key: deps-{{ checksum "poetry.lock" }}
30 | paths:
31 | - /home/circleci/.cache/pypoetry/virtualenvs
32 |
33 | - run:
34 | name: run tests
35 | command: |
36 | poetry run tox
37 |
38 | - store_artifacts:
39 | path: test-reports
40 | destination: test-reports
41 |
42 | jobs:
43 | "python-3.7":
44 | <<: *shared
45 | docker:
46 | # specify the version you desire here
47 | # use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
48 | # check all Python images here: https://circleci.com/docs/2.0/circleci-images/#python
49 | - image: circleci/python:3.7.12-buster
50 | "python-3.8":
51 | <<: *shared
52 | docker:
53 | # specify the version you desire here
54 | # use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
55 | # check all Python images here: https://circleci.com/docs/2.0/circleci-images/#python
56 | - image: circleci/python:3.8.9-buster
57 | "python-3.9":
58 | <<: *shared
59 | docker:
60 | # specify the version you desire here
61 | # use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
62 | # check all Python images here: https://circleci.com/docs/2.0/circleci-images/#python
63 | - image: circleci/python:3.9.7-buster
64 |
65 | workflows:
66 | version: 2
67 | build:
68 | jobs:
69 | - "python-3.7"
70 | - "python-3.8"
71 | - "python-3.9"
72 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Python ###
2 | # Byte-compiled / optimized / DLL files
3 | __pycache__/
4 | *.py[cod]
5 | *$py.class
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | env/
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *,cover
48 | .hypothesis/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 |
58 | # Flask stuff:
59 | instance/
60 | .webassets-cache
61 |
62 | # Scrapy stuff:
63 | .scrapy
64 |
65 | # Sphinx documentation
66 | docs/_build/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # Jupyter Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # celery beat schedule file
78 | celerybeat-schedule
79 |
80 | # SageMath parsed files
81 | *.sage.py
82 |
83 | # dotenv
84 | .env
85 |
86 | # virtualenv
87 | .venv
88 | venv/
89 | ENV/
90 |
91 | # Spyder project settings
92 | .spyderproject
93 | .spyproject
94 |
95 | # Rope project settings
96 | .ropeproject
97 |
98 | # mkdocs documentation
99 | /site
100 |
101 | # End of https://www.gitignore.io/api/python
102 |
103 | # Created by https://www.gitignore.io/api/pycharm
104 |
105 | ### PyCharm ###
106 | .idea
107 |
108 | # Created by https://www.gitignore.io/api/macos
109 |
110 | ### macOS ###
111 | *.DS_Store
112 | .AppleDouble
113 | .LSOverride
114 |
115 | # Icon must end with two \r
116 | Icon
117 |
118 | # Thumbnails
119 | ._*
120 |
121 | # Files that might appear in the root of a volume
122 | .DocumentRevisions-V100
123 | .fseventsd
124 | .Spotlight-V100
125 | .TemporaryItems
126 | .Trashes
127 | .VolumeIcon.icns
128 | .com.apple.timemachine.donotpresent
129 |
130 | # Directories potentially created on remote AFP share
131 | .AppleDB
132 | .AppleDesktop
133 | Network Trash Folder
134 | Temporary Items
135 | .apdisk
136 |
137 | # End of https://www.gitignore.io/api/macos
138 |
139 | # Example project
140 | demo/static/bulma
141 | bulma/tests/static
142 | demo/memory
143 |
144 | node_modules
145 |
146 | # version file is generated by setuptools_scm
147 | bulma/version.py
148 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Tim Kamanin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | update_bulma:
2 | cd ./bulma/static/bulma/sass && rm -f package-lock.json && npm i && npm run build && rm -rf ./node_modules
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A Bulma Theme for Django Projects
2 |
3 | 
4 |
5 | A Django base theme based on Bulma ([bulma.io](https://bulma.io/)). Bulma is a modern CSS framework based on Flexbox.
6 |
7 | *** work in progress ***
8 |
9 | ## Installation
10 |
11 | 1. Install the python package django-bulma from pip
12 |
13 | ``pip install django-bulma``
14 |
15 | Alternatively, you can install download or clone this repo and call ``pip install -e .``.
16 |
17 | 2. Add to INSTALLED_APPS in your **settings.py**:
18 |
19 | `'bulma',`
20 |
21 | 3. If you want to use the provided base template, extend from **bulma/base.html**:
22 |
23 | ```
24 | {% extends 'bulma/base.html' %}
25 |
26 | {% block title %}Bulma Site{% endblock %}
27 |
28 | {% block content %}
29 | Content goes here...
30 | {% endblock content %}
31 |
32 | ```
33 |
34 | 4. If you want to customize bulma sass and your own components:
35 |
36 | 4.1 Copy bulma static files into your project's **STATIC_ROOT**:
37 |
38 | ```
39 | python manage.py copy_bulma_static_into_project
40 | ```
41 | You should see **bulma** dir appeared in your **STATIC_ROOT**. It contains
42 | two dirs:
43 | * **sass** - this is the place where you can put your own sass code and customize
44 | bulma variables
45 | * **css** - this is where compiled sass output goes, you should link this file
46 | in your base.html
47 |
48 | 4.2 Install npm packages for sass compilation to work:
49 |
50 | ```
51 | python manage.py bulma install
52 | ```
53 |
54 | 4.3 Start sass watch mode:
55 | ```
56 | python manage.py bulma start
57 | ```
58 |
59 | 5. For forms, in your templates, load the `bulma_tags` library and use the `|bulma` filters:
60 |
61 | ##### Example template
62 |
63 | ```django
64 |
65 | {% load bulma_tags %}
66 |
67 | {# Display a form #}
68 |
69 |
{% trans "Your username and password didn't match. Please try again." %}
8 | {% endif %}
9 |
10 | {% trans "Your password has been set. You may go ahead and log in now." %}
10 |
11 | {% trans "Please enter your new password twice so we can verify you typed it in correctly." %}
10 | {% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}
16 | {% endif %}
17 |
18 | {% endblock %}
--------------------------------------------------------------------------------
/bulma/templates/registration/password_reset_done.html:
--------------------------------------------------------------------------------
1 | {% extends "registration/base.html" %}
2 | {% load i18n %}
3 |
4 | {% block title %}{{ title }}{% endblock %}
5 | {% block content_title %}{% trans "Forgotten your password? Enter your email address below, and we'll email instructions for setting a new one." %}
8 |
23 | {% csrf_token %}
24 | {{ form|bulma }}
25 |
Submit
26 |
27 | {% endblock %}
28 | """, context={
29 | 'form': form
30 | }
31 | )
32 |
33 |
34 | def get_dom(html):
35 | return BeautifulSoup(html, 'html.parser')
36 |
37 |
38 | def element_has_all_attributes(element, attributes):
39 | for attribute_name, attribute_value in attributes.items():
40 | assert element.has_attr(attribute_name) is True
41 | print(element.get(attribute_name))
42 | assert element.get(attribute_name) == attribute_value, f'Element {element} has attribute "{attribute_name}" with value {attribute_value}'
43 | #return False
44 | #return True
45 |
46 |
47 | def element_has_attribute(element, attribute_name, attribute_value):
48 | return element.has_attr(attribute_name) and element.get(attribute_name) == attribute_value
49 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
2 |
3 | [[package]]
4 | name = "asgiref"
5 | version = "3.7.2"
6 | description = "ASGI specs, helper code, and adapters"
7 | optional = false
8 | python-versions = ">=3.7"
9 | files = [
10 | {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
11 | {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
12 | ]
13 |
14 | [package.dependencies]
15 | typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
16 |
17 | [package.extras]
18 | tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
19 |
20 | [[package]]
21 | name = "atomicwrites"
22 | version = "1.4.1"
23 | description = "Atomic file writes."
24 | optional = false
25 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
26 | files = [
27 | {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
28 | ]
29 |
30 | [[package]]
31 | name = "attrs"
32 | version = "23.2.0"
33 | description = "Classes Without Boilerplate"
34 | optional = false
35 | python-versions = ">=3.7"
36 | files = [
37 | {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
38 | {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
39 | ]
40 |
41 | [package.dependencies]
42 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
43 |
44 | [package.extras]
45 | cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
46 | dev = ["attrs[tests]", "pre-commit"]
47 | docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
48 | tests = ["attrs[tests-no-zope]", "zope-interface"]
49 | tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
50 | tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
51 |
52 | [[package]]
53 | name = "beautifulsoup4"
54 | version = "4.12.3"
55 | description = "Screen-scraping library"
56 | optional = false
57 | python-versions = ">=3.6.0"
58 | files = [
59 | {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"},
60 | {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"},
61 | ]
62 |
63 | [package.dependencies]
64 | soupsieve = ">1.2"
65 |
66 | [package.extras]
67 | cchardet = ["cchardet"]
68 | chardet = ["chardet"]
69 | charset-normalizer = ["charset-normalizer"]
70 | html5lib = ["html5lib"]
71 | lxml = ["lxml"]
72 |
73 | [[package]]
74 | name = "colorama"
75 | version = "0.4.6"
76 | description = "Cross-platform colored terminal text."
77 | optional = false
78 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
79 | files = [
80 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
81 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
82 | ]
83 |
84 | [[package]]
85 | name = "distlib"
86 | version = "0.3.8"
87 | description = "Distribution utilities"
88 | optional = false
89 | python-versions = "*"
90 | files = [
91 | {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
92 | {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
93 | ]
94 |
95 | [[package]]
96 | name = "django"
97 | version = "3.2.25"
98 | description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
99 | optional = false
100 | python-versions = ">=3.6"
101 | files = [
102 | {file = "Django-3.2.25-py3-none-any.whl", hash = "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38"},
103 | {file = "Django-3.2.25.tar.gz", hash = "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777"},
104 | ]
105 |
106 | [package.dependencies]
107 | asgiref = ">=3.3.2,<4"
108 | pytz = "*"
109 | sqlparse = ">=0.2.2"
110 |
111 | [package.extras]
112 | argon2 = ["argon2-cffi (>=19.1.0)"]
113 | bcrypt = ["bcrypt"]
114 |
115 | [[package]]
116 | name = "filelock"
117 | version = "3.12.2"
118 | description = "A platform independent file lock."
119 | optional = false
120 | python-versions = ">=3.7"
121 | files = [
122 | {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"},
123 | {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"},
124 | ]
125 |
126 | [package.extras]
127 | docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
128 | testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
129 |
130 | [[package]]
131 | name = "importlib-metadata"
132 | version = "6.7.0"
133 | description = "Read metadata from Python packages"
134 | optional = false
135 | python-versions = ">=3.7"
136 | files = [
137 | {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"},
138 | {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"},
139 | ]
140 |
141 | [package.dependencies]
142 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
143 | zipp = ">=0.5"
144 |
145 | [package.extras]
146 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
147 | perf = ["ipython"]
148 | testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
149 |
150 | [[package]]
151 | name = "more-itertools"
152 | version = "9.1.0"
153 | description = "More routines for operating on iterables, beyond itertools"
154 | optional = false
155 | python-versions = ">=3.7"
156 | files = [
157 | {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"},
158 | {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"},
159 | ]
160 |
161 | [[package]]
162 | name = "packaging"
163 | version = "24.0"
164 | description = "Core utilities for Python packages"
165 | optional = false
166 | python-versions = ">=3.7"
167 | files = [
168 | {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
169 | {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
170 | ]
171 |
172 | [[package]]
173 | name = "platformdirs"
174 | version = "4.0.0"
175 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
176 | optional = false
177 | python-versions = ">=3.7"
178 | files = [
179 | {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"},
180 | {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"},
181 | ]
182 |
183 | [package.dependencies]
184 | typing-extensions = {version = ">=4.7.1", markers = "python_version < \"3.8\""}
185 |
186 | [package.extras]
187 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
188 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
189 |
190 | [[package]]
191 | name = "pluggy"
192 | version = "0.13.1"
193 | description = "plugin and hook calling mechanisms for python"
194 | optional = false
195 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
196 | files = [
197 | {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
198 | {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
199 | ]
200 |
201 | [package.dependencies]
202 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
203 |
204 | [package.extras]
205 | dev = ["pre-commit", "tox"]
206 |
207 | [[package]]
208 | name = "py"
209 | version = "1.11.0"
210 | description = "library with cross-python path, ini-parsing, io, code, log facilities"
211 | optional = false
212 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
213 | files = [
214 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
215 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
216 | ]
217 |
218 | [[package]]
219 | name = "pytest"
220 | version = "5.4.3"
221 | description = "pytest: simple powerful testing with Python"
222 | optional = false
223 | python-versions = ">=3.5"
224 | files = [
225 | {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
226 | {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
227 | ]
228 |
229 | [package.dependencies]
230 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
231 | attrs = ">=17.4.0"
232 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
233 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
234 | more-itertools = ">=4.0.0"
235 | packaging = "*"
236 | pluggy = ">=0.12,<1.0"
237 | py = ">=1.5.0"
238 | wcwidth = "*"
239 |
240 | [package.extras]
241 | checkqa-mypy = ["mypy (==v0.761)"]
242 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
243 |
244 | [[package]]
245 | name = "pytest-django"
246 | version = "3.10.0"
247 | description = "A Django plugin for pytest."
248 | optional = false
249 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
250 | files = [
251 | {file = "pytest-django-3.10.0.tar.gz", hash = "sha256:4de6dbd077ed8606616958f77655fed0d5e3ee45159475671c7fa67596c6dba6"},
252 | {file = "pytest_django-3.10.0-py2.py3-none-any.whl", hash = "sha256:c33e3d3da14d8409b125d825d4e74da17bb252191bf6fc3da6856e27a8b73ea4"},
253 | ]
254 |
255 | [package.dependencies]
256 | pytest = ">=3.6"
257 |
258 | [package.extras]
259 | docs = ["sphinx", "sphinx-rtd-theme"]
260 | testing = ["Django", "django-configurations (>=2.0)", "six"]
261 |
262 | [[package]]
263 | name = "pytz"
264 | version = "2024.1"
265 | description = "World timezone definitions, modern and historical"
266 | optional = false
267 | python-versions = "*"
268 | files = [
269 | {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
270 | {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
271 | ]
272 |
273 | [[package]]
274 | name = "six"
275 | version = "1.16.0"
276 | description = "Python 2 and 3 compatibility utilities"
277 | optional = false
278 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
279 | files = [
280 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
281 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
282 | ]
283 |
284 | [[package]]
285 | name = "soupsieve"
286 | version = "2.4.1"
287 | description = "A modern CSS selector implementation for Beautiful Soup."
288 | optional = false
289 | python-versions = ">=3.7"
290 | files = [
291 | {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"},
292 | {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"},
293 | ]
294 |
295 | [[package]]
296 | name = "sqlparse"
297 | version = "0.4.4"
298 | description = "A non-validating SQL parser."
299 | optional = false
300 | python-versions = ">=3.5"
301 | files = [
302 | {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
303 | {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
304 | ]
305 |
306 | [package.extras]
307 | dev = ["build", "flake8"]
308 | doc = ["sphinx"]
309 | test = ["pytest", "pytest-cov"]
310 |
311 | [[package]]
312 | name = "tomli"
313 | version = "2.0.1"
314 | description = "A lil' TOML parser"
315 | optional = false
316 | python-versions = ">=3.7"
317 | files = [
318 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
319 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
320 | ]
321 |
322 | [[package]]
323 | name = "tox"
324 | version = "3.28.0"
325 | description = "tox is a generic virtualenv management and test command line tool"
326 | optional = false
327 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
328 | files = [
329 | {file = "tox-3.28.0-py2.py3-none-any.whl", hash = "sha256:57b5ab7e8bb3074edc3c0c0b4b192a4f3799d3723b2c5b76f1fa9f2d40316eea"},
330 | {file = "tox-3.28.0.tar.gz", hash = "sha256:d0d28f3fe6d6d7195c27f8b054c3e99d5451952b54abdae673b71609a581f640"},
331 | ]
332 |
333 | [package.dependencies]
334 | colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""}
335 | filelock = ">=3.0.0"
336 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
337 | packaging = ">=14"
338 | pluggy = ">=0.12.0"
339 | py = ">=1.4.17"
340 | six = ">=1.14.0"
341 | tomli = {version = ">=2.0.1", markers = "python_version >= \"3.7\" and python_version < \"3.11\""}
342 | virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7"
343 |
344 | [package.extras]
345 | docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"]
346 | testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"]
347 |
348 | [[package]]
349 | name = "typing-extensions"
350 | version = "4.7.1"
351 | description = "Backported and Experimental Type Hints for Python 3.7+"
352 | optional = false
353 | python-versions = ">=3.7"
354 | files = [
355 | {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
356 | {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
357 | ]
358 |
359 | [[package]]
360 | name = "virtualenv"
361 | version = "20.26.2"
362 | description = "Virtual Python Environment builder"
363 | optional = false
364 | python-versions = ">=3.7"
365 | files = [
366 | {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"},
367 | {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"},
368 | ]
369 |
370 | [package.dependencies]
371 | distlib = ">=0.3.7,<1"
372 | filelock = ">=3.12.2,<4"
373 | importlib-metadata = {version = ">=6.6", markers = "python_version < \"3.8\""}
374 | platformdirs = ">=3.9.1,<5"
375 |
376 | [package.extras]
377 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
378 | test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
379 |
380 | [[package]]
381 | name = "wcwidth"
382 | version = "0.2.13"
383 | description = "Measures the displayed width of unicode strings in a terminal"
384 | optional = false
385 | python-versions = "*"
386 | files = [
387 | {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
388 | {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
389 | ]
390 |
391 | [[package]]
392 | name = "zipp"
393 | version = "3.15.0"
394 | description = "Backport of pathlib-compatible object wrapper for zip files"
395 | optional = false
396 | python-versions = ">=3.7"
397 | files = [
398 | {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
399 | {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
400 | ]
401 |
402 | [package.extras]
403 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
404 | testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
405 |
406 | [metadata]
407 | lock-version = "2.0"
408 | python-versions = ">=3.7"
409 | content-hash = "8da55925859b407644ea7f8375efc71d197c55922d76bf8af90e85b80fc3e6e0"
410 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "django-bulma"
3 | version = "0.9.0"
4 | description = "Bulma CSS Framework for Django projects"
5 | authors = ["Tim Kamanin
"]
6 | license = "MIT"
7 | readme = "README.md"
8 | homepage = "https://timonweb.com"
9 | keywords = ["django", "css", "bulma", "theme"]
10 | classifiers = [
11 | "Development Status :: 4 - Beta",
12 | "Intended Audience :: Developers",
13 | "License :: OSI Approved :: Apache Software License",
14 | "Programming Language :: Python :: 3.7",
15 | "Programming Language :: Python :: 3.8",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Operating System :: OS Independent",
20 | "Topic :: Software Development :: Libraries",
21 | "Topic :: Utilities",
22 | "Environment :: Web Environment",
23 | "Framework :: Django"
24 | ]
25 | packages = [
26 | { include = "bulma" }
27 | ]
28 |
29 | [tool.poetry.dependencies]
30 | python = ">=3.7"
31 | django = ">=2.2"
32 |
33 | [tool.poetry.dev-dependencies]
34 | pytest-django = "^3.8.0"
35 | pytest = "^5.3.4"
36 | tox = "^3.14.3"
37 | beautifulsoup4 = "^4.8.2"
38 |
39 | [build-system]
40 | requires = ["poetry>=0.12"]
41 | build-backend = "poetry.masonry.api"
42 |
--------------------------------------------------------------------------------
/showcase/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timonweb/django-bulma/15836cfd5be0d63d9be77ddf378d3253a872498d/showcase/__init__.py
--------------------------------------------------------------------------------
/showcase/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/showcase/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ShowcaseConfig(AppConfig):
5 | name = 'showcase'
6 |
--------------------------------------------------------------------------------
/showcase/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 |
3 | COLOR_CHOICES = (
4 | ('red', 'Red'),
5 | ('green', 'Green'),
6 | ('blue', 'Blue')
7 | )
8 |
9 |
10 | class FormExample(forms.Form):
11 | text = forms.CharField()
12 | email = forms.EmailField()
13 | number = forms.CharField(widget=forms.NumberInput())
14 | url = forms.CharField(widget=forms.URLInput())
15 | password = forms.CharField(widget=forms.PasswordInput())
16 | select = forms.ChoiceField(choices=COLOR_CHOICES)
17 | multi_select = forms.MultipleChoiceField(choices=COLOR_CHOICES)
18 | textarea = forms.CharField(widget=forms.Textarea())
19 | checkbox = forms.BooleanField()
20 | checkboxes = forms.MultipleChoiceField(
21 | choices=COLOR_CHOICES,
22 | widget=forms.CheckboxSelectMultiple()
23 | )
24 | radios = forms.ChoiceField(
25 | choices=COLOR_CHOICES,
26 | widget=forms.RadioSelect()
27 | )
28 | file = forms.FileField(required=True)
29 |
--------------------------------------------------------------------------------
/showcase/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.6 on 2018-02-26 16:53
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Task',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('name', models.CharField(max_length=128)),
21 | ('done', models.BooleanField(default=False)),
22 | ],
23 | ),
24 | ]
25 |
--------------------------------------------------------------------------------
/showcase/migrations/0002_auto_20180226_1645.py:
--------------------------------------------------------------------------------
1 | import random
2 | from django.db import migrations
3 |
4 |
5 | def create_tasks(apps, schema_editor):
6 | Task = apps.get_model('showcase', 'Task')
7 | for number in range(1, 51):
8 | task = Task(
9 | name='Boring task name #{}'.format(number),
10 | done=random.randint(0, 1)
11 | )
12 | task.save()
13 |
14 |
15 | def delete_tasks(apps, schema_editor):
16 | Task = apps.get_model('showcase', 'Task')
17 | Task.objects.all().delete()
18 |
19 |
20 | class Migration(migrations.Migration):
21 |
22 | dependencies = [
23 | ('showcase', '0001_initial'),
24 | ]
25 |
26 | operations = [
27 | migrations.RunPython(create_tasks, delete_tasks),
28 | ]
29 |
--------------------------------------------------------------------------------
/showcase/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timonweb/django-bulma/15836cfd5be0d63d9be77ddf378d3253a872498d/showcase/migrations/__init__.py
--------------------------------------------------------------------------------
/showcase/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | class Task(models.Model):
5 | name = models.CharField(max_length=128)
6 | done = models.BooleanField(default=False)
7 |
8 |
--------------------------------------------------------------------------------
/showcase/templates/showcase/form.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% load bulma_tags %}
3 |
4 | {% block content %}
5 |
10 | {% endblock %}
--------------------------------------------------------------------------------
/showcase/templates/showcase/paginated_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block content %}
4 |
5 |
6 |
7 | Task
8 | Done?
9 |
10 |
11 |
12 | {% for task in object_list %}
13 |
14 | {{ task.name }}
15 |
16 |
17 |
18 |
19 |
20 | {% endfor %}
21 |
22 |
23 | {% include 'pagination.html' %}
24 | {% endblock %}
--------------------------------------------------------------------------------
/showcase/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 |
3 | from . import views
4 |
5 | app_name = 'showcase'
6 | urlpatterns = [
7 | url(r'^list/$', views.PaginatedList.as_view(), name='paginated_list'),
8 | url(r'^form/$', views.FormExampleView.as_view(), name='form'),
9 | ]
10 |
--------------------------------------------------------------------------------
/showcase/views.py:
--------------------------------------------------------------------------------
1 | from django.views.generic import ListView, FormView
2 |
3 | from .forms import FormExample
4 | from .models import Task
5 |
6 |
7 | class PaginatedList(ListView):
8 | template_name = 'showcase/paginated_list.html'
9 | model = Task
10 | paginate_by = 20
11 |
12 |
13 | class FormExampleView(FormView):
14 | template_name = 'showcase/form.html'
15 | form_class = FormExample
16 |
--------------------------------------------------------------------------------
/test_project/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timonweb/django-bulma/15836cfd5be0d63d9be77ddf378d3253a872498d/test_project/__init__.py
--------------------------------------------------------------------------------
/test_project/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
7 |
8 | from django.core.management import execute_from_command_line
9 | from django.conf import settings
10 | settings.DEBUG = True
11 |
12 | execute_from_command_line(sys.argv)
--------------------------------------------------------------------------------
/test_project/settings.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | ALLOWED_HOSTS = ['*']
4 |
5 | BASE_DIR = os.path.dirname(__file__)
6 |
7 | SECRET_KEY = "007"
8 |
9 | INSTALLED_APPS = [
10 | # Default Django apps
11 | "django.contrib.admin",
12 | "django.contrib.auth",
13 | "django.contrib.contenttypes",
14 | "django.contrib.sessions",
15 | "django.contrib.messages",
16 | "django.contrib.staticfiles",
17 |
18 | "bulma",
19 | "showcase"
20 | ]
21 |
22 | ROOT_URLCONF = "test_project.urls"
23 |
24 | DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}
25 |
26 | MIDDLEWARE = (
27 | "django.contrib.sessions.middleware.SessionMiddleware",
28 | "django.contrib.auth.middleware.AuthenticationMiddleware", # required for django.contrib.admin
29 | "django.contrib.messages.middleware.MessageMiddleware", # required for django.contrib.admin
30 | )
31 |
32 | STATIC_URL = "/static/"
33 |
34 | STATICFILES_DIRS = [
35 | os.path.join(BASE_DIR, 'static')
36 | ]
37 |
38 | TEMPLATES = [
39 | {
40 | "BACKEND": "django.template.backends.django.DjangoTemplates",
41 | 'DIRS': [
42 | os.path.join(BASE_DIR, 'templates')
43 | ],
44 | "APP_DIRS": True,
45 | "OPTIONS": {
46 | "context_processors": [
47 | "django.contrib.auth.context_processors.auth",
48 | "django.template.context_processors.debug",
49 | "django.template.context_processors.i18n",
50 | "django.template.context_processors.media",
51 | "django.template.context_processors.static",
52 | "django.template.context_processors.tz",
53 | "django.contrib.messages.context_processors.messages",
54 | ]
55 | },
56 | }
57 | ]
58 |
--------------------------------------------------------------------------------
/test_project/templates/base.html:
--------------------------------------------------------------------------------
1 | {% extends 'bulma/base.html' %}
--------------------------------------------------------------------------------
/test_project/templates/home.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block content %}
4 |
5 |
6 |
7 | Hello World
8 |
9 |
10 | My first website with Django-Bulma !
11 |
12 |
13 |
Demo pages:
14 |
18 |
19 |
20 |
21 | {% endblock %}
--------------------------------------------------------------------------------
/test_project/urls.py:
--------------------------------------------------------------------------------
1 | """example URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.conf.urls import url, include
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
15 | """
16 | from django.conf.urls import url, include
17 | from django.contrib import admin
18 | from django.views.generic import TemplateView
19 | from django.contrib.auth.views import LoginView
20 |
21 | urlpatterns = [
22 | url(r'^$', TemplateView.as_view(template_name='home.html')),
23 | url(r'^login/$', LoginView.as_view(), name='login'),
24 | url(r'^admin/', admin.site.urls),
25 | url(r'^showcase/', include('showcase.urls', namespace='showcase')),
26 | ]
27 |
--------------------------------------------------------------------------------
/test_project/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for example project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | DJANGO_SETTINGS_MODULE = test_project.settings
3 | python_files = tests.py test_*.py *_tests.py
4 | ignore = 'node_modules'
5 |
6 | [tox]
7 | isolated_build = True
8 | envlist = django{22,30,32}
9 |
10 | [tox:.package]
11 | # note tox will use the same python version as under what tox is installed to package
12 | # so unless this is python 3 you can require a given python version for the packaging
13 | # environment via the basepython key
14 | basepython = python3
15 |
16 | [testenv]
17 | commands = pytest {posargs}
18 | deps =
19 | django22: Django>=2.2.9,<3.0
20 | django30: Django>=3.0,<3.1
21 | django32: Django>=3.2,<3.3
22 | setenv =
23 | DJANGO_SETTINGS_MODULE = test_project.settings
24 | PYTHONPATH = {toxinidir}
25 |
--------------------------------------------------------------------------------