Skip to content

Commit

Permalink
feat: vs code devcontainer (#319)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasvinclav committed Mar 18, 2024
1 parent 6cf1b7c commit 788eca2
Show file tree
Hide file tree
Showing 17 changed files with 357 additions and 36 deletions.
15 changes: 15 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM mcr.microsoft.com/devcontainers/python:3.12

ENV PYTHONUNBUFFERED 1

RUN pip install poetry

RUN poetry config virtualenvs.create false

COPY poetry.lock pyproject.toml /app/

WORKDIR /app

RUN poetry install --no-root

EXPOSE 8000
1 change: 1 addition & 0 deletions .devcontainer/backend.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SECRET_KEY=changeme
32 changes: 32 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"service": "unfold",
"name": "Unfold",
"dockerComposeFile": ["docker-compose.yml"],
"overrideCommand": true,
"workspaceFolder": "/app",
"forwardPorts": [8000],
"postCreateCommand": "python manage.py migrate",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "latest"
}
},
"customizations": {
"vscode": {
"settings": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
}
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"batisteo.vscode-django",
"tamasfe.even-better-toml",
"charliermarsh.ruff",
"bradlc.vscode-tailwindcss"
]
}
}
}
12 changes: 12 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: "3.4"

services:
unfold:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/app
- ../src/unfold:/usr/local/lib/python3.12/site-packages/unfold
env_file:
- backend.env
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ __pycache__
venv
node_modules
dist/
*.sqlite3
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
- **Colors:** possibility to override default color scheme
- **Third party packages:** default support for multiple popular applications
- **Environment label**: distinguish between environments by displaying a label
- **VS Code**: project configuration and development container is included

## Table of contents <!-- omit from toc -->

Expand Down Expand Up @@ -70,6 +71,9 @@ Did you decide to start using Unfold but you don't have time to make the switch
- [Pre-commit](#pre-commit)
- [Poetry configuration](#poetry-configuration)
- [Compiling Tailwind](#compiling-tailwind)
- [Using VS Code with containers](#using-vs-code-with-containers)
- [Development server](#development-server)
- [Compiling Tailwind in devcontainer](#compiling-tailwind-in-devcontainer)
- [Credits](#credits)

## Installation
Expand Down Expand Up @@ -965,6 +969,7 @@ Before adding any source code, it is recommended to have pre-commit installed on
pip install pre-commit
pre-commit install
pre-commit install --hook-type commit-msg
pre-commit run --all-files # Check if everything is okay
```

### Poetry configuration
Expand Down Expand Up @@ -992,6 +997,20 @@ Some components like datepickers, calendars or selectors in admin was not possib

**Note:** most of the custom styles located in style.css are created via `@apply some-tailwind-class;` as is not possible to manually add CSS class to element which are for example created via jQuery.

### Using VS Code with containers

Unfold already contains prepared support for VS Code development. After cloning the project locally, open the main folder in VS Code (in terminal `code .`). Immediately, you would see a message from VS Code **Folder contains a Dev Container configuration file. Reopen folder to develop in a container** which will inform you that the support for containers is prepared. Confirm the message by clicking on **Reopen in Container**. If the message is not there, you can still manually open the project in a container by running the command **Dev Containers: Reopen in Container**.

#### Development server

Now the VS Code will build an image and install Python dependencies. After successful installation is completed, VS Code will spin a container and from now it is possible to directly develop in the container. Unfold contains an example development application with the basic Unfold configuration available under `tests/server`. Run `python manage.py runserver` within a `tests/server` folder to start a development Django server. Note that you have to run the command from VS Code terminal which is already connected to the running container.

**Note:** this is not a production ready server. Use it just for running tests or developing features & fixes.

#### Compiling Tailwind in devcontainer

The container has already a node preinstalled so it is possible to compile a new CSS. Open the terminal and run `npm install` which will install all dependencies and will create `node_modules` folder. Now, you can run npm commands for Tailwind as described in the previous chapter.

## Credits

- [TailwindCSS](https://tailwindcss.com/) - CSS framework
Expand Down
29 changes: 9 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,8 @@ readme = "README.md"
authors = []
homepage = "https://unfoldadmin.com"
repository = "https://github.com/unfoldadmin/django-unfold"
packages = [
{ include = "unfold", from = "src" },
]
keywords = [
"django",
"admin",
"tailwind",
"theme",
]
packages = [{ include = "unfold", from = "src" }]
keywords = ["django", "admin", "tailwind", "theme"]
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
Expand All @@ -39,7 +32,6 @@ pytest-django = "^4.5.2"
tox = "^4.5.2"



[tool.poetry.group.dev.dependencies]
python-semantic-release = "^8.7.0"

Expand All @@ -56,23 +48,19 @@ select = [
"UP", # pyupgrade
]
ignore = [
"E501", # line too long, handled by black
"B905", # zip() without strict=True
"C901", # too complex
"E501", # line too long, handled by black
"B905", # zip() without strict=True
"C901", # too complex
]

[tool.semantic_release]
tag_format = "{version}"
major_on_zero = true
version_toml = [
"pyproject.toml:tool.poetry.version"
]
version_toml = ["pyproject.toml:tool.poetry.version"]

[tool.semantic_release.changelog]
template_dir = ".github/templates"
exclude_commit_patterns = [
"chore: version bump"
]
exclude_commit_patterns = ["chore: version bump"]

[tool.semantic_release.changelog.environment]
trim_blocks = true
Expand All @@ -85,8 +73,9 @@ upload_to_vcs_release = false
addopts = """\
--strict-config
--strict-markers
--ds=tests.settings
--ds=example.settings
"""
pythonpath = "tests/server"
django_find_project = false

[build-system]
Expand Down
Empty file.
22 changes: 22 additions & 0 deletions tests/server/example/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import Group
from unfold.admin import ModelAdmin
from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm

from .models import User

admin.site.unregister(Group)


@admin.register(User)
class UserAdmin(BaseUserAdmin, ModelAdmin):
form = UserChangeForm
add_form = UserCreationForm
change_password_form = AdminPasswordChangeForm


@admin.register(Group)
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
pass
129 changes: 129 additions & 0 deletions tests/server/example/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models


class Migration(migrations.Migration):
initial = True

dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
]

operations = [
migrations.CreateModel(
name="User",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"username",
models.CharField(
error_messages={
"unique": "A user with that username already exists."
},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
),
),
(
"first_name",
models.CharField(
blank=True, max_length=150, verbose_name="first name"
),
),
(
"last_name",
models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
),
(
"email",
models.EmailField(
blank=True, max_length=254, verbose_name="email address"
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
),
),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.Group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.Permission",
verbose_name="user permissions",
),
),
],
options={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
],
),
]
Empty file.
5 changes: 5 additions & 0 deletions tests/server/example/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
pass
Loading

0 comments on commit 788eca2

Please sign in to comment.