diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 856a1bb..61cfaad 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -31,9 +31,21 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -78,14 +90,36 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -133,6 +167,11 @@
+
+
+
+
+
@@ -153,7 +192,8 @@
-
+
+ 1650187914913
@@ -176,7 +216,14 @@
1651746739401
-
+
+ 1651748255265
+
+
+
+ 1651748255265
+
+
@@ -211,7 +258,8 @@
-
+
+
@@ -226,6 +274,10 @@
+
+
+
+
@@ -242,22 +294,22 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
@@ -282,14 +334,14 @@
-
+
-
-
+
+
-
+
@@ -307,4 +359,7 @@
+
+
+
\ No newline at end of file
diff --git a/ITShowPlatform/.gitignore b/ITShowPlatform/.gitignore
new file mode 100644
index 0000000..b9ad17b
--- /dev/null
+++ b/ITShowPlatform/.gitignore
@@ -0,0 +1,3 @@
+config.ini
+
+settings.py
diff --git a/ITShowPlatform/config.ini b/ITShowPlatform/config.ini
new file mode 100644
index 0000000..42c1892
--- /dev/null
+++ b/ITShowPlatform/config.ini
@@ -0,0 +1,22 @@
+[email]
+EMAIL_HOST = smtp.qq.com # 服务器
+
+EMAIL_PORT = 465
+
+EMAIL_HOST_USER = 2302253692@qq.com # 账号
+
+EMAIL_HOST_PASSWORD = idujbpdlpgbmdhjg # 密码 (注意:这里的密码指的是授权码)
+
+EMAIL_USE_SSL = True # 一般都为False
+
+EMAIL_FROM = 2302253692@qq.com # 邮箱来自
+
+[database]
+
+ENGINE = django.db.backends.mysql
+
+NAME = ITShowPlatform
+
+USER = root
+
+PASSWORD = HNXhnx123
diff --git a/ITShowPlatform/settings.py b/ITShowPlatform/settings.py
index 4cbb943..48835e4 100644
--- a/ITShowPlatform/settings.py
+++ b/ITShowPlatform/settings.py
@@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/4.0/ref/settings/
from pathlib import Path
import os
+import configparser
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -29,6 +30,12 @@ ALLOWED_HOSTS = ["*"]
# Application definition
+conf = configparser.ConfigParser()
+
+conf.read(str(BASE_DIR)+r"\ITShowPlatform\config.ini",encoding="utf-8")
+
+
+
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
@@ -79,10 +86,10 @@ WSGI_APPLICATION = 'ITShowPlatform.wsgi.application'
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'ITShowPlatform',
- 'USER': 'root',
- 'PASSWORD': 'HNXhnx123',
+ 'ENGINE': conf.get("database","ENGINE"),
+ 'NAME': conf.get("database","NAME"),
+ 'USER': conf.get("database","USER"),
+ 'PASSWORD': conf.get("database","PASSWORD"),
}
}
@@ -138,9 +145,10 @@ REST_FRAMEWORK = {
)
}
-EMAIL_HOST = "smtp.qq.com" # 服务器
-EMAIL_PORT = 465
-EMAIL_HOST_USER = "2302253692@qq.com" # 账号
-EMAIL_HOST_PASSWORD = "idujbpdlpgbmdhjg" # 密码 (注意:这里的密码指的是授权码)
-EMAIL_USE_SSL = True # 一般都为False
-EMAIL_FROM = "2302253692@qq.com" # 邮箱来自
+EMAIL_HOST = conf.get('email',"EMAIL_HOST") # 服务器
+EMAIL_PORT = conf.get("email","EMAIL_PORT")
+EMAIL_HOST_USER = conf.get("email","EMAIL_HOST_USER") # 账号
+EMAIL_HOST_PASSWORD = conf.get("email","EMAIL_HOST_PASSWORD") # 密码 (注意:这里的密码指的是授权码)
+EMAIL_USE_SSL = conf.get("email","EMAIL_USE_SSL") # 一般都为False
+EMAIL_FROM = conf.get("email","EMAIL_FROM") # 邮箱来自
+
diff --git a/venv/Lib/site-packages/backports/configparser/__init__.py b/venv/Lib/site-packages/backports/configparser/__init__.py
new file mode 100644
index 0000000..73386a9
--- /dev/null
+++ b/venv/Lib/site-packages/backports/configparser/__init__.py
@@ -0,0 +1,1440 @@
+"""Configuration file parser.
+
+A configuration file consists of sections, lead by a "[section]" header,
+and followed by "name: value" entries, with continuations and such in
+the style of RFC 822.
+
+Intrinsic defaults can be specified by passing them into the
+ConfigParser constructor as a dictionary.
+
+class:
+
+ConfigParser -- responsible for parsing a list of
+ configuration files, and managing the parsed database.
+
+ methods:
+
+ __init__(defaults=None, dict_type=_default_dict, allow_no_value=False,
+ delimiters=('=', ':'), comment_prefixes=('#', ';'),
+ inline_comment_prefixes=None, strict=True,
+ empty_lines_in_values=True, default_section='DEFAULT',
+ interpolation=, converters=):
+ Create the parser. When `defaults' is given, it is initialized into the
+ dictionary or intrinsic defaults. The keys must be strings, the values
+ must be appropriate for %()s string interpolation.
+
+ When `dict_type' is given, it will be used to create the dictionary
+ objects for the list of sections, for the options within a section, and
+ for the default values.
+
+ When `delimiters' is given, it will be used as the set of substrings
+ that divide keys from values.
+
+ When `comment_prefixes' is given, it will be used as the set of
+ substrings that prefix comments in empty lines. Comments can be
+ indented.
+
+ When `inline_comment_prefixes' is given, it will be used as the set of
+ substrings that prefix comments in non-empty lines.
+
+ When `strict` is True, the parser won't allow for any section or option
+ duplicates while reading from a single source (file, string or
+ dictionary). Default is True.
+
+ When `empty_lines_in_values' is False (default: True), each empty line
+ marks the end of an option. Otherwise, internal empty lines of
+ a multiline option are kept as part of the value.
+
+ When `allow_no_value' is True (default: False), options without
+ values are accepted; the value presented for these is None.
+
+ When `default_section' is given, the name of the special section is
+ named accordingly. By default it is called ``"DEFAULT"`` but this can
+ be customized to point to any other valid section name. Its current
+ value can be retrieved using the ``parser_instance.default_section``
+ attribute and may be modified at runtime.
+
+ When `interpolation` is given, it should be an Interpolation subclass
+ instance. It will be used as the handler for option value
+ pre-processing when using getters. RawConfigParser objects don't do
+ any sort of interpolation, whereas ConfigParser uses an instance of
+ BasicInterpolation. The library also provides a ``zc.buildbot``
+ inspired ExtendedInterpolation implementation.
+
+ When `converters` is given, it should be a dictionary where each key
+ represents the name of a type converter and each value is a callable
+ implementing the conversion from string to the desired datatype. Every
+ converter gets its corresponding get*() method on the parser object and
+ section proxies.
+
+ sections()
+ Return all the configuration section names, sans DEFAULT.
+
+ has_section(section)
+ Return whether the given section exists.
+
+ has_option(section, option)
+ Return whether the given option exists in the given section.
+
+ options(section)
+ Return list of configuration options for the named section.
+
+ read(filenames, encoding=None)
+ Read and parse the iterable of named configuration files, given by
+ name. A single filename is also allowed. Non-existing files
+ are ignored. Return list of successfully read files.
+
+ read_file(f, filename=None)
+ Read and parse one configuration file, given as a file object.
+ The filename defaults to f.name; it is only used in error
+ messages (if f has no `name' attribute, the string `??>' is used).
+
+ read_string(string)
+ Read configuration from a given string.
+
+ read_dict(dictionary)
+ Read configuration from a dictionary. Keys are section names,
+ values are dictionaries with keys and values that should be present
+ in the section. If the used dictionary type preserves order, sections
+ and their keys will be added in order. Values are automatically
+ converted to strings.
+
+ get(section, option, raw=False, vars=None, fallback=_UNSET)
+ Return a string value for the named option. All % interpolations are
+ expanded in the return values, based on the defaults passed into the
+ constructor and the DEFAULT section. Additional substitutions may be
+ provided using the `vars' argument, which must be a dictionary whose
+ contents override any pre-existing defaults. If `option' is a key in
+ `vars', the value from `vars' is used.
+
+ getint(section, options, raw=False, vars=None, fallback=_UNSET)
+ Like get(), but convert value to an integer.
+
+ getfloat(section, options, raw=False, vars=None, fallback=_UNSET)
+ Like get(), but convert value to a float.
+
+ getboolean(section, options, raw=False, vars=None, fallback=_UNSET)
+ Like get(), but convert value to a boolean (currently case
+ insensitively defined as 0, false, no, off for False, and 1, true,
+ yes, on for True). Returns False or True.
+
+ items(section=_UNSET, raw=False, vars=None)
+ If section is given, return a list of tuples with (name, value) for
+ each option in the section. Otherwise, return a list of tuples with
+ (section_name, section_proxy) for each section, including DEFAULTSECT.
+
+ remove_section(section)
+ Remove the given file section and all its options.
+
+ remove_option(section, option)
+ Remove the given option from the given section.
+
+ set(section, option, value)
+ Set the given option.
+
+ write(fp, space_around_delimiters=True)
+ Write the configuration state in .ini format. If
+ `space_around_delimiters' is True (the default), delimiters
+ between keys and values are surrounded by spaces.
+"""
+
+from collections.abc import MutableMapping
+from collections import ChainMap as _ChainMap
+import functools
+from .compat import io
+import itertools
+import os
+import re
+import sys
+import warnings
+
+
+__all__ = [
+ "NoSectionError",
+ "DuplicateOptionError",
+ "DuplicateSectionError",
+ "NoOptionError",
+ "InterpolationError",
+ "InterpolationDepthError",
+ "InterpolationMissingOptionError",
+ "InterpolationSyntaxError",
+ "ParsingError",
+ "MissingSectionHeaderError",
+ "ConfigParser",
+ "SafeConfigParser",
+ "RawConfigParser",
+ "Interpolation",
+ "BasicInterpolation",
+ "ExtendedInterpolation",
+ "LegacyInterpolation",
+ "SectionProxy",
+ "ConverterMapping",
+ "DEFAULTSECT",
+ "MAX_INTERPOLATION_DEPTH",
+]
+
+_default_dict = dict
+DEFAULTSECT = "DEFAULT"
+
+MAX_INTERPOLATION_DEPTH = 10
+
+
+# exception classes
+class Error(Exception):
+ """Base class for ConfigParser exceptions."""
+
+ def __init__(self, msg=''):
+ self.message = msg
+ Exception.__init__(self, msg)
+
+ def __repr__(self):
+ return self.message
+
+ __str__ = __repr__
+
+
+class NoSectionError(Error):
+ """Raised when no section matches a requested option."""
+
+ def __init__(self, section):
+ Error.__init__(self, 'No section: %r' % (section,))
+ self.section = section
+ self.args = (section,)
+
+
+class DuplicateSectionError(Error):
+ """Raised when a section is repeated in an input source.
+
+ Possible repetitions that raise this exception are: multiple creation
+ using the API or in strict parsers when a section is found more than once
+ in a single input file, string or dictionary.
+ """
+
+ def __init__(self, section, source=None, lineno=None):
+ msg = [repr(section), " already exists"]
+ if source is not None:
+ message = ["While reading from ", repr(source)]
+ if lineno is not None:
+ message.append(" [line {0:2d}]".format(lineno))
+ message.append(": section ")
+ message.extend(msg)
+ msg = message
+ else:
+ msg.insert(0, "Section ")
+ Error.__init__(self, "".join(msg))
+ self.section = section
+ self.source = source
+ self.lineno = lineno
+ self.args = (section, source, lineno)
+
+
+class DuplicateOptionError(Error):
+ """Raised by strict parsers when an option is repeated in an input source.
+
+ Current implementation raises this exception only when an option is found
+ more than once in a single file, string or dictionary.
+ """
+
+ def __init__(self, section, option, source=None, lineno=None):
+ msg = [repr(option), " in section ", repr(section), " already exists"]
+ if source is not None:
+ message = ["While reading from ", repr(source)]
+ if lineno is not None:
+ message.append(" [line {0:2d}]".format(lineno))
+ message.append(": option ")
+ message.extend(msg)
+ msg = message
+ else:
+ msg.insert(0, "Option ")
+ Error.__init__(self, "".join(msg))
+ self.section = section
+ self.option = option
+ self.source = source
+ self.lineno = lineno
+ self.args = (section, option, source, lineno)
+
+
+class NoOptionError(Error):
+ """A requested option was not found."""
+
+ def __init__(self, option, section):
+ Error.__init__(self, "No option %r in section: %r" % (option, section))
+ self.option = option
+ self.section = section
+ self.args = (option, section)
+
+
+class InterpolationError(Error):
+ """Base class for interpolation-related exceptions."""
+
+ def __init__(self, option, section, msg):
+ Error.__init__(self, msg)
+ self.option = option
+ self.section = section
+ self.args = (option, section, msg)
+
+
+class InterpolationMissingOptionError(InterpolationError):
+ """A string substitution required a setting which was not available."""
+
+ def __init__(self, option, section, rawval, reference):
+ msg = (
+ "Bad value substitution: option {!r} in section {!r} contains "
+ "an interpolation key {!r} which is not a valid option name. "
+ "Raw value: {!r}".format(option, section, reference, rawval)
+ )
+ InterpolationError.__init__(self, option, section, msg)
+ self.reference = reference
+ self.args = (option, section, rawval, reference)
+
+
+class InterpolationSyntaxError(InterpolationError):
+ """Raised when the source text contains invalid syntax.
+
+ Current implementation raises this exception when the source text into
+ which substitutions are made does not conform to the required syntax.
+ """
+
+
+class InterpolationDepthError(InterpolationError):
+ """Raised when substitutions are nested too deeply."""
+
+ def __init__(self, option, section, rawval):
+ msg = (
+ "Recursion limit exceeded in value substitution: option {!r} "
+ "in section {!r} contains an interpolation key which "
+ "cannot be substituted in {} steps. Raw value: {!r}"
+ "".format(option, section, MAX_INTERPOLATION_DEPTH, rawval)
+ )
+ InterpolationError.__init__(self, option, section, msg)
+ self.args = (option, section, rawval)
+
+
+class ParsingError(Error):
+ """Raised when a configuration file does not follow legal syntax."""
+
+ def __init__(self, source=None, filename=None):
+ # Exactly one of `source'/`filename' arguments has to be given.
+ # `filename' kept for compatibility.
+ if filename and source:
+ raise ValueError(
+ "Cannot specify both `filename' and `source'. " "Use `source'."
+ )
+ elif not filename and not source:
+ raise ValueError("Required argument `source' not given.")
+ elif filename:
+ source = filename
+ Error.__init__(self, 'Source contains parsing errors: %r' % source)
+ self.source = source
+ self.errors = []
+ self.args = (source,)
+
+ @property
+ def filename(self):
+ """Deprecated, use `source'."""
+ warnings.warn(
+ "The 'filename' attribute will be removed in future versions. "
+ "Use 'source' instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ return self.source
+
+ @filename.setter
+ def filename(self, value):
+ """Deprecated, user `source'."""
+ warnings.warn(
+ "The 'filename' attribute will be removed in future versions. "
+ "Use 'source' instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ self.source = value
+
+ def append(self, lineno, line):
+ self.errors.append((lineno, line))
+ self.message += '\n\t[line %2d]: %s' % (lineno, line)
+
+
+class MissingSectionHeaderError(ParsingError):
+ """Raised when a key-value pair is found before any section header."""
+
+ def __init__(self, filename, lineno, line):
+ Error.__init__(
+ self,
+ 'File contains no section headers.\nfile: %r, line: %d\n%r'
+ % (filename, lineno, line),
+ )
+ self.source = filename
+ self.lineno = lineno
+ self.line = line
+ self.args = (filename, lineno, line)
+
+
+# Used in parser getters to indicate the default behaviour when a specific
+# option is not found it to raise an exception. Created to enable `None' as
+# a valid fallback value.
+_UNSET = object()
+
+
+class Interpolation:
+ """Dummy interpolation that passes the value through with no changes."""
+
+ def before_get(self, parser, section, option, value, defaults):
+ return value
+
+ def before_set(self, parser, section, option, value):
+ return value
+
+ def before_read(self, parser, section, option, value):
+ return value
+
+ def before_write(self, parser, section, option, value):
+ return value
+
+
+class BasicInterpolation(Interpolation):
+ """Interpolation as implemented in the classic ConfigParser.
+
+ The option values can contain format strings which refer to other values in
+ the same section, or values in the special default section.
+
+ For example:
+
+ something: %(dir)s/whatever
+
+ would resolve the "%(dir)s" to the value of dir. All reference
+ expansions are done late, on demand. If a user needs to use a bare % in
+ a configuration file, she can escape it by writing %%. Other % usage
+ is considered a user error and raises `InterpolationSyntaxError'."""
+
+ _KEYCRE = re.compile(r"%\(([^)]+)\)s")
+
+ def before_get(self, parser, section, option, value, defaults):
+ L = []
+ self._interpolate_some(parser, option, L, value, section, defaults, 1)
+ return ''.join(L)
+
+ def before_set(self, parser, section, option, value):
+ tmp_value = value.replace('%%', '') # escaped percent signs
+ tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax
+ if '%' in tmp_value:
+ raise ValueError(
+ "invalid interpolation syntax in %r at "
+ "position %d" % (value, tmp_value.find('%'))
+ )
+ return value
+
+ def _interpolate_some( # noqa: C901
+ self, parser, option, accum, rest, section, map, depth
+ ):
+ rawval = parser.get(section, option, raw=True, fallback=rest)
+ if depth > MAX_INTERPOLATION_DEPTH:
+ raise InterpolationDepthError(option, section, rawval)
+ while rest:
+ p = rest.find("%")
+ if p < 0:
+ accum.append(rest)
+ return
+ if p > 0:
+ accum.append(rest[:p])
+ rest = rest[p:]
+ # p is no longer used
+ c = rest[1:2]
+ if c == "%":
+ accum.append("%")
+ rest = rest[2:]
+ elif c == "(":
+ m = self._KEYCRE.match(rest)
+ if m is None:
+ raise InterpolationSyntaxError(
+ option,
+ section,
+ "bad interpolation variable reference %r" % rest,
+ )
+ var = parser.optionxform(m.group(1))
+ rest = rest[m.end() :]
+ try:
+ v = map[var]
+ except KeyError:
+ raise InterpolationMissingOptionError(
+ option, section, rawval, var
+ ) from None
+ if "%" in v:
+ self._interpolate_some(
+ parser, option, accum, v, section, map, depth + 1
+ )
+ else:
+ accum.append(v)
+ else:
+ raise InterpolationSyntaxError(
+ option,
+ section,
+ "'%%' must be followed by '%%' or '(', " "found: %r" % (rest,),
+ )
+
+
+class ExtendedInterpolation(Interpolation):
+ """Advanced variant of interpolation, supports the syntax used by
+ `zc.buildout'. Enables interpolation between sections."""
+
+ _KEYCRE = re.compile(r"\$\{([^}]+)\}")
+
+ def before_get(self, parser, section, option, value, defaults):
+ L = []
+ self._interpolate_some(parser, option, L, value, section, defaults, 1)
+ return ''.join(L)
+
+ def before_set(self, parser, section, option, value):
+ tmp_value = value.replace('$$', '') # escaped dollar signs
+ tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax
+ if '$' in tmp_value:
+ raise ValueError(
+ "invalid interpolation syntax in %r at "
+ "position %d" % (value, tmp_value.find('$'))
+ )
+ return value
+
+ def _interpolate_some( # noqa: C901
+ self, parser, option, accum, rest, section, map, depth
+ ):
+ rawval = parser.get(section, option, raw=True, fallback=rest)
+ if depth > MAX_INTERPOLATION_DEPTH:
+ raise InterpolationDepthError(option, section, rawval)
+ while rest:
+ p = rest.find("$")
+ if p < 0:
+ accum.append(rest)
+ return
+ if p > 0:
+ accum.append(rest[:p])
+ rest = rest[p:]
+ # p is no longer used
+ c = rest[1:2]
+ if c == "$":
+ accum.append("$")
+ rest = rest[2:]
+ elif c == "{":
+ m = self._KEYCRE.match(rest)
+ if m is None:
+ raise InterpolationSyntaxError(
+ option,
+ section,
+ "bad interpolation variable reference %r" % rest,
+ )
+ path = m.group(1).split(':')
+ rest = rest[m.end() :]
+ sect = section
+ opt = option
+ try:
+ if len(path) == 1:
+ opt = parser.optionxform(path[0])
+ v = map[opt]
+ elif len(path) == 2:
+ sect = path[0]
+ opt = parser.optionxform(path[1])
+ v = parser.get(sect, opt, raw=True)
+ else:
+ raise InterpolationSyntaxError(
+ option, section, "More than one ':' found: %r" % (rest,)
+ )
+ except (KeyError, NoSectionError, NoOptionError):
+ raise InterpolationMissingOptionError(
+ option, section, rawval, ":".join(path)
+ ) from None
+ if "$" in v:
+ self._interpolate_some(
+ parser,
+ opt,
+ accum,
+ v,
+ sect,
+ dict(parser.items(sect, raw=True)),
+ depth + 1,
+ )
+ else:
+ accum.append(v)
+ else:
+ raise InterpolationSyntaxError(
+ option,
+ section,
+ "'$' must be followed by '$' or '{', " "found: %r" % (rest,),
+ )
+
+
+class LegacyInterpolation(Interpolation):
+ """Deprecated interpolation used in old versions of ConfigParser.
+ Use BasicInterpolation or ExtendedInterpolation instead."""
+
+ _KEYCRE = re.compile(r"%\(([^)]*)\)s|.")
+
+ def before_get(self, parser, section, option, value, vars):
+ rawval = value
+ depth = MAX_INTERPOLATION_DEPTH
+ while depth: # Loop through this until it's done
+ depth -= 1
+ if value and "%(" in value:
+ replace = functools.partial(self._interpolation_replace, parser=parser)
+ value = self._KEYCRE.sub(replace, value)
+ try:
+ value = value % vars
+ except KeyError as e:
+ raise InterpolationMissingOptionError(
+ option, section, rawval, e.args[0]
+ ) from None
+ else:
+ break
+ if value and "%(" in value:
+ raise InterpolationDepthError(option, section, rawval)
+ return value
+
+ def before_set(self, parser, section, option, value):
+ return value
+
+ @staticmethod
+ def _interpolation_replace(match, parser):
+ s = match.group(1)
+ if s is None:
+ return match.group()
+ else:
+ return "%%(%s)s" % parser.optionxform(s)
+
+
+class RawConfigParser(MutableMapping):
+ """ConfigParser that does not do interpolation."""
+
+ # Regular expressions for parsing section headers and options
+ _SECT_TMPL = r"""
+ \[ # [
+ (?P.+) # very permissive!
+ \] # ]
+ """
+ _OPT_TMPL = r"""
+ (?P