mirror of
https://github.com/django/django.git
synced 2025-08-03 18:38:50 +00:00
Used auto-numbered lists in documentation.
This commit is contained in:
parent
cf915cb513
commit
9b15ff08ba
36 changed files with 169 additions and 173 deletions
|
@ -62,9 +62,9 @@ startproject <startproject>`, these consist of two items listed in your
|
|||
|
||||
and these items in your :setting:`MIDDLEWARE` setting:
|
||||
|
||||
1. :class:`~django.contrib.sessions.middleware.SessionMiddleware` manages
|
||||
#. :class:`~django.contrib.sessions.middleware.SessionMiddleware` manages
|
||||
:doc:`sessions </topics/http/sessions>` across requests.
|
||||
2. :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` associates
|
||||
#. :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` associates
|
||||
users with requests using sessions.
|
||||
|
||||
With these settings in place, running the command ``manage.py migrate`` creates
|
||||
|
|
|
@ -86,11 +86,11 @@ use of Argon2 rather than the other algorithms supported by Django.
|
|||
|
||||
To use Argon2 as your default storage algorithm, do the following:
|
||||
|
||||
1. Install the `argon2-cffi library`_. This can be done by running ``pip
|
||||
#. Install the `argon2-cffi library`_. This can be done by running ``pip
|
||||
install django[argon2]``, which is equivalent to ``pip install argon2-cffi``
|
||||
(along with any version requirement from Django's ``setup.py``).
|
||||
|
||||
2. Modify :setting:`PASSWORD_HASHERS` to list ``Argon2PasswordHasher`` first.
|
||||
#. Modify :setting:`PASSWORD_HASHERS` to list ``Argon2PasswordHasher`` first.
|
||||
That is, in your settings file, you'd put::
|
||||
|
||||
PASSWORD_HASHERS = [
|
||||
|
@ -115,11 +115,11 @@ use it Django supports bcrypt with minimal effort.
|
|||
|
||||
To use Bcrypt as your default storage algorithm, do the following:
|
||||
|
||||
1. Install the `bcrypt library`_. This can be done by running ``pip install
|
||||
#. Install the `bcrypt library`_. This can be done by running ``pip install
|
||||
django[bcrypt]``, which is equivalent to ``pip install bcrypt`` (along with
|
||||
any version requirement from Django's ``setup.py``).
|
||||
|
||||
2. Modify :setting:`PASSWORD_HASHERS` to list ``BCryptSHA256PasswordHasher``
|
||||
#. Modify :setting:`PASSWORD_HASHERS` to list ``BCryptSHA256PasswordHasher``
|
||||
first. That is, in your settings file, you'd put::
|
||||
|
||||
PASSWORD_HASHERS = [
|
||||
|
@ -153,7 +153,7 @@ you'll subclass the appropriate algorithm and override the ``iterations``
|
|||
parameters. For example, to increase the number of iterations used by the
|
||||
default PBKDF2 algorithm:
|
||||
|
||||
1. Create a subclass of ``django.contrib.auth.hashers.PBKDF2PasswordHasher``::
|
||||
#. Create a subclass of ``django.contrib.auth.hashers.PBKDF2PasswordHasher``::
|
||||
|
||||
from django.contrib.auth.hashers import PBKDF2PasswordHasher
|
||||
|
||||
|
@ -166,7 +166,7 @@ default PBKDF2 algorithm:
|
|||
Save this somewhere in your project. For example, you might put this in
|
||||
a file like ``myproject/hashers.py``.
|
||||
|
||||
2. Add your new hasher as the first entry in :setting:`PASSWORD_HASHERS`::
|
||||
#. Add your new hasher as the first entry in :setting:`PASSWORD_HASHERS`::
|
||||
|
||||
PASSWORD_HASHERS = [
|
||||
'myproject.hashers.MyPBKDF2PasswordHasher',
|
||||
|
|
|
@ -176,16 +176,16 @@ trying to change has been altered in the meantime.
|
|||
|
||||
For example, consider the following exchange between the client and server:
|
||||
|
||||
1. Client requests ``/foo/``.
|
||||
2. Server responds with some content with an ETag of ``"abcd1234"``.
|
||||
3. Client sends an HTTP ``PUT`` request to ``/foo/`` to update the
|
||||
#. Client requests ``/foo/``.
|
||||
#. Server responds with some content with an ETag of ``"abcd1234"``.
|
||||
#. Client sends an HTTP ``PUT`` request to ``/foo/`` to update the
|
||||
resource. It also sends an ``If-Match: "abcd1234"`` header to specify
|
||||
the version it is trying to update.
|
||||
4. Server checks to see if the resource has changed, by computing the ETag
|
||||
#. Server checks to see if the resource has changed, by computing the ETag
|
||||
the same way it does for a ``GET`` request (using the same function).
|
||||
If the resource *has* changed, it will return a 412 status code,
|
||||
meaning "precondition failed".
|
||||
5. Client sends a ``GET`` request to ``/foo/``, after receiving a 412
|
||||
#. Client sends a ``GET`` request to ``/foo/``, after receiving a 412
|
||||
response, to retrieve an updated version of the content before updating
|
||||
it.
|
||||
|
||||
|
|
|
@ -651,19 +651,19 @@ Field name restrictions
|
|||
|
||||
Django places some restrictions on model field names:
|
||||
|
||||
1. A field name cannot be a Python reserved word, because that would result
|
||||
#. A field name cannot be a Python reserved word, because that would result
|
||||
in a Python syntax error. For example::
|
||||
|
||||
class Example(models.Model):
|
||||
pass = models.IntegerField() # 'pass' is a reserved word!
|
||||
|
||||
2. A field name cannot contain more than one underscore in a row, due to
|
||||
#. A field name cannot contain more than one underscore in a row, due to
|
||||
the way Django's query lookup syntax works. For example::
|
||||
|
||||
class Example(models.Model):
|
||||
foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
|
||||
|
||||
3. A field name cannot end with an underscore, for similar reasons.
|
||||
#. A field name cannot end with an underscore, for similar reasons.
|
||||
|
||||
These limitations can be worked around, though, because your field name doesn't
|
||||
necessarily have to match your database column name. See the
|
||||
|
@ -1307,11 +1307,11 @@ directly inherit its fields and managers.
|
|||
|
||||
The general rules are:
|
||||
|
||||
1. If you are mirroring an existing model or database table and don't want
|
||||
#. If you are mirroring an existing model or database table and don't want
|
||||
all the original database table columns, use ``Meta.managed=False``.
|
||||
That option is normally useful for modeling database views and tables
|
||||
not under the control of Django.
|
||||
2. If you are wanting to change the Python-only behavior of a model, but
|
||||
#. If you are wanting to change the Python-only behavior of a model, but
|
||||
keep all the same fields as in the original, use ``Meta.proxy=True``.
|
||||
This sets things up so that the proxy model is an exact copy of the
|
||||
storage structure of the original model when data is saved.
|
||||
|
|
|
@ -283,7 +283,7 @@ many-to-many relation to User, the following template code is optimal:
|
|||
|
||||
It is optimal because:
|
||||
|
||||
1. Since QuerySets are lazy, this does no database queries if 'display_inbox'
|
||||
#. Since QuerySets are lazy, this does no database queries if 'display_inbox'
|
||||
is False.
|
||||
|
||||
#. Use of :ttag:`with` means that we store ``user.emails.all`` in a variable
|
||||
|
|
|
@ -148,9 +148,9 @@ Instantiating, processing, and rendering forms
|
|||
|
||||
When rendering an object in Django, we generally:
|
||||
|
||||
1. get hold of it in the view (fetch it from the database, for example)
|
||||
2. pass it to the template context
|
||||
3. expand it to HTML markup using template variables
|
||||
#. get hold of it in the view (fetch it from the database, for example)
|
||||
#. pass it to the template context
|
||||
#. expand it to HTML markup using template variables
|
||||
|
||||
Rendering a form in a template involves nearly the same work as rendering any
|
||||
other kind of object, but there are some key differences.
|
||||
|
|
|
@ -319,7 +319,7 @@ may need some changes to adjust to the new semantics.
|
|||
These are the behavioral differences between using :setting:`MIDDLEWARE` and
|
||||
``MIDDLEWARE_CLASSES``:
|
||||
|
||||
1. Under ``MIDDLEWARE_CLASSES``, every middleware will always have its
|
||||
#. Under ``MIDDLEWARE_CLASSES``, every middleware will always have its
|
||||
``process_response`` method called, even if an earlier middleware
|
||||
short-circuited by returning a response from its ``process_request``
|
||||
method. Under :setting:`MIDDLEWARE`, middleware behaves more like an onion:
|
||||
|
@ -328,7 +328,7 @@ These are the behavioral differences between using :setting:`MIDDLEWARE` and
|
|||
that middleware and the ones before it in :setting:`MIDDLEWARE` will see the
|
||||
response.
|
||||
|
||||
2. Under ``MIDDLEWARE_CLASSES``, ``process_exception`` is applied to
|
||||
#. Under ``MIDDLEWARE_CLASSES``, ``process_exception`` is applied to
|
||||
exceptions raised from a middleware ``process_request`` method. Under
|
||||
:setting:`MIDDLEWARE`, ``process_exception`` applies only to exceptions
|
||||
raised from the view (or from the ``render`` method of a
|
||||
|
@ -336,7 +336,7 @@ These are the behavioral differences between using :setting:`MIDDLEWARE` and
|
|||
a middleware are converted to the appropriate HTTP response and then passed
|
||||
to the next middleware.
|
||||
|
||||
3. Under ``MIDDLEWARE_CLASSES``, if a ``process_response`` method raises
|
||||
#. Under ``MIDDLEWARE_CLASSES``, if a ``process_response`` method raises
|
||||
an exception, the ``process_response`` methods of all earlier middleware are
|
||||
skipped and a ``500 Internal Server Error`` HTTP response is always
|
||||
returned (even if the exception raised was e.g. an
|
||||
|
|
|
@ -119,7 +119,7 @@ Examples
|
|||
|
||||
You can use the :func:`redirect` function in a number of ways.
|
||||
|
||||
1. By passing some object; that object's
|
||||
#. By passing some object; that object's
|
||||
:meth:`~django.db.models.Model.get_absolute_url` method will be called
|
||||
to figure out the redirect URL::
|
||||
|
||||
|
@ -130,7 +130,7 @@ You can use the :func:`redirect` function in a number of ways.
|
|||
obj = MyModel.objects.get(...)
|
||||
return redirect(obj)
|
||||
|
||||
2. By passing the name of a view and optionally some positional or
|
||||
#. By passing the name of a view and optionally some positional or
|
||||
keyword arguments; the URL will be reverse resolved using the
|
||||
:func:`~django.urls.reverse` method::
|
||||
|
||||
|
@ -138,7 +138,7 @@ You can use the :func:`redirect` function in a number of ways.
|
|||
...
|
||||
return redirect('some-view-name', foo='bar')
|
||||
|
||||
3. By passing a hardcoded URL to redirect to::
|
||||
#. By passing a hardcoded URL to redirect to::
|
||||
|
||||
def my_view(request):
|
||||
...
|
||||
|
|
|
@ -34,20 +34,20 @@ How Django processes a request
|
|||
When a user requests a page from your Django-powered site, this is the
|
||||
algorithm the system follows to determine which Python code to execute:
|
||||
|
||||
1. Django determines the root URLconf module to use. Ordinarily,
|
||||
#. Django determines the root URLconf module to use. Ordinarily,
|
||||
this is the value of the :setting:`ROOT_URLCONF` setting, but if the incoming
|
||||
``HttpRequest`` object has a :attr:`~django.http.HttpRequest.urlconf`
|
||||
attribute (set by middleware), its value will be used in place of the
|
||||
:setting:`ROOT_URLCONF` setting.
|
||||
|
||||
2. Django loads that Python module and looks for the variable
|
||||
#. Django loads that Python module and looks for the variable
|
||||
``urlpatterns``. This should be a Python list of :func:`django.urls.path`
|
||||
and/or :func:`django.urls.re_path` instances.
|
||||
|
||||
3. Django runs through each URL pattern, in order, and stops at the first
|
||||
#. Django runs through each URL pattern, in order, and stops at the first
|
||||
one that matches the requested URL.
|
||||
|
||||
4. Once one of the URL patterns matches, Django imports and calls the given
|
||||
#. Once one of the URL patterns matches, Django imports and calls the given
|
||||
view, which is a simple Python function (or a :doc:`class-based view
|
||||
</topics/class-based-views/index>`). The view gets passed the following
|
||||
arguments:
|
||||
|
@ -60,7 +60,7 @@ algorithm the system follows to determine which Python code to execute:
|
|||
``kwargs`` argument to :func:`django.urls.path` or
|
||||
:func:`django.urls.re_path`.
|
||||
|
||||
5. If no URL pattern matches, or if an exception is raised during any
|
||||
#. If no URL pattern matches, or if an exception is raised during any
|
||||
point in this process, Django invokes an appropriate
|
||||
error-handling view. See `Error handling`_ below.
|
||||
|
||||
|
@ -718,11 +718,11 @@ Reversing namespaced URLs
|
|||
When given a namespaced URL (e.g. ``'polls:index'``) to resolve, Django splits
|
||||
the fully qualified name into parts and then tries the following lookup:
|
||||
|
||||
1. First, Django looks for a matching :term:`application namespace` (in this
|
||||
#. First, Django looks for a matching :term:`application namespace` (in this
|
||||
example, ``'polls'``). This will yield a list of instances of that
|
||||
application.
|
||||
|
||||
2. If there is a current application defined, Django finds and returns the URL
|
||||
#. If there is a current application defined, Django finds and returns the URL
|
||||
resolver for that instance. The current application can be specified with
|
||||
the ``current_app`` argument to the :func:`~django.urls.reverse()`
|
||||
function.
|
||||
|
@ -733,15 +733,15 @@ the fully qualified name into parts and then tries the following lookup:
|
|||
setting the current application on the :attr:`request.current_app
|
||||
<django.http.HttpRequest.current_app>` attribute.
|
||||
|
||||
3. If there is no current application, Django looks for a default
|
||||
#. If there is no current application, Django looks for a default
|
||||
application instance. The default application instance is the instance
|
||||
that has an :term:`instance namespace` matching the :term:`application
|
||||
namespace` (in this example, an instance of ``polls`` called ``'polls'``).
|
||||
|
||||
4. If there is no default application instance, Django will pick the last
|
||||
#. If there is no default application instance, Django will pick the last
|
||||
deployed instance of the application, whatever its instance name may be.
|
||||
|
||||
5. If the provided namespace doesn't match an :term:`application namespace` in
|
||||
#. If the provided namespace doesn't match an :term:`application namespace` in
|
||||
step 1, Django will attempt a direct lookup of the namespace as an
|
||||
:term:`instance namespace`.
|
||||
|
||||
|
|
|
@ -462,7 +462,7 @@ FAQ
|
|||
Setup
|
||||
-----
|
||||
|
||||
1. **I don't need multiple time zones. Should I enable time zone support?**
|
||||
#. **I don't need multiple time zones. Should I enable time zone support?**
|
||||
|
||||
Yes. When time zone support is enabled, Django uses a more accurate model
|
||||
of local time. This shields you from subtle and unreproducible bugs around
|
||||
|
@ -481,7 +481,7 @@ Setup
|
|||
For these reasons, time zone support is enabled by default in new projects,
|
||||
and you should keep it unless you have a very good reason not to.
|
||||
|
||||
2. **I've enabled time zone support. Am I safe?**
|
||||
#. **I've enabled time zone support. Am I safe?**
|
||||
|
||||
Maybe. You're better protected from DST-related bugs, but you can still
|
||||
shoot yourself in the foot by carelessly turning naive datetimes into aware
|
||||
|
@ -508,7 +508,7 @@ Setup
|
|||
one year is 2011-02-28 or 2011-03-01, which depends on your business
|
||||
requirements.)
|
||||
|
||||
3. **How do I interact with a database that stores datetimes in local time?**
|
||||
#. **How do I interact with a database that stores datetimes in local time?**
|
||||
|
||||
Set the :setting:`TIME_ZONE <DATABASE-TIME_ZONE>` option to the appropriate
|
||||
time zone for this database in the :setting:`DATABASES` setting.
|
||||
|
@ -519,7 +519,7 @@ Setup
|
|||
Troubleshooting
|
||||
---------------
|
||||
|
||||
1. **My application crashes with** ``TypeError: can't compare offset-naive``
|
||||
#. **My application crashes with** ``TypeError: can't compare offset-naive``
|
||||
``and offset-aware datetimes`` **-- what's wrong?**
|
||||
|
||||
Let's reproduce this error by comparing a naive and an aware datetime::
|
||||
|
@ -551,7 +551,7 @@ Troubleshooting
|
|||
datetime when ``USE_TZ = True``. You can add or subtract
|
||||
:class:`datetime.timedelta` as needed.
|
||||
|
||||
2. **I see lots of** ``RuntimeWarning: DateTimeField received a naive
|
||||
#. **I see lots of** ``RuntimeWarning: DateTimeField received a naive
|
||||
datetime`` ``(YYYY-MM-DD HH:MM:SS)`` ``while time zone support is active``
|
||||
**-- is that bad?**
|
||||
|
||||
|
@ -564,7 +564,7 @@ Troubleshooting
|
|||
In the meantime, for backwards compatibility, the datetime is considered to
|
||||
be in the default time zone, which is generally what you expect.
|
||||
|
||||
3. ``now.date()`` **is yesterday! (or tomorrow)**
|
||||
#. ``now.date()`` **is yesterday! (or tomorrow)**
|
||||
|
||||
If you've always used naive datetimes, you probably believe that you can
|
||||
convert a datetime to a date by calling its :meth:`~datetime.datetime.date`
|
||||
|
@ -623,7 +623,7 @@ Troubleshooting
|
|||
>>> local.date()
|
||||
datetime.date(2012, 3, 3)
|
||||
|
||||
4. **I get an error** "``Are time zone definitions for your database
|
||||
#. **I get an error** "``Are time zone definitions for your database
|
||||
installed?``"
|
||||
|
||||
If you are using MySQL, see the :ref:`mysql-time-zone-definitions` section
|
||||
|
@ -632,7 +632,7 @@ Troubleshooting
|
|||
Usage
|
||||
-----
|
||||
|
||||
1. **I have a string** ``"2012-02-21 10:28:45"`` **and I know it's in the**
|
||||
#. **I have a string** ``"2012-02-21 10:28:45"`` **and I know it's in the**
|
||||
``"Europe/Helsinki"`` **time zone. How do I turn that into an aware
|
||||
datetime?**
|
||||
|
||||
|
@ -649,7 +649,7 @@ Usage
|
|||
documentation of pytz contains `more examples`_. You should review it
|
||||
before attempting to manipulate aware datetimes.
|
||||
|
||||
2. **How can I obtain the local time in the current time zone?**
|
||||
#. **How can I obtain the local time in the current time zone?**
|
||||
|
||||
Well, the first question is, do you really need to?
|
||||
|
||||
|
@ -672,7 +672,7 @@ Usage
|
|||
|
||||
In this example, the current time zone is ``"Europe/Paris"``.
|
||||
|
||||
3. **How can I see all available time zones?**
|
||||
#. **How can I see all available time zones?**
|
||||
|
||||
pytz_ provides helpers_, including a list of current time zones and a list
|
||||
of all available time zones -- some of which are only of historical
|
||||
|
|
|
@ -63,12 +63,12 @@ as a shorter alias, ``_``, to save typing.
|
|||
global namespace, as an alias for ``gettext()``. In Django, we have chosen
|
||||
not to follow this practice, for a couple of reasons:
|
||||
|
||||
1. Sometimes, you should use :func:`~django.utils.translation.gettext_lazy`
|
||||
#. Sometimes, you should use :func:`~django.utils.translation.gettext_lazy`
|
||||
as the default translation method for a particular file. Without ``_()``
|
||||
in the global namespace, the developer has to think about which is the
|
||||
most appropriate translation function.
|
||||
|
||||
2. The underscore character (``_``) is used to represent "the previous
|
||||
#. The underscore character (``_``) is used to represent "the previous
|
||||
result" in Python's interactive shell and doctest tests. Installing a
|
||||
global ``_()`` function causes interference. Explicitly importing
|
||||
``gettext()`` as ``_()`` avoids this problem.
|
||||
|
@ -2073,13 +2073,13 @@ the order in which it examines the different file paths to load the compiled
|
|||
:term:`message files <message file>` (``.mo``) and the precedence of multiple
|
||||
translations for the same literal:
|
||||
|
||||
1. The directories listed in :setting:`LOCALE_PATHS` have the highest
|
||||
#. The directories listed in :setting:`LOCALE_PATHS` have the highest
|
||||
precedence, with the ones appearing first having higher precedence than
|
||||
the ones appearing later.
|
||||
2. Then, it looks for and uses if it exists a ``locale`` directory in each
|
||||
#. Then, it looks for and uses if it exists a ``locale`` directory in each
|
||||
of the installed apps listed in :setting:`INSTALLED_APPS`. The ones
|
||||
appearing first have higher precedence than the ones appearing later.
|
||||
3. Finally, the Django-provided base translation in ``django/conf/locale``
|
||||
#. Finally, the Django-provided base translation in ``django/conf/locale``
|
||||
is used as a fallback.
|
||||
|
||||
.. seealso::
|
||||
|
|
|
@ -140,18 +140,18 @@ Installing an official release with ``pip``
|
|||
|
||||
This is the recommended way to install Django.
|
||||
|
||||
1. Install pip_. The easiest is to use the `standalone pip installer`_. If your
|
||||
#. Install pip_. The easiest is to use the `standalone pip installer`_. If your
|
||||
distribution already has ``pip`` installed, you might need to update it if
|
||||
it's outdated. If it's outdated, you'll know because installation won't
|
||||
work.
|
||||
|
||||
2. Take a look at virtualenv_ and virtualenvwrapper_. These tools provide
|
||||
#. Take a look at virtualenv_ and virtualenvwrapper_. These tools provide
|
||||
isolated Python environments, which are more practical than installing
|
||||
packages systemwide. They also allow installing packages without
|
||||
administrator privileges. The :doc:`contributing tutorial
|
||||
</intro/contributing>` walks through how to create a virtualenv.
|
||||
|
||||
3. After you've created and activated a virtual environment, enter the command
|
||||
#. After you've created and activated a virtual environment, enter the command
|
||||
``pip install Django`` at the shell prompt.
|
||||
|
||||
.. _pip: https://pip.pypa.io/
|
||||
|
@ -191,10 +191,10 @@ Installing the development version
|
|||
If you'd like to be able to update your Django code occasionally with the
|
||||
latest bug fixes and improvements, follow these instructions:
|
||||
|
||||
1. Make sure that you have Git_ installed and that you can run its commands
|
||||
#. Make sure that you have Git_ installed and that you can run its commands
|
||||
from a shell. (Enter ``git help`` at a shell prompt to test this.)
|
||||
|
||||
2. Check out Django's main development branch like so:
|
||||
#. Check out Django's main development branch like so:
|
||||
|
||||
.. console::
|
||||
|
||||
|
@ -202,12 +202,12 @@ latest bug fixes and improvements, follow these instructions:
|
|||
|
||||
This will create a directory ``django`` in your current directory.
|
||||
|
||||
3. Make sure that the Python interpreter can load Django's code. The most
|
||||
#. Make sure that the Python interpreter can load Django's code. The most
|
||||
convenient way to do this is to use virtualenv_, virtualenvwrapper_, and
|
||||
pip_. The :doc:`contributing tutorial </intro/contributing>` walks through
|
||||
how to create a virtualenv.
|
||||
|
||||
4. After setting up and activating the virtualenv, run the following command:
|
||||
#. After setting up and activating the virtualenv, run the following command:
|
||||
|
||||
.. console::
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ User-uploaded content
|
|||
validate all user uploaded file content, however, there are some other steps
|
||||
you can take to mitigate these attacks:
|
||||
|
||||
1. One class of attacks can be prevented by always serving user uploaded
|
||||
#. One class of attacks can be prevented by always serving user uploaded
|
||||
content from a distinct top-level or second-level domain. This prevents
|
||||
any exploit blocked by `same-origin policy`_ protections such as cross
|
||||
site scripting. For example, if your site runs on ``example.com``, you
|
||||
|
@ -252,7 +252,7 @@ User-uploaded content
|
|||
from something like ``usercontent-example.com``. It's *not* sufficient to
|
||||
serve content from a subdomain like ``usercontent.example.com``.
|
||||
|
||||
2. Beyond this, applications may choose to define a whitelist of allowable
|
||||
#. Beyond this, applications may choose to define a whitelist of allowable
|
||||
file extensions for user uploaded files and configure the web server
|
||||
to only serve such files.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue