-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add
djangocms
command to quickly start a project (#7702)
- Loading branch information
Showing
7 changed files
with
316 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: djangocms mysite test | ||
|
||
on: [push, pull_request] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
create-project: | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
django-version: [ | ||
'3.2', '4.2', | ||
] | ||
python-version: ['3.11'] | ||
requirements-file: ['requirements_base.txt'] | ||
os: [ | ||
ubuntu-20.04, | ||
] | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up Python ${{ matrix.python-version }} | ||
|
||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
- name: Create project from template | ||
run: | | ||
sudo apt install gettext gcc -y | ||
python -m venv .venv | ||
source ./.venv/bin/activate | ||
python -m pip install --upgrade pip | ||
pip install -e . | ||
djangocms mysite --noinput |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
""" | ||
Invokes djangocms when the cms module is run as a script. | ||
Example: python -m cms mysite | ||
""" | ||
from cms.management import djangocms | ||
|
||
if __name__ == "__main__": | ||
djangocms.execute_from_command_line() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
#!/usr/bin/env python | ||
import os | ||
import subprocess | ||
import sys | ||
|
||
from django.core.checks.security.base import SECRET_KEY_INSECURE_PREFIX | ||
from django.core.management import CommandError | ||
from django.core.management.templates import TemplateCommand | ||
from django.core.management.utils import get_random_secret_key | ||
|
||
from cms import __version__ as cms_version | ||
|
||
|
||
class Command(TemplateCommand): | ||
help = ( | ||
"Creates a django CMS project directory structure for the given project " | ||
"name in the current directory or optionally in the given directory." | ||
) | ||
missing_args_message = "You must provide a project name." | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
|
||
# Version major.minor | ||
self.major_minor = ".".join(cms_version.split(".")[:2]) | ||
|
||
# Configure formatting | ||
self.HEADING = lambda text: "\n" + self.style.SQL_FIELD(text) | ||
self.COMMAND = self.style.HTTP_SUCCESS | ||
|
||
def add_arguments(self, parser): | ||
super().add_arguments(parser) | ||
parser.add_argument( | ||
"--noinput", | ||
"--no-input", | ||
action="store_false", | ||
dest="interactive", | ||
help=( | ||
"Tells django CMS to NOT prompt the user for input of any kind. " | ||
"Superusers created with --noinput will " | ||
"not be able to log in until they're given a valid password." | ||
), | ||
) | ||
parser.add_argument( | ||
"--username", | ||
help="Specifies the login for the superuser to be created", | ||
) | ||
parser.add_argument("--email", help="Specifies the email for the superuser to be created") | ||
|
||
def get_default_template(self): | ||
return f"https://github.com/django-cms/cms-template/archive/{self.major_minor}.tar.gz" | ||
|
||
def postprocess(self, project, options): | ||
# Go to project dir | ||
self.write_command(f'cd "{project}"') | ||
os.chdir(project) | ||
|
||
# Install requirements | ||
self.install_requirements(project) | ||
|
||
# Create database by running migrations | ||
self.stdout.write(self.HEADING("Run migrations")) | ||
self.run_management_command(["migrate"], capture_output=True) | ||
|
||
# Create superuser (respecting command line arguments) | ||
self.stdout.write(self.HEADING("Create superuser")) | ||
command = ["createsuperuser"] | ||
if options.get("username"): | ||
command.append("--username") | ||
command.append(options.get("username")) | ||
if options.get("email"): | ||
command.append("--email") | ||
command.append(options.get("email")) | ||
if not options["interactive"]: | ||
if "--username" not in command: | ||
command.append("--username") | ||
command.append(os.environ.get("DJANGO_SUPERUSER_USERNAME", "admin")) | ||
if "--email" not in command: | ||
command.append("--email") | ||
command.append(os.environ.get("DJANGO_SUPERUSER_EMAIL", "none@nowhere.com")) | ||
command.append("--noinput") | ||
self.run_management_command(command) | ||
|
||
# Check installation | ||
self.stdout.write(self.HEADING("Check installation")) | ||
self.run_management_command(["cms", "check"], capture_output=True) | ||
|
||
# Display success message | ||
message = f"django CMS {cms_version} installed successfully" | ||
separator = "*" * len(message) | ||
self.stdout.write(self.HEADING(f"{separator}\n{message}\n{separator}")) | ||
self.stdout.write( | ||
f""" | ||
Congratulations! You have successfully installed django CMS, | ||
the lean enterprise content management powered by Django! | ||
Now, to start the development server first go to your newly | ||
created project and then call the runserver management command: | ||
$ {self.style.SUCCESS("cd " + project)} | ||
$ {self.style.SUCCESS("python -m manage runserver")} | ||
Learn more at https://docs.django-cms.org/ | ||
Join the django CMS Slack channel http://www.django-cms.org/slack | ||
Enjoy! | ||
""" | ||
) | ||
|
||
def install_requirements(self, project): | ||
for req_file in ("requirements.txt", "requirements.in"): | ||
requirements = os.path.join(project, req_file) | ||
if os.path.isfile(requirements): | ||
if self.running_in_venv() or os.environ.get("DJANGOCMS_ALLOW_PIP_INSTALL", "False") == "True": | ||
self.stdout.write(self.HEADING(f"Install requirements in {requirements}")) | ||
self.write_command(f'python -m pip install -r "{requirements}"') | ||
result = subprocess.run( | ||
[sys.executable, "-m", "pip", "install", "-r", requirements], | ||
capture_output=True, | ||
) | ||
if result.returncode: | ||
self.stderr.write(self.style.ERROR(result.stderr.decode())) | ||
raise CommandError(f"Failed to install requirements in {requirements}") | ||
break | ||
else: | ||
self.stderr.write( | ||
self.style.ERROR( | ||
"To automatically install requirements for your new django CMS " | ||
"project use this command in an virtual environment." | ||
) | ||
) | ||
raise CommandError("Requirements not installed") | ||
|
||
def run_management_command(self, commands, capture_output=False): | ||
self.write_command("python -m manage " + " ".join(commands)) | ||
result = subprocess.run([sys.executable, "-m", "manage"] + commands, capture_output=capture_output) | ||
if result.returncode: | ||
if capture_output: | ||
self.stderr.write(self.style.ERROR(result.stderr.decode())) | ||
raise CommandError(f"{sys.executable} -m manage {' '.join(commands)} failed.") | ||
|
||
def write_command(self, command): | ||
self.stderr.write(self.COMMAND(command)) | ||
|
||
@staticmethod | ||
def running_in_venv(): | ||
return sys.prefix != sys.base_prefix | ||
|
||
def handle_template(self, template, subdir): | ||
if not template: | ||
template = self.get_default_template() | ||
return super().handle_template(template, subdir) | ||
|
||
def handle(self, **options): | ||
# Capture target and name for postprocessing | ||
name = options.pop("name") | ||
directory = options.pop("directory", None) | ||
# Create a random SECRET_KEY to put it in the main settings. | ||
options["secret_key"] = SECRET_KEY_INSECURE_PREFIX + get_random_secret_key() | ||
|
||
self.stdout.write(self.HEADING("Clone template using django-admin")) | ||
command = ( | ||
f'django-admin startproject "{name}" ' f'--template {options["template"] or self.get_default_template()}' | ||
) | ||
if directory: | ||
command += f' --directory "{directory}"' | ||
self.write_command(command) | ||
|
||
# Run startproject command | ||
super().handle( | ||
"project", name, directory, cms_version=cms_version, cms_docs_version=self.major_minor, **options | ||
) | ||
|
||
if directory is None: | ||
top_dir = os.path.join(os.getcwd(), name) | ||
else: | ||
top_dir = os.path.abspath(os.path.expanduser(directory)) | ||
self.postprocess(top_dir, options) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import os | ||
import sys | ||
|
||
from django.core.management import load_command_class | ||
|
||
|
||
def execute_from_command_line(argv=None): | ||
"""Run the startcmsproject management command.""" | ||
|
||
# Prepare arguments | ||
argv = argv or sys.argv[:] | ||
argv[0] = os.path.basename(argv[0]) | ||
if argv[0] == "__main__.py": | ||
argv[0] = "python -m cms" | ||
|
||
# Find command | ||
command = load_command_class("cms", "startcmsproject") | ||
if argv[1:] == ["--version"]: | ||
from cms import __version__ | ||
sys.stdout.write(__version__ + "\n") | ||
elif argv[1:] == ["--help"]: | ||
command.print_help(argv[0], "") | ||
else: | ||
command.run_from_argv([argv[0], ""] + argv[1:]) # fake "empty" subcommand |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,5 @@ | ||
#!/usr/bin/env python | ||
import os | ||
from setuptools import setup | ||
|
||
from cms import __version__ | ||
from setuptools import find_packages, setup | ||
|
||
|
||
REQUIREMENTS = [ | ||
'Django>=2.2', | ||
'django-classy-tags>=0.7.2', | ||
'django-formtools>=2.1', | ||
'django-treebeard>=4.3', | ||
'django-sekizai>=0.7', | ||
'djangocms-admin-style>=1.2', | ||
'packaging', | ||
'setuptools', | ||
] | ||
|
||
|
||
CLASSIFIERS = [ | ||
'Development Status :: 5 - Production/Stable', | ||
'Environment :: Web Environment', | ||
'Framework :: Django', | ||
'Intended Audience :: Developers', | ||
'License :: OSI Approved :: BSD License', | ||
'Operating System :: OS Independent', | ||
'Programming Language :: Python', | ||
'Programming Language :: Python :: 3', | ||
'Programming Language :: Python :: 3.8', | ||
'Programming Language :: Python :: 3.9', | ||
'Programming Language :: Python :: 3.10', | ||
'Programming Language :: Python :: 3.11', | ||
'Framework :: Django', | ||
'Framework :: Django :: 2.2', | ||
'Framework :: Django :: 3.0', | ||
'Framework :: Django :: 3.1', | ||
'Framework :: Django :: 3.2', | ||
'Framework :: Django :: 4.0', | ||
'Framework :: Django :: 4.1', | ||
'Framework :: Django :: 4.2', | ||
'Framework :: Django :: 5.0', | ||
'Topic :: Internet :: WWW/HTTP', | ||
'Topic :: Internet :: WWW/HTTP :: Dynamic Content', | ||
'Topic :: Software Development', | ||
'Topic :: Software Development :: Libraries', | ||
'Topic :: Software Development :: Libraries :: Application Frameworks', | ||
] | ||
|
||
|
||
setup( | ||
name='django-cms', | ||
version=__version__, | ||
author='Django CMS Association and contributors', | ||
author_email='info@django-cms.org', | ||
url='https://www.django-cms.org/', | ||
license='BSD-3-Clause', | ||
description='Lean enterprise content management powered by Django.', | ||
long_description=open(os.path.join(os.path.dirname(__file__), 'README.rst')).read(), | ||
packages=find_packages(exclude=['project', 'project.*']), | ||
include_package_data=True, | ||
zip_safe=False, | ||
install_requires=REQUIREMENTS, | ||
classifiers=CLASSIFIERS, | ||
test_suite='runtests.main', | ||
) | ||
setup() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
-e . | ||
argparse | ||
coverage<5 | ||
dj-database-url | ||
|