feat(projects): 新增Django综合案例示例代码及素材
This commit is contained in:
17
projects/web-django/delegate.py
Normal file
17
projects/web-django/delegate.py
Normal file
@@ -0,0 +1,17 @@
|
||||
class Proxy:
|
||||
def __init__(self, delegate):
|
||||
self.delegate = delegate
|
||||
|
||||
def fetch(self):
|
||||
print(f"fetching {self.delegate.url} by proxy...")
|
||||
|
||||
|
||||
class Request:
|
||||
def __init__(self, url, proxy=False):
|
||||
self.url = url
|
||||
self.proxy = Proxy(self) if proxy else None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
req = Request("https://sspai.com", proxy=True)
|
||||
req.proxy.fetch()
|
||||
28
projects/web-django/orm.py
Normal file
28
projects/web-django/orm.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from dataclasses import dataclass
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
@dataclass
|
||||
class User:
|
||||
name: str
|
||||
age: int
|
||||
email: str
|
||||
telephone: str
|
||||
|
||||
|
||||
table = [
|
||||
User(
|
||||
name="John",
|
||||
age=25,
|
||||
email="example.john@sspai.com",
|
||||
telephone="021-12345678",
|
||||
),
|
||||
User(
|
||||
name="Steve",
|
||||
age=30,
|
||||
email="example.steve@sspai.com",
|
||||
telephone="000-1111-1111",
|
||||
),
|
||||
]
|
||||
|
||||
pprint(table)
|
||||
22
projects/web-django/quickstart/manage.py
Executable file
22
projects/web-django/quickstart/manage.py
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quickstart.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
0
projects/web-django/quickstart/myapp/__init__.py
Normal file
0
projects/web-django/quickstart/myapp/__init__.py
Normal file
3
projects/web-django/quickstart/myapp/admin.py
Normal file
3
projects/web-django/quickstart/myapp/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
projects/web-django/quickstart/myapp/apps.py
Normal file
6
projects/web-django/quickstart/myapp/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MyappConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'myapp'
|
||||
3
projects/web-django/quickstart/myapp/models.py
Normal file
3
projects/web-django/quickstart/myapp/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
3
projects/web-django/quickstart/myapp/tests.py
Normal file
3
projects/web-django/quickstart/myapp/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
61
projects/web-django/quickstart/myapp/views.py
Normal file
61
projects/web-django/quickstart/myapp/views.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from django.http import HttpResponse
|
||||
|
||||
|
||||
def poem(request):
|
||||
|
||||
content = """
|
||||
<style>
|
||||
figure {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 40%;
|
||||
}
|
||||
figure > figcaption {
|
||||
text-align: center;
|
||||
}
|
||||
blockquote {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
padding: 15px;
|
||||
line-height: 1cm;
|
||||
background: #eee;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
<figure>
|
||||
<blockquote>
|
||||
<i>
|
||||
<p>
|
||||
Beautiful is better than ugly.<br />
|
||||
Explicit is better than implicit.<br />
|
||||
Simple is better than complex.<br />
|
||||
Complex is better than complicated.<br />
|
||||
Flat is better than nested.<br />
|
||||
Sparse is better than dense.<br />
|
||||
Readability counts.<br />
|
||||
Special cases aren't special enough to break the rules.<br />
|
||||
Although practicality beats purity.<br />
|
||||
Errors should never pass silently.<br />
|
||||
Unless explicitly silenced.<br />
|
||||
In the face of ambiguity, refuse the temptation to guess.<br />
|
||||
There should be one-- and preferably only one --obvious way to do
|
||||
it.<br />
|
||||
Although that way may not be obvious at first unless you're
|
||||
Dutch.<br />
|
||||
Now is better than never.<br />
|
||||
Although never is often better than *right* now.<br />
|
||||
If the implementation is hard to explain, it's a bad idea.<br />
|
||||
If the implementation is easy to explain, it may be a good idea.<br />
|
||||
Namespaces are one honking great idea -- let's do more of those!<br />
|
||||
</p>
|
||||
</i>
|
||||
</blockquote>
|
||||
<figcaption>
|
||||
——Tim Peters, <cite><b>The Zen of Python</b></cite>
|
||||
</figcaption>
|
||||
</figure>
|
||||
"""
|
||||
|
||||
return HttpResponse(content)
|
||||
0
projects/web-django/quickstart/orm/__init__.py
Normal file
0
projects/web-django/quickstart/orm/__init__.py
Normal file
3
projects/web-django/quickstart/orm/admin.py
Normal file
3
projects/web-django/quickstart/orm/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
projects/web-django/quickstart/orm/apps.py
Normal file
6
projects/web-django/quickstart/orm/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class OrmConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'orm'
|
||||
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 4.0.4 on 2022-06-25 05:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='用户ID')),
|
||||
('name', models.CharField(max_length=10, verbose_name='用户名')),
|
||||
('age', models.IntegerField(verbose_name='年龄')),
|
||||
('gender', models.BooleanField(blank=True, choices=[(0, '女'), (1, '男')], default='', verbose_name='性别')),
|
||||
('email', models.EmailField(max_length=50, verbose_name='邮箱')),
|
||||
('telephone', models.CharField(blank=True, max_length=11, verbose_name='联系电话')),
|
||||
('register_at', models.DateTimeField(auto_now_add=True, verbose_name='注册时间')),
|
||||
],
|
||||
),
|
||||
]
|
||||
35
projects/web-django/quickstart/orm/models.py
Normal file
35
projects/web-django/quickstart/orm/models.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class User(models.Model):
|
||||
|
||||
gender_choices = [
|
||||
(0, "女"),
|
||||
(1, "男"),
|
||||
]
|
||||
|
||||
id = models.AutoField(
|
||||
primary_key=True,
|
||||
verbose_name="用户ID",
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=10,
|
||||
verbose_name="用户名",
|
||||
)
|
||||
age = models.IntegerField(verbose_name="年龄")
|
||||
gender = models.BooleanField(
|
||||
choices=gender_choices,
|
||||
blank=True,
|
||||
default="",
|
||||
verbose_name="性别",
|
||||
)
|
||||
email = models.EmailField(max_length=50, verbose_name="邮箱")
|
||||
telephone = models.CharField(
|
||||
max_length=11,
|
||||
blank=True,
|
||||
verbose_name="联系电话",
|
||||
)
|
||||
register_at = models.DateTimeField(auto_now_add=True, verbose_name="注册时间")
|
||||
|
||||
def __repr__(self):
|
||||
return f"User<id:{self.id}, name:{self.name}>"
|
||||
3
projects/web-django/quickstart/orm/tests.py
Normal file
3
projects/web-django/quickstart/orm/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
7
projects/web-django/quickstart/orm/urls.py
Normal file
7
projects/web-django/quickstart/orm/urls.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import index
|
||||
|
||||
urlpatterns = [
|
||||
path("", index, name="orm.index"),
|
||||
]
|
||||
5
projects/web-django/quickstart/orm/views.py
Normal file
5
projects/web-django/quickstart/orm/views.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.http import HttpResponse
|
||||
|
||||
|
||||
def index(request):
|
||||
return HttpResponse("ORM page here.")
|
||||
16
projects/web-django/quickstart/quickstart/asgi.py
Normal file
16
projects/web-django/quickstart/quickstart/asgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
ASGI config for quickstart project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quickstart.settings')
|
||||
|
||||
application = get_asgi_application()
|
||||
125
projects/web-django/quickstart/quickstart/settings.py
Normal file
125
projects/web-django/quickstart/quickstart/settings.py
Normal file
@@ -0,0 +1,125 @@
|
||||
"""
|
||||
Django settings for quickstart project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 4.0.4.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.0/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/4.0/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = "django-insecure-)8usuw-fz#s1wq7u2_$u!g&=llu!%j5gl5)$a(avyh5h20_ssq"
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
# internal apps
|
||||
"orm",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "quickstart.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [BASE_DIR.joinpath("templates")],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = "quickstart.wsgi.application"
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.sqlite3",
|
||||
"NAME": BASE_DIR / "db.sqlite3",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.0/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = "zh-Hans"
|
||||
|
||||
TIME_ZONE = "Asia/Shanghai"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
||||
|
||||
STATIC_URL = "static/"
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
26
projects/web-django/quickstart/quickstart/urls.py
Normal file
26
projects/web-django/quickstart/quickstart/urls.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""quickstart URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/4.0/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
from myapp import views
|
||||
|
||||
urlpatterns = [
|
||||
path("admin/", admin.site.urls),
|
||||
path("poem/", views.poem, name="poem"),
|
||||
path("view/", include("view.urls")),
|
||||
path("tmpl/", include("tmpl.urls")),
|
||||
path("orm/", include("orm.urls")),
|
||||
]
|
||||
16
projects/web-django/quickstart/quickstart/wsgi.py
Normal file
16
projects/web-django/quickstart/quickstart/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for quickstart project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quickstart.settings')
|
||||
|
||||
application = get_wsgi_application()
|
||||
43
projects/web-django/quickstart/templates/poem.html
Normal file
43
projects/web-django/quickstart/templates/poem.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>The Zen of Python</title>
|
||||
<style>
|
||||
figure {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 40%;
|
||||
}
|
||||
figure > figcaption {
|
||||
text-align: center;
|
||||
}
|
||||
blockquote {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
padding: 15px;
|
||||
line-height: 1cm;
|
||||
background: #eee;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{% csrf_token %}
|
||||
<figure>
|
||||
<blockquote>
|
||||
<p>
|
||||
{% for line in lines %} <i>{{ line }}</i><br />
|
||||
{% endfor %}
|
||||
</p>
|
||||
</blockquote>
|
||||
<figcaption>
|
||||
——{{ author }}, <cite><b>{{ source }}</b></cite>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</body>
|
||||
</html>
|
||||
0
projects/web-django/quickstart/tmpl/__init__.py
Normal file
0
projects/web-django/quickstart/tmpl/__init__.py
Normal file
3
projects/web-django/quickstart/tmpl/admin.py
Normal file
3
projects/web-django/quickstart/tmpl/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
projects/web-django/quickstart/tmpl/apps.py
Normal file
6
projects/web-django/quickstart/tmpl/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TmplConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'tmpl'
|
||||
3
projects/web-django/quickstart/tmpl/models.py
Normal file
3
projects/web-django/quickstart/tmpl/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
3
projects/web-django/quickstart/tmpl/tests.py
Normal file
3
projects/web-django/quickstart/tmpl/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
7
projects/web-django/quickstart/tmpl/urls.py
Normal file
7
projects/web-django/quickstart/tmpl/urls.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import index
|
||||
|
||||
urlpatterns = [
|
||||
path("", index, name="tmpl_index"),
|
||||
]
|
||||
36
projects/web-django/quickstart/tmpl/views.py
Normal file
36
projects/web-django/quickstart/tmpl/views.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def index(request):
|
||||
|
||||
poem = """\
|
||||
Beautiful is better than ugly.
|
||||
Explicit is better than implicit.
|
||||
Simple is better than complex.
|
||||
Complex is better than complicated.
|
||||
Flat is better than nested.
|
||||
Sparse is better than dense.
|
||||
Readability counts.
|
||||
Special cases aren't special enough to break the rules.
|
||||
Although practicality beats purity.
|
||||
Errors should never pass silently.
|
||||
Unless explicitly silenced.
|
||||
In the face of ambiguity, refuse the temptation to guess.
|
||||
There should be one-- and preferably only one --obvious way to do it.
|
||||
Although that way may not be obvious at first unless you're Dutch.
|
||||
Now is better than never.
|
||||
Although never is often better than *right* now.
|
||||
If the implementation is hard to explain, it's a bad idea.
|
||||
If the implementation is easy to explain, it may be a good idea.
|
||||
Namespaces are one honking great idea -- let's do more of those!
|
||||
"""
|
||||
lines = poem.strip().split("\n")
|
||||
author = "Tim Peters"
|
||||
source = "The Zen of Python"
|
||||
|
||||
context = dict(
|
||||
lines=lines,
|
||||
author=author,
|
||||
source=source,
|
||||
)
|
||||
return render(request, "poem.html", context=context)
|
||||
0
projects/web-django/quickstart/view/__init__.py
Normal file
0
projects/web-django/quickstart/view/__init__.py
Normal file
3
projects/web-django/quickstart/view/admin.py
Normal file
3
projects/web-django/quickstart/view/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
projects/web-django/quickstart/view/apps.py
Normal file
6
projects/web-django/quickstart/view/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ViewConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'view'
|
||||
3
projects/web-django/quickstart/view/models.py
Normal file
3
projects/web-django/quickstart/view/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
3
projects/web-django/quickstart/view/tests.py
Normal file
3
projects/web-django/quickstart/view/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
8
projects/web-django/quickstart/view/urls.py
Normal file
8
projects/web-django/quickstart/view/urls.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import IndexView, index
|
||||
|
||||
urlpatterns = [
|
||||
path("", index),
|
||||
path("class/", IndexView.as_view()),
|
||||
]
|
||||
59
projects/web-django/quickstart/view/views.py
Normal file
59
projects/web-django/quickstart/view/views.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from django.http import HttpResponse, HttpResponseNotAllowed
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
def index(request):
|
||||
"""index page"""
|
||||
|
||||
method = request.method
|
||||
|
||||
if method == "GET":
|
||||
return HttpResponseNotAllowed(["POST"])
|
||||
elif method == "POST":
|
||||
return HttpResponse(f"You has got this page by POST method.")
|
||||
|
||||
|
||||
@method_decorator(csrf_exempt, name="dispatch")
|
||||
class IndexView(View):
|
||||
|
||||
template = """\
|
||||
<p>You has got this page by {method} method, the following steps are: <br />
|
||||
{content}
|
||||
</p>
|
||||
"""
|
||||
|
||||
def get(self, request):
|
||||
"""index page"""
|
||||
|
||||
steps = [
|
||||
"1. handle GET request",
|
||||
"2. log request and other info",
|
||||
"3. query something from database",
|
||||
]
|
||||
response = self.template.format(
|
||||
method="GET",
|
||||
content=r"<br />".join(steps),
|
||||
)
|
||||
|
||||
return HttpResponse(response)
|
||||
|
||||
def post(self, request):
|
||||
|
||||
steps = [
|
||||
"1. handle POST request",
|
||||
"2. log request and other info",
|
||||
"3. get form or parameters from request",
|
||||
"4. parse form or parameters",
|
||||
"5. query something from database",
|
||||
"6. return response",
|
||||
]
|
||||
|
||||
response = self.template.format(
|
||||
method="POST",
|
||||
content=r"<br />".join(steps),
|
||||
)
|
||||
|
||||
return HttpResponse(response)
|
||||
49
projects/web-django/server.py
Normal file
49
projects/web-django/server.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# server.py
|
||||
|
||||
import logging
|
||||
import socketserver
|
||||
import sys
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="[{asctime}] [{levelname}] [{module}] - {message}",
|
||||
style="{",
|
||||
)
|
||||
log = logging.getLogger("server")
|
||||
|
||||
|
||||
class TCPHandler(socketserver.BaseRequestHandler):
|
||||
def handle(self) -> None:
|
||||
request = self.request.recv(1024).decode().strip()
|
||||
log.info(f"Get request:\n{request}")
|
||||
header = "HTTP/1.0 200 OK\r\n\n"
|
||||
content = """
|
||||
<div style="text-align: center;">
|
||||
<h1>Hello, World</h1>
|
||||
<p>You got it!</p>
|
||||
</div>
|
||||
""".strip()
|
||||
response = header + content
|
||||
self.request.sendall(response.encode())
|
||||
|
||||
|
||||
def main():
|
||||
HOST, PORT = "127.0.0.1", 8000
|
||||
srv = socketserver.TCPServer(
|
||||
server_address=(HOST, PORT),
|
||||
RequestHandlerClass=TCPHandler,
|
||||
)
|
||||
|
||||
log.info(f"Listening on http://{HOST}:{PORT}...")
|
||||
try:
|
||||
srv.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
log.info("Server stopped")
|
||||
srv.server_close()
|
||||
srv.shutdown()
|
||||
log.info("Bye...")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
22
projects/web-django/todolist/manage.py
Executable file
22
projects/web-django/todolist/manage.py
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todolist.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
0
projects/web-django/todolist/popup/__init__.py
Normal file
0
projects/web-django/todolist/popup/__init__.py
Normal file
3
projects/web-django/todolist/popup/admin.py
Normal file
3
projects/web-django/todolist/popup/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
projects/web-django/todolist/popup/apps.py
Normal file
6
projects/web-django/todolist/popup/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PopupConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'popup'
|
||||
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 4.0.4 on 2022-06-28 13:48
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Group',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(default='收集箱', max_length=100, unique=True, verbose_name='分类名称')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Task',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, verbose_name='任务名称')),
|
||||
('priority', models.IntegerField(choices=[(0, '一般'), (1, '优先'), (3, '紧急')], default=0, verbose_name='任务优先级')),
|
||||
('description', models.TextField(blank=True, max_length=500, null=True, verbose_name='任务描述')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
|
||||
('is_done', models.BooleanField(choices=[(False, '未完成'), (True, '已完成')], default=False, verbose_name='是否完成')),
|
||||
('group', models.ForeignKey(default=0, on_delete=django.db.models.deletion.DO_NOTHING, to='popup.group', verbose_name='所属分类')),
|
||||
],
|
||||
),
|
||||
]
|
||||
47
projects/web-django/todolist/popup/models.py
Normal file
47
projects/web-django/todolist/popup/models.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Task(models.Model):
|
||||
"""the task record in todolist"""
|
||||
|
||||
priority_choices = (
|
||||
(0, "一般"),
|
||||
(1, "优先"),
|
||||
(3, "紧急"),
|
||||
)
|
||||
|
||||
is_done_choices = (
|
||||
(False, "未完成"),
|
||||
(True, "已完成"),
|
||||
)
|
||||
|
||||
name = models.CharField(max_length=100, verbose_name="任务名称")
|
||||
priority = models.IntegerField(
|
||||
choices=priority_choices, default=0, verbose_name="任务优先级"
|
||||
)
|
||||
description = models.TextField(
|
||||
max_length=500, verbose_name="任务描述", blank=True, null=True
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
|
||||
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
|
||||
is_done = models.BooleanField(
|
||||
default=False, verbose_name="是否完成", choices=is_done_choices
|
||||
)
|
||||
group = models.ForeignKey(
|
||||
"Group", on_delete=models.DO_NOTHING, default=0, verbose_name="所属分类"
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Task {self.name}>"
|
||||
|
||||
|
||||
class Group(models.Model):
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
default="收集箱",
|
||||
unique=True,
|
||||
verbose_name="分类名称",
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Group '{self.name}'>"
|
||||
3
projects/web-django/todolist/popup/tests.py
Normal file
3
projects/web-django/todolist/popup/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
12
projects/web-django/todolist/popup/urls.py
Normal file
12
projects/web-django/todolist/popup/urls.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import about, create_task, delete_task, index, query_all_tasks, update_task
|
||||
|
||||
urlpatterns = [
|
||||
path("", index, name="index"),
|
||||
path("about/", about, name="about"),
|
||||
path("tasks/", query_all_tasks, name="tasks"),
|
||||
path("tasks/create/", create_task, name="create_task"),
|
||||
path("tasks/update/<int:task_id>/", update_task, name="update_task"),
|
||||
path("tasks/delete/<int:task_id>/", delete_task, name="delete_task"),
|
||||
]
|
||||
112
projects/web-django/todolist/popup/views.py
Normal file
112
projects/web-django/todolist/popup/views.py
Normal file
@@ -0,0 +1,112 @@
|
||||
from django.http.response import HttpResponseNotAllowed
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils.html import format_html
|
||||
|
||||
from .models import Group, Task
|
||||
|
||||
|
||||
def index(request):
|
||||
|
||||
welcome = "欢迎来到 Todolist 练习项目 Popup 应用主页!"
|
||||
|
||||
index_content = format_html(
|
||||
"""
|
||||
这是<a href="https://sspai.com/series/271" style="text-decoration: none;">《100 小时后请叫我程序员》</a>课程用于进行 Django 实践练习的网站,主要包括了以下几部分:
|
||||
<ul>
|
||||
<li><b>少数派 Logo</b>:你可以点击跳转至少数派首页;</li>
|
||||
<li><b>Home</b>:即当前页面;</li>
|
||||
<li><b>Task</b>:用于实践的待办清单页面,你可以在里面创建、更新以及删除任务;</li>
|
||||
<li><b>About</b>:对个人或网站信息进行简要说明的介绍页。</li>
|
||||
</ul>
|
||||
"""
|
||||
)
|
||||
|
||||
ctx = dict(
|
||||
title="home",
|
||||
welcome=welcome,
|
||||
index_content=index_content,
|
||||
)
|
||||
|
||||
return render(request, "index.html", context=ctx)
|
||||
|
||||
|
||||
def about(request):
|
||||
title = "About"
|
||||
header = f"{title} Me"
|
||||
about_content = """
|
||||
这是一段简单的,About Me 页面。
|
||||
它可以用来展示关于个人的一些信息,或者是简单的介绍。
|
||||
|
||||
例如:
|
||||
""".strip().splitlines()
|
||||
items = [
|
||||
("昵称", "100gle"),
|
||||
("职业", "少数派作者"),
|
||||
("编程语言", "Python、Golang、JavaScript 等等"),
|
||||
]
|
||||
|
||||
ctx = dict(
|
||||
title=title,
|
||||
header=header,
|
||||
about_content=about_content,
|
||||
items=items,
|
||||
)
|
||||
return render(request, "about.html", context=ctx)
|
||||
|
||||
|
||||
def query_all_tasks(request):
|
||||
tasks = Task.objects.all()
|
||||
fields = ["序号", "任务名称", "优先级", "任务描述", "是否完成", "分组"]
|
||||
|
||||
if Group.objects.count() == 0:
|
||||
groups = [
|
||||
Group(name="收集箱"),
|
||||
Group(name="生活"),
|
||||
Group(name="工作"),
|
||||
]
|
||||
|
||||
Group.objects.bulk_create(groups)
|
||||
|
||||
groups = Group.objects.all()
|
||||
|
||||
ctx = dict(
|
||||
title="Task",
|
||||
tasks=tasks,
|
||||
fields=fields,
|
||||
groups=groups,
|
||||
)
|
||||
return render(request, "tasks.html", context=ctx)
|
||||
|
||||
|
||||
def create_task(request):
|
||||
"""create a task"""
|
||||
if request.method == "POST":
|
||||
name = request.POST.get("taskName")
|
||||
priority = request.POST.get("taskPriority")
|
||||
description = request.POST.get("taskDescription")
|
||||
group_id = request.POST.get("taskGroup")
|
||||
group = Group.objects.get(id=group_id)
|
||||
|
||||
Task.objects.create(
|
||||
name=name, priority=priority, description=description, group=group
|
||||
)
|
||||
return redirect("/tasks/")
|
||||
else:
|
||||
return HttpResponseNotAllowed(["POST"])
|
||||
|
||||
|
||||
def update_task(request, task_id):
|
||||
"""update a task"""
|
||||
task = Task.objects.get(id=task_id)
|
||||
task.is_done = False if task.is_done else True
|
||||
|
||||
task.save()
|
||||
return redirect("/tasks/")
|
||||
|
||||
|
||||
def delete_task(request, task_id):
|
||||
"""delete a task"""
|
||||
task = Task.objects.get(id=task_id)
|
||||
|
||||
task.delete()
|
||||
return redirect("/tasks/")
|
||||
1
projects/web-django/todolist/static/css/simple-v1.min.css
vendored
Executable file
1
projects/web-django/todolist/static/css/simple-v1.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
149
projects/web-django/todolist/static/css/style.css
Normal file
149
projects/web-django/todolist/static/css/style.css
Normal file
@@ -0,0 +1,149 @@
|
||||
/* base layout */
|
||||
.container {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px;
|
||||
word-spacing: 1.5px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* navbar */
|
||||
.navbar ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.navbar a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.navbar a:hover {
|
||||
color: goldenrod !important;
|
||||
}
|
||||
|
||||
.content,
|
||||
.about {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.content li::before,
|
||||
.about li::before {
|
||||
content: "\1F449";
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
/* data table */
|
||||
.data-table {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.data-table th,
|
||||
.data-table td {
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.data-table th:first-child {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
.data-table th:nth-child(2) {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.data-table th:nth-child(4) {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.data-table td[class="ops"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.data-table .ops span {
|
||||
display: block;
|
||||
color: var(--accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-add-task {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.btn-add-task > button {
|
||||
display: block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
font-size: 20px;
|
||||
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-add-task > button:hover {
|
||||
background-color: rgb(204, 77, 77);
|
||||
}
|
||||
|
||||
.task-form {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.form {
|
||||
display: block;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.form > div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.form .btn-submit {
|
||||
text-align: center;
|
||||
transition: 0.1ms;
|
||||
}
|
||||
|
||||
.form .btn-submit > input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: 20px;
|
||||
transition: 0.1ms;
|
||||
}
|
||||
|
||||
#task-textarea {
|
||||
width: 60%;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
/* footer */
|
||||
#footer {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="123" height="44" viewBox="0 0 123 44" style="enable-background:new 0 0 123 44;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#292525;}
|
||||
.st1{fill:#DA282A;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M59.8,31.7C59.8,31.7,59.7,31.7,59.8,31.7c-0.1,0-0.2-0.1-0.2-0.1l-0.9-1.3c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1
|
||||
c0,0,0-0.1,0.1-0.1c0,0,0.1,0,0.1,0c6.6-0.6,11.8-2.9,17-7.5c0,0,0,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0,0,0.1,0.1
|
||||
l0.9,1.1c0,0,0.1,0.1,0,0.2c0,0.1,0,0.1-0.1,0.1C71.6,28.6,66.6,30.8,59.8,31.7L59.8,31.7z" />
|
||||
<path class="st0" d="M69.2,12.2h-1.5c-0.1,0-0.2,0.1-0.2,0.2v12.4c0,0.1,0.1,0.2,0.2,0.2h1.5c0.1,0,0.2-0.1,0.2-0.2V12.5
|
||||
C69.4,12.3,69.3,12.2,69.2,12.2z" />
|
||||
<path class="st0" d="M60.7,23.5H59c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1l3.6-7.9c0,0,0-0.1,0.1-0.1
|
||||
c0,0,0.1,0,0.1,0h1.7c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1l-3.6,7.9c0,0,0,0.1-0.1,0.1
|
||||
C60.8,23.5,60.7,23.5,60.7,23.5z" />
|
||||
<path class="st0" d="M75.6,21c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1-0.1l-3.1-5.4c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0.1-0.1
|
||||
c0,0,0.1,0,0.1,0h1.8c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0.1l3.1,5.4c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1-0.1,0.1
|
||||
c0,0-0.1,0-0.1,0H75.6L75.6,21z" />
|
||||
<path class="st0" d="M108.5,31.6C108.5,31.6,108.4,31.6,108.5,31.6l-1.4-0.5c-0.1,0-0.1-0.1-0.1-0.1c0,0,0-0.1,0-0.1
|
||||
c0,0,0-0.1,0-0.1l0.8-2c0.3-0.8,0.6-1.6,0.8-2.5c0.3-1.3,0.4-2.5,0.4-3.8V14c0-0.1,0-0.1,0.1-0.2c0,0,0.1-0.1,0.2-0.1
|
||||
c5.3,0.1,7.5-0.5,10.3-1.3l0.7-0.2c0,0,0.1,0,0.1,0s0.1,0,0.1,0.1l0.8,1.2c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1-0.1,0.1
|
||||
c0,0-0.1,0-0.1,0l-0.3,0.1c-2.9,0.9-5,1.5-9.8,1.6c-0.1,0-0.1,0-0.1,0.1c0,0-0.1,0.1-0.1,0.1v6.9c0,1.4-0.2,2.7-0.5,4.1l-0.1,0.3
|
||||
c-0.2,0.8-0.4,1.7-0.8,2.5l-0.8,2C108.7,31.5,108.6,31.6,108.5,31.6C108.6,31.6,108.5,31.6,108.5,31.6z" />
|
||||
<path class="st0" d="M105.6,22c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1-0.1L103,18c0,0,0,0,0-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1
|
||||
c0,0,0,0,0.1-0.1l1.8-1.1c0,0,0.1,0,0.1-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1l-1.9-2.9c0,0,0-0.1,0-0.1
|
||||
c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0,0,0,0.1-0.1l1.3-0.8c0,0,0.1,0,0.2,0c0.1,0,0.1,0,0.1,0.1l2.3,3.6c0,0,0,0,0,0.1l0.6,0.9
|
||||
c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0-0.1,0.1l-1.8,1.1c0,0-0.1,0-0.1,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1
|
||||
c0,0,0,0.1,0,0.1l1.4,2.2c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0.1,0,0.1-0.1,0.1l-1.3,0.8C105.7,22,105.6,22,105.6,22z" />
|
||||
<path class="st0" d="M104.4,31.8C104.4,31.8,104.4,31.8,104.4,31.8l-1.5-0.6c0,0-0.1,0-0.1,0c0,0,0,0,0-0.1c0,0,0-0.1,0-0.1
|
||||
c0,0,0-0.1,0-0.1l3.3-8.3c0,0,0-0.1,0-0.1c0,0,0,0,0.1,0s0.1,0,0.1,0c0,0,0.1,0,0.1,0l1.4,0.6c0,0,0.1,0,0.1,0c0,0,0,0,0,0.1
|
||||
c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1l-3.3,8.3c0,0,0,0,0,0.1C104.6,31.7,104.6,31.7,104.4,31.8C104.5,31.8,104.5,31.8,104.4,31.8z" />
|
||||
<path class="st0" d="M120.8,31.7C120.8,31.7,120.8,31.7,120.8,31.7c-0.1,0-0.2-0.1-0.2-0.1l-1.6-2.3c-0.3-0.4-0.6-0.8-0.8-1.3
|
||||
l-0.8-1.6c-0.3-0.6-0.6-1.3-0.8-2l-1.5-5.7c0,0,0-0.1-0.1-0.1c0,0-0.1,0-0.1,0c-0.4,0-0.7,0-1.1,0.1c0,0-0.1,0-0.1,0
|
||||
c0,0,0,0.1,0,0.1v10.9c0,0.1,0,0.1,0.1,0.1c0,0,0.1,0.1,0.1,0.1h2.6c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0.1,0.1,0.2v1.4
|
||||
c0,0.1,0,0.1-0.1,0.2c0,0-0.1,0.1-0.2,0.1h-4.3c-0.1,0-0.1,0-0.2-0.1c0,0-0.1-0.1-0.1-0.2V17.6c0,0,0,0,0-0.1V17
|
||||
c0-0.1,0-0.1,0.1-0.2c0,0,0,0,0.1,0c0,0,0.1,0,0.1,0c2.4,0,4.7-0.3,7-0.8l0.9-0.2c0,0,0.1,0,0.1,0c0,0,0.1,0.1,0.1,0.1l0.7,1.3
|
||||
c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1-0.1,0.1c0,0-0.1,0-0.1,0l-0.9,0.2c-1,0.2-1.9,0.4-2.9,0.6c0,0,0,0-0.1,0c0,0,0,0,0,0
|
||||
c0,0,0,0,0,0.1c0,0,0,0,0,0.1l0.9,3.5c0,0,0,0.1,0,0.1c0,0,0,0,0.1,0.1c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0l2.9-1.2c0,0,0.1,0,0.1,0
|
||||
c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0.1l0.5,1.3c0,0.1,0,0.1,0,0.2c0,0.1-0.1,0.1-0.1,0.1l-3.2,1.3c0,0-0.1,0-0.1,0.1
|
||||
c0,0,0,0.1,0,0.1c0.2,0.6,0.4,1.1,0.6,1.6l0.7,1.3c0.2,0.4,0.4,0.8,0.7,1.2l1.9,2.7c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1
|
||||
c0,0,0,0.1,0,0.1c0,0-0.1,0-0.1,0.1L120.8,31.7C120.9,31.7,120.9,31.7,120.8,31.7z" />
|
||||
<path class="st0" d="M86.8,22.3h-1.5c-0.1,0-0.1,0-0.2-0.1c0,0-0.1-0.1-0.1-0.2v-4c0,0,0-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1h-4
|
||||
c-0.1,0-0.1,0-0.2-0.1c0,0-0.1-0.1-0.1-0.2v-1.4c0-0.1,0-0.1,0.1-0.2c0,0,0.1-0.1,0.2-0.1h4c0,0,0.1,0,0.1-0.1c0,0,0.1-0.1,0.1-0.1
|
||||
v-3.5c0-0.1,0-0.1,0.1-0.2c0,0,0.1-0.1,0.2-0.1h1.5c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0.1,0.1,0.2V16c0,0,0,0.1,0.1,0.1
|
||||
c0,0,0.1,0.1,0.1,0.1h4c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0.1,0.1,0.2v1.4c0,0.1,0,0.1-0.1,0.2c0,0-0.1,0.1-0.2,0.1h-4c0,0,0,0-0.1,0
|
||||
c0,0,0,0-0.1,0c0,0,0,0,0,0.1c0,0,0,0,0,0.1v4c0,0.1,0,0.1-0.1,0.2C86.9,22.3,86.9,22.3,86.8,22.3z" />
|
||||
<path class="st0" d="M83,16.2c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1-0.1l-1.5-2.8c0-0.1,0-0.1,0-0.2c0-0.1,0.1-0.1,0.1-0.1l1.4-0.7
|
||||
c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0.1,0.1,0.1l1.5,2.8c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0.1-0.1,0.1-0.1,0.1L83,16.2
|
||||
C83,16.2,83,16.2,83,16.2z" />
|
||||
<path class="st0" d="M89,16.2c0,0-0.1,0-0.1,0l-1.2-1c0,0-0.1-0.1-0.1-0.1c0-0.1,0-0.1,0-0.2l2.1-2.5c0,0,0.1-0.1,0.1-0.1
|
||||
c0.1,0,0.1,0,0.2,0l1.2,1c0,0,0.1,0.1,0.1,0.1c0,0.1,0,0.1,0,0.2l-2.1,2.5C89.1,16.1,89.1,16.2,89,16.2C89.1,16.2,89,16.2,89,16.2z" />
|
||||
<path class="st0" d="M82.2,22c-0.1,0-0.1,0-0.1-0.1l-1.2-1c0,0,0,0-0.1-0.1c0,0,0-0.1,0-0.1c0-0.1,0-0.1,0.1-0.2l2.2-2.6
|
||||
c0,0,0,0,0.1-0.1c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0l1.2,1c0,0,0,0,0.1,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1
|
||||
c0,0,0,0.1,0,0.1l-2.2,2.6C82.4,21.9,82.3,21.9,82.2,22C82.3,22,82.3,22,82.2,22z" />
|
||||
<path class="st0" d="M89.8,21.9C89.7,21.9,89.7,21.8,89.8,21.9c-0.1,0-0.2-0.1-0.2-0.1l-1.9-2.6c0,0,0,0,0-0.1c0,0,0-0.1,0-0.1
|
||||
c0,0,0-0.1,0-0.1c0,0,0,0,0.1-0.1L89,18c0,0,0,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0,0,0.1,0.1l1.9,2.6c0,0,0,0.1,0,0.2
|
||||
c0,0.1,0,0.1-0.1,0.1l-1.2,0.9C89.8,21.8,89.8,21.9,89.8,21.9z" />
|
||||
<path class="st0" d="M91.6,30.2C91.6,30.2,91.7,30.2,91.6,30.2c0.1,0.1,0.1,0.1,0.1,0.2c0,0,0,0.1,0,0.1c0,0,0,0.1-0.1,0.1l-1.2,1
|
||||
c-0.1,0.1-0.1,0.1-0.2,0.1c-0.1,0-0.2,0-0.3,0l-3.6-1.7c0,0-0.1,0-0.1,0s-0.1,0-0.1,0l-1.4,0.6c-0.6,0.3-1.3,0.5-1.9,0.7l-1.7,0.5
|
||||
c-0.1,0-0.1,0-0.2,0c-0.1,0-0.1-0.1-0.1-0.1l-0.3-1.1c0-0.1,0-0.1,0-0.2c0-0.1,0-0.1,0-0.2c0-0.1,0.1-0.1,0.1-0.1
|
||||
c0,0,0.1-0.1,0.2-0.1l1.8-0.6c0.3-0.1,0.7-0.2,1-0.4l0.4-0.2l-0.8-0.4l-1.8-0.8c0,0-0.1,0-0.1-0.1c0,0,0,0,0-0.1c0,0,0-0.1,0-0.1
|
||||
c0,0,0-0.1,0-0.1l1-1.8c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0-0.1-0.1-0.1-0.1c0,0-0.1,0-0.1,0h-1.1c-0.1,0-0.2,0-0.3-0.1
|
||||
c-0.1-0.1-0.1-0.2-0.1-0.3v-0.9c0-0.1,0-0.2,0.1-0.3c0.1-0.1,0.2-0.1,0.3-0.1h2.5l0.3-0.5c0,0,0-0.1,0.1-0.1c0,0,0.1,0,0.1,0H86
|
||||
c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0.1c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1L86,23.3h5.2c0.1,0,0.2,0,0.3,0.1c0.1,0.1,0.1,0.2,0.1,0.3v1.6
|
||||
c0,0.1,0,0.2,0,0.2c0,0.1-0.1,0.1-0.1,0.2l-1,1c-0.7,0.7-1.4,1.3-2.2,1.8L91.6,30.2z M84.4,26.9l1.8,0.8c0,0,0.1,0,0.1,0
|
||||
c0,0,0.1,0,0.1,0l0.9-0.6c0.6-0.4,1.1-0.9,1.7-1.4l0.6-0.6h-4.4c-0.1,0-0.2,0-0.2,0.1c-0.1,0-0.1,0.1-0.2,0.2l-0.6,1
|
||||
c0,0,0,0.1-0.1,0.2c0,0.1,0,0.1,0,0.2c0,0.1,0,0.1,0.1,0.1C84.3,26.9,84.3,26.9,84.4,26.9z" />
|
||||
<path class="st0" d="M98,28l2.1,2.3c0,0,0.1,0.1,0.1,0.2c0,0.1,0,0.1-0.1,0.2l-1.1,1c0,0,0,0-0.1,0c0,0-0.1,0-0.1,0
|
||||
c-0.1,0-0.1,0-0.2-0.1L96.2,29c0,0-0.1,0-0.1-0.1c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0.1l-2.5,2.7c0,0-0.1,0.1-0.2,0.1
|
||||
c-0.1,0-0.1,0-0.2-0.1l-1.1-1c0,0,0,0,0-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1l2-2.1l0.8-0.9c0,0,0.1-0.1,0.1-0.1
|
||||
c0-0.1,0-0.1-0.1-0.1l-0.2-0.3c-0.8-1-1.3-2.2-1.6-3.5l-0.2-0.7c-0.1-0.7-0.2-1.3-0.2-2v-4c0-0.1,0-0.1,0.1-0.2c0,0,0,0,0.1,0
|
||||
c0,0,0.1,0,0.1,0h1.5c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0.1,0.1,0.2v3.8c0,0.6,0.1,1.3,0.2,1.9l0.1,0.3c0.2,1,0.6,2,1.2,2.9
|
||||
c0,0,0,0,0.1,0c0,0,0,0,0.1,0c0,0,0,0,0.1,0c0,0,0,0,0.1,0c0.6-0.9,1-1.9,1.3-3l0-0.1c0.2-0.7,0.2-1.3,0.2-2v-4.4c0,0,0-0.1,0-0.1
|
||||
c0,0-0.1,0-0.1,0h-4.9c-0.1,0-0.1,0-0.2-0.1c0,0-0.1-0.1-0.1-0.2v-2.9c0-0.1,0-0.1,0.1-0.2c0,0,0.1-0.1,0.2-0.1h1.5
|
||||
c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0.1,0.1,0.2v1.3h5c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0.1,0.1,0.2v1.4v5c0,0.7-0.1,1.4-0.2,2.2l-0.2,0.7
|
||||
c-0.3,1.2-0.8,2.4-1.6,3.4L97.4,27c0,0-0.1,0.1-0.1,0.2c0,0.1,0,0.1,0.1,0.2L98,28z" />
|
||||
<path class="st1" d="M22,44c12.2,0,22-9.8,22-22C44,9.8,34.2,0,22,0C9.8,0,0,9.8,0,22C0,34.2,9.8,44,22,44z" />
|
||||
<path class="st2" d="M32,11.3l-21.2,3.6c-0.2,0-0.4,0.1-0.6,0.3c-0.1,0.2-0.2,0.4-0.3,0.6l-0.2,1.8c0,0.2,0,0.3,0,0.4
|
||||
c0.1,0.1,0.1,0.3,0.2,0.4c0.1,0.1,0.2,0.2,0.4,0.2c0.1,0,0.3,0.1,0.4,0l4.1-0.7v14.7c0,0.2,0,0.4,0.1,0.5c0.1,0.2,0.2,0.3,0.4,0.4
|
||||
c0.2,0.1,0.3,0.1,0.5,0.1c0.2,0,0.4-0.1,0.5-0.2l1.6-1c0.2-0.1,0.3-0.3,0.4-0.5c0.1-0.2,0.2-0.4,0.2-0.6v-14l5.7-0.9v10.3
|
||||
c0,0.6,0.2,1.3,0.5,1.8l2.5,4.7c0.1,0.1,0.2,0.3,0.3,0.3c0.1,0.1,0.3,0.1,0.4,0.1h2.2c0.1,0,0.3,0,0.4-0.1c0.1-0.1,0.2-0.2,0.3-0.3
|
||||
c0.1-0.1,0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4l-2.5-4.9C28.2,27,28,26.4,28,25.7V15.7l4-0.7c0.2,0,0.4-0.1,0.5-0.3
|
||||
c0.1-0.2,0.2-0.4,0.3-0.6l0.2-1.8c0-0.2,0-0.3,0-0.5s-0.1-0.3-0.2-0.4s-0.2-0.2-0.4-0.2C32.3,11.3,32.1,11.2,32,11.3z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.7 KiB |
16
projects/web-django/todolist/static/js/main.js
Normal file
16
projects/web-django/todolist/static/js/main.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const addTaskButton = document.querySelector(".btn-add-task");
|
||||
const formDiv = document.querySelector(".task-form");
|
||||
const taskStatus = document.querySelector(".task-status");
|
||||
const updateOp = document.querySelector(".update-op");
|
||||
|
||||
// show task form
|
||||
if (addTaskButton) {
|
||||
addTaskButton.addEventListener("click", () => {
|
||||
// use inline style to override css property.
|
||||
if (formDiv.style.display === "") {
|
||||
formDiv.style.display = "none";
|
||||
}
|
||||
formDiv.style.display =
|
||||
formDiv.style.display == "none" ? "flex" : "none";
|
||||
});
|
||||
}
|
||||
24
projects/web-django/todolist/templates/about.html
Normal file
24
projects/web-django/todolist/templates/about.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<article class="about">
|
||||
<h1>{{ header }}</h1>
|
||||
<section>
|
||||
<p>
|
||||
{% for content in about_content %}
|
||||
{{ content }} <br />
|
||||
{% endfor %}
|
||||
</p>
|
||||
<ul>
|
||||
{% for item in items %}
|
||||
<li>{{ item.0 }}:{{ item.1 }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
{% endblock %}
|
||||
44
projects/web-django/todolist/templates/base.html
Normal file
44
projects/web-django/todolist/templates/base.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>
|
||||
{% if title == "home" %}
|
||||
Todolist Web App
|
||||
{% else %}
|
||||
Todolist Web App - {% block title %}{% endblock %}
|
||||
{% endif %}
|
||||
</title>
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href={% static "css/simple-v1.min.css" %}>
|
||||
<link rel="stylesheet" href={% static "css/style.css" %}>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<nav class="navbar">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://sspai.com" class="logo">
|
||||
<img src={% static "images/sspai-logo-light.svg" %} alt="logo">
|
||||
</a>
|
||||
</li>
|
||||
<li><a href={% url "index" %}>Home</a></li>
|
||||
<li><a href={% url "tasks" %}>Task</a></li>
|
||||
<li><a href={% url "about" %}>About</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<hr />
|
||||
<main>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p class="copyright">© 2022-Present 100gle & 少数派</p>
|
||||
</footer>
|
||||
</div>
|
||||
<script type="text/javascript" src={% static "js/main.js" %}></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
19
projects/web-django/todolist/templates/index.html
Normal file
19
projects/web-django/todolist/templates/index.html
Normal file
@@ -0,0 +1,19 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}
|
||||
{{ title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content%}
|
||||
|
||||
<article class="content">
|
||||
<h1>🗣 <i>Hello, world</i></h1>
|
||||
<section>
|
||||
<p>{{ welcome }}</p>
|
||||
<p>
|
||||
{{ index_content }}
|
||||
</p>
|
||||
|
||||
</section>
|
||||
</article>
|
||||
|
||||
{% endblock%}
|
||||
96
projects/web-django/todolist/templates/tasks.html
Normal file
96
projects/web-django/todolist/templates/tasks.html
Normal file
@@ -0,0 +1,96 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title%}
|
||||
{{ title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="data-table">
|
||||
<h1>Tasks</h1>
|
||||
{% if not tasks %}
|
||||
<p>🤔 Whoops……似乎任务都做完了?那么可以点击下方的按钮添加任务!</p>
|
||||
{% else %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{% for field in fields %}
|
||||
<th>{{ field }}</th>
|
||||
{% endfor%}
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for task in tasks %}
|
||||
<tr>
|
||||
<td>{{ task.id }}</td>
|
||||
<td>{{ task.name }}</td>
|
||||
<td>
|
||||
{% if task.priority == 1 %}
|
||||
{{ "一般" }}
|
||||
{% elif task.priority == 2 %}
|
||||
{{ "优先" }}
|
||||
{% else %}
|
||||
{{ "紧急" }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="task-decs">{{ task.description }}</td>
|
||||
<td class="task-status">
|
||||
{% if task.is_done %}
|
||||
{{ "已完成" }}
|
||||
{% else %}
|
||||
{{ "未完成" }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ task.group.name }}</td>
|
||||
<td>
|
||||
<div class="ops">
|
||||
<span>
|
||||
<a href="/tasks/update/{{task.id}}">更新</a>
|
||||
</span>
|
||||
<span>
|
||||
<a href="/tasks/delete/{{task.id}}">删除</a>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="btn-add-task">
|
||||
<button>+</button>
|
||||
</div>
|
||||
<div class="task-form">
|
||||
<form action={% url "create_task" %} method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
<label for="taskName">任务名称:</label>
|
||||
<input type="text" name="taskName" id="taskName" placeholder="请输入待办事项名称" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="taskPriority">优先级:</label>
|
||||
<select name="taskPriority" id="taskPriority">
|
||||
<option value="1" selected>一般</option>
|
||||
<option value="2">优先</option>
|
||||
<option value="3">紧急</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="taskGroup"> 分组: </label>
|
||||
<select name="taskGroup" id="taskGroup">
|
||||
{% for group in groups %}
|
||||
<option value="{{ group.id }}">{{ group.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="task-textarea">任务备注:</label>
|
||||
<textarea name="taskDescription" id="task-textarea" rows="5" placeholder="备注内容(可选)"></textarea>
|
||||
</div>
|
||||
<div class="btn-submit">
|
||||
<input type="submit" value="添加" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
0
projects/web-django/todolist/todolist/__init__.py
Normal file
0
projects/web-django/todolist/todolist/__init__.py
Normal file
16
projects/web-django/todolist/todolist/asgi.py
Normal file
16
projects/web-django/todolist/todolist/asgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
ASGI config for todolist project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todolist.settings')
|
||||
|
||||
application = get_asgi_application()
|
||||
126
projects/web-django/todolist/todolist/settings.py
Normal file
126
projects/web-django/todolist/todolist/settings.py
Normal file
@@ -0,0 +1,126 @@
|
||||
"""
|
||||
Django settings for todolist project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 4.0.4.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.0/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/4.0/ref/settings/
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = "django-insecure-h$0(p$ca027=i@rg(!3ut8zm@((lfkvjdc%=g$f6gecl#5c)ly"
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"popup",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "todolist.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [BASE_DIR / "templates"],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = "todolist.wsgi.application"
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.sqlite3",
|
||||
"NAME": BASE_DIR / "db.sqlite3",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/4.0/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = "zh-Hans"
|
||||
|
||||
TIME_ZONE = "Asia/Shanghai"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
||||
|
||||
STATIC_URL = "static/"
|
||||
STATICFILES_DIRS = [
|
||||
BASE_DIR / "static",
|
||||
]
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
22
projects/web-django/todolist/todolist/urls.py
Normal file
22
projects/web-django/todolist/todolist/urls.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""todolist URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/4.0/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path("admin/", admin.site.urls),
|
||||
path("", include("popup.urls")),
|
||||
]
|
||||
16
projects/web-django/todolist/todolist/wsgi.py
Normal file
16
projects/web-django/todolist/todolist/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for todolist project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todolist.settings')
|
||||
|
||||
application = get_wsgi_application()
|
||||
Reference in New Issue
Block a user