Django, as a powerful web application framework, has gradually become popular in recent years. More and more Python developers are embracing Django. , but also because of the many contents in Django, when everyone first enters Django, they always feel a little "a little bit overwhelmed" and don't know where to start. Or after an initial understanding, you are still not sure whether the current approach is elegant, how to organize the project, and how to make the code more reusable.
A good project structure is half the battle.
By default, the project structure generated by Django is roughly like this:
With As the number of applications in the project continues to increase, the number of packages in the local root directory will continue to increase, making it increasingly difficult to maintain. Therefore, we need to have a clear plan for the entire project and reasonably place each file.
If the project is small and you do not plan to reuse the Application in it, you can consider the following methods:
venv folder The virtualenv environment where the project is stored is optional and can be placed elsewhere.
database This App is specially used to store model, manage commands and some custom filters used in templates. It is stored in the project root directory.
docs and logs respectively store project-related documents and log files generated during runtime.
static stores static files, such as css/js/img/font, etc.
utils stores tool functions, classes used in the project, and some common modules, such as logger, etc.
templates stores template files. The parent template or templates inherited by multiple templates are placed in the root directory and named with names such as base for easy maintenance. The remaining templates are placed in folders with corresponding application names. middle.
The web directory stores all Applications. If there are many Applications, they can be divided into more packages for planning. Each package stores a type of Application.
In the Model module part, we are mainly concerned with the mapping of data to classes. Under normal circumstances, the classes corresponding to each table will be placed in a separate file, and Import the corresponding classes in models/__init__.py in order, so that when used in other places, they can be imported through from database.models import xxxx. When naming the classes, it is recommended to add the name of the project. For example, I have a project here with the name Cherry, then all classes are CherryLeaks, CherryVulns, etc. It will be clear at a glance during the reivew code and writing process, knowing that this class represents data.
It is recommended to add a separate manager for Models and implement the corresponding methods to avoid repeated operations.
In addition, there are some suggestions, which can be chosen according to the actual situation:
It is not recommended to use types such as foreign keys
Add is_deleted to each table, created_time, updated_time fields
Make good use of indexes
Most business logic should be placed in the View part, and this part should be the core. It is also recommended here to place all Views with similar functions in the same file. To facilitate future maintenance and development, this file should be placed in a package named "controller" or "view". For example, handling project-related routing is all placed in controller/project.py.
Prioritize using some of Django’s built-in View classes, such as ListView, TemplateView, etc. If you need to implement the View yourself, it is recommended to use Class-based view to encapsulate different request methods into different methods for future convenience. maintain.
For template files, the best way is to cut different pages and functions into different template files, and store them in folders according to the name of Application, so that in During later maintenance, you can quickly find the corresponding template file from each Application.
In addition, it is strongly recommended to use the template inheritance function. All pages are inherited from the parent template, and various blocks are used to expand the page. The block name of each position is defined in the parent template. Provides child template overrides. It is recommended to use a popular and short name for each block, such as: sidebar, script, header, main_content, page_title, page_description, etc.
For common functions, such as comment boxes, you can consider storing them in a separate file and loading them in through {% include 'filename.tpl.html' %} where needed. It should be noted that if you need to use the extends and include instructions at the same time, you must use them in a block, otherwise they will be invalid. The following examples are invalid:
should be used as follows:
The flexibility of the Python language makes us sometimes forget the parameter type or return type of a specific method when writing code. In this case, we need to use docstring to provide clear information annotation for each method so that others can develop and maintain it. Refer to this link, if you are using PyCharm, you can write auto-completion docstring.
In many cases, our methods need to return multiple values to the caller, or return to the front end through JSON. If data is returned randomly, it will lead to development chaos. , in the end we don’t even know what the method returns.
A better approach is to agree on the return format. For returning to the caller, simply return a tuple and write the meaning of each value in the docstring. In addition to returning results, sometimes we need to return an err to indicate whether a problem or exception occurred during data processing. Generally, there are several available methods:
Throw an exception through raise
Return through multiple return values, such as err, result = func()
Returned through an attribute in the class, for example instance = Class(); err = instance.error_message
These three methods have pros and cons and need to be selected according to the actual situation of the project, no matter which one is used Both methods need to be unified throughout the project and should not be mixed as much as possible;
For the JSON returned to the front end, it needs to be slightly more complicated, at least 2~3 fields must be returned:
#code is the status code returned by this call, which can be agreed upon based on the actual situation. The message is an easy-to-understand message of the status code that can be used by developers to debug and provide notifications to users. data is the actual returned data information. In many cases, this field may not be needed. The specific field format also needs to be agreed upon again based on the actual situation.
Elegant and simple routing ensures project quality and reduces maintenance costs.
Django has a powerful routing system and routing algorithm that can meet various needs in the business, and the configuration is flexible and simple. Each routing configuration file is URL PATH to Function/class mapping. Everything can be set up by yourself, without being subject to frameworks or other restrictions. You can refer to this section of the documentation about Django's request routing strategies.
In configuring routes, you can enclose some variables in angle brackets for easy use later. Some "Path Converters" can be used in angle brackets to specify variable types, such as str, int, slug, uuid, path. A complete URL routing file looks like the following:
In addition, you can also set regular matching in the route through re_path:
Sometimes, you may want to add a default route for some URLs. For example, when accessing /blog/, a default page will be returned, and when accessing /blog/page
As the project continues to expand, the routes used also There will continue to be more, so Django provides a route inclusion mechanism to facilitate us in organizing routes in different apps. Let’s take a look at a simple example:
In this example, all routes requesting community/* are handed over to aggregator.urls for parsing. Similarly, All contact/* requests are also handed over to another routing module for processing; if there are not so many Applications in your project and you still want to manage routing through include, you can use the following method:
Generally, each of our Django projects is composed of multiple Apps. If all App routes are placed in URLCONF_ROOT , over time this file will become more and more difficult to maintain and very confusing. Routes with the same name may be used in different apps, causing conflicts. In order to solve these problems, we can use "route inclusion" and "namespace" to solve it. Especially if you are maintaining an App that can be reused, in order to ensure the uniqueness of the route, the namespace is particularly important.
There are usually two types of namespaces: Application namespace and Instance namespace. For example, admin:index represents the index route of the admin namespace. For more information about this part, please refer to:Official Document
Application Namespace is easier to understand. It refers to the namespace at the application level. It is generally organized in the following way:
Instance Namespace refers to the instance. Level namespace is often used when an App is instantiated multiple times. In order to distinguish each instance, Instance Namespace needs to be introduced. Let’s take a look at the example in the official documentation:
You can see that the two routes author-polls and publisher-polls actually contain the same route, but specify different Namespace, this is the Instance level namespace, that is, the namespace of the object currently being accessed. Different user identities will get different namespaces when accessing different URLs. For example, visitors and administrators both access the page pointed to by polls:index, but due to different namespaces, they will get completely different results.
The above is the detailed content of What is Django development method. For more information, please follow other related articles on the PHP Chinese website!