Django项目开发技巧
当前项目结构:
djangotutorial/manage.py -> 管理 Django 项目的命令行工具mysite/ -> 项目的实际 Python 包__init__.py -> 标识 mysite 为 python 包的空文件settings.py -> Django 项目的配置文件urls.py -> Django 项目的 URL 声明asgi.py -> 运行在 ASGI 兼容的 Web 服务器上的入口wsgi.py -> 运行在 WSGI 兼容的Web服务器上的入口
时区
默认时区是美国,中国需要手动修改一下,比如:TIME_ZONE = 'Asia/Shanghai'
其他时区列表
修改时区的作用:自动转换显示时间、涉及定时任务时按当地时区执行、跨国系统确保所有用户看到统一逻辑时间、所有日志使用UTC时间等。
数据库配置
打开 mysite/settings.py
,默认情况下,DATABASES 配置使用 SQLite。
DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3","NAME": "mydatabase",}
}
通常, INSTALLED_APPS 默认包括了 Django 的自带应用,自行创建应用后需要在列表中添加应用名称注册一下。
默认开启的某些应用需要至少一个数据表,所以,在使用他们之前需要在数据库中创建一些表。请执行以下命令:python manage.py migrate
。 migrate 命令只会为在 INSTALLED_APPS 里声明了的应用进行数据库迁移。
1、创建模型,举例:
from django.db import modelsclass Question(models.Model):question_text = models.CharField(max_length=200)pub_date = models.DateTimeField("date published")class Choice(models.Model):question = models.ForeignKey(Question, on_delete=models.CASCADE)choice_text = models.CharField(max_length=200)votes = models.IntegerField(default=0)
2、使用 models.py 编写数据表结构的话,则需要激活模型: python manage.py makemigrations polls
,生成的迁移数据会储存在 polls/migrations/0001_initial.py 里
3、查看具体迁移命令对应的SQL语句:python manage.py sqlmigrate polls 0001
3、再次运行 migrate 命令,在数据库里创建新定义的模型的数据表:python manage.py migrate
4、后续改变模型需要这三步:
- 编辑
models.py
文件,改变模型。 - 运行
python manage.py makemigrations
为模型的改变生成迁移文件。 - 运行
python manage.py migrate
来应用数据库迁移。
视图
URL中获取参数
对应HTML文件中的链接构造如下:用{{ 变量名 }}
表示
URL构造比较推荐的做法是:
<!-- polls/templates/polls/detail.html -->
<!-- 方法1:直接使用视图传递的变量 -->
<a href="{% url 'polls:vote' question.id%}">投票</a>
或
<a href="{% url 'polls:vote' question_id=question.id ... %}">投票</a><!-- 方法2:使用模板循环中的变量(如在列表页) -->
{% for q in questions %}<a href="{% url 'polls:vote' q.id %}">为 {{ q.text }} 投票</a>
{% endfor %}<!-- 方法3:在 JavaScript 中使用 -->
<script>const voteUrl = "{% url 'polls:vote' 0 %}".replace('/0/', `/${questionId}/`);
</script>
完整语法结构:
{% url 'url-name' arg1 arg2 ... %}
或
{% url 'url-name' kwarg1=value1 kwarg2=value2 ... %}
{% url 'polls:vote' q.id %}
的解析过程:
-
解析命名空间和名称:
'polls:vote'
分解为:polls
→ 应用命名空间(定义在 urls.py 的app_name
)vote
→ URL 名称(定义在 path() 的name
参数)
-
匹配 URL 模式:
# polls/urls.py from django.urls import pathfrom . import viewsapp_name = "polls" # app_name 设置命名空间 urlpatterns = [path("<int:question_id>/vote/", views.vote, name="vote"), ]
-
参数处理:
q.id
的值会被插入到 URL 模式中的<int:question_id>
位置- 自动转换为整数类型(因为 URL 模式指定了
int:
转换器)
-
生成最终 URL:假设
q.id = 5
,则生成:/polls/5/votes/
快捷函数:render()
from django.shortcuts import renderfrom .models import Questiondef index(request):latest_question_list = ['数据1', '数据2']context = {"latest_question_list": latest_question_list}return render(request, "polls/index.html", context) # context这里可以用locals(),传递所有局部变量
表单
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset><legend><h1>{{ question.question_text }}</h1></legend>{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}{% for choice in question.choice_set.all %}<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}"><label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>{% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>
form
中的action
指定提交地址,匹配polls/urls.py
中的:path("<int:question_id>/vote/", views.vote, name="vote")
form
中的method
指定提交请求的方法为 post,匹配poll/views.py
中的:from django.http import HttpResponseRedirect from django.urls import reversedef vote(request, question_id):if request.method == 'POST':pk=request.POST["choice"] # 获取name为choice的元素值return HttpResponseRedirect(reverse("polls:results", args=(pk,))) # 如果pk=3, 表示重定向到 /polls/3/results/ 地址
forloop.counter
表示 for 标签已经循环多少次。
改良视图:使用通用视图
如果你发现,views.py 中有较多重复冗余的视图,如下所示:
def detail(request, question_id):return HttpResponse("You're looking at question %s." % question_id)def results(request, question_id):response = "You're looking at the results of question %s."return HttpResponse(response % question_id)def vote(request, question_id):return HttpResponse("You're voting on question %s." % question_id)
可以考虑改良一下:
- 首先,使用 DetailView 通用视图来替换我们的 detail() 和 results() 视图,打开 polls/urls.py 这个 URLconf 并将它修改成:
from django.urls import pathfrom . import viewsapp_name = "polls" urlpatterns = [path("", views.IndexView.as_view(), name="index"),path("<int:pk>/", views.DetailView.as_view(), name="detail"),path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),path("<int:question_id>/vote/", views.vote, name="vote"), ]
- 将删除旧的 index, detail, 和 results 视图,并用 Django 的通用视图代替。打开 polls/views.py 文件,并将它修改成:
from django.db.models import F from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views import genericfrom .models import Choice, Questionclass IndexView(generic.ListView):template_name = "polls/index.html" # 指定模板,不指定则默认用:<app name>/<model name>_list.htmlcontext_object_name = "latest_question_list" # 为context变量指定名称,不指定则默认: <model name>_listclass DetailView(generic.DetailView):model = Question # Django的数据模型template_name = "polls/detail.html" # 默认:<app name>/<model name>_detail.htmlclass ResultsView(generic.DetailView): # 都是DetailViewmodel = Questiontemplate_name = "polls/results.html"def vote(request, question_id):# same as above, no changes needed....
自定义界面风格
-
在你的
polls
目录下创建一个名为static
的目录 -
Django 的查找器会自动在每个
INSTALLED_APPS
中指定的应用的子文件中寻找名称为static
的特定文件夹(确保应用已经添加到INSTALLED_APPS
中)
-
在你刚创建的
static
文件夹中创建一个名为polls
的文件夹 (这一步是为了防止其他应用有同名文件而无法正确区分) ,再在polls
文件夹中创建一个名为style.css
的文件,文件路径为:polls/static/polls/style.css
,将自定义样式内容填入style.css
文件中,比如:li a {color: green; }
-
在
polls/templates/polls/index.html
的文件头添加以下内容:{% load static %}<link rel="stylesheet" href="{% static 'polls/style.css' %}">
{% static %}
模板标签会生成静态文件的绝对路径。PS:
{% static %}
模板标签在静态文件(例如样式表)中是不可用的,应使用相对路径。 -
运行查看效果:
python manage.py runserver
静态文件获取
静态文件是先检查项目文件夹中 settings.py 内的 STATICFILES_DIRS
配置(默认没有配置),再根据 settings.py 中 TEMPLATES
的 APP_DIRS
决定是否从应用文件夹中查找。举例:
-
使用项目级 static 文件,
/项目名/settings.py
中添加:STATICFILES_DIRS = [BASE_DIR / 'static', # 项目级的静态文件目录 ]
文件路径:
/项目名/static/style.css
html 文件中:{% load static %} <link rel="stylesheet" href="{% static 'style.css' %}">
-
使用应用内的 static 文件:
1、/项目名/settings.py
中确认:INSTALLED_APPS = [...'polls', # 在项目中注册应用 ] TEMPLATES = [ {...'APP_DIRS': True,... ]
2、html中调用:
- 文件路径1(推荐):
polls/static/polls/style.css
html中使用:<link rel="stylesheet" href="{% static 'polls/style.css' %}">
- 文件路径2:
polls/static/style.css
html中使用:<link rel="stylesheet" href="{% static 'style.css' %}">
(前提是项目没有配置或者项目static目录下没有同名文件)
- 文件路径1(推荐):
Django和pymongo搭建项目举例
基础步骤
-
创建虚拟环境并安装依赖
python -m venv myenv # 创建虚拟环境 source myenv/bin/activate # 激活环境 (Linux/macOS) # 或 myenv\Scripts\activate (Windows)pip install django pymongo dnspython # 安装核心依赖
-
创建 Django 项目和应用
django-admin startproject myproject cd myproject python manage.py startapp myapp
-
配置 MongoDB 连接
在myproject/settings.py
中添加:# 自定义 MongoDB 配置 MONGODB = {'HOST': 'your-cluster-url.mongodb.net','PORT': 27017,'USERNAME': 'your-username','PASSWORD': 'your-password','DATABASE': 'your-db-name','OPTIONS': {'ssl': True, # 如果使用 Atlas 需启用 SSL'authSource': 'admin',} }
-
创建数据库工具模块
在应用目录下创建db.py
:# myapp/db.py from pymongo import MongoClient from django.conf import settingsdef get_db():config = settings.MONGODBclient = MongoClient(host=config['HOST'],port=config['PORT'],username=config['USERNAME'],password=config['PASSWORD'],**config.get('OPTIONS', {}))return client[config['DATABASE']]
建议:用户名、密码等敏感信息可以使用.env环境配置文件脱敏处理。
-
.env
环境配置文件举例:# .env DEBUG=True SECRET_KEY=...# MongoDB Configuration MONGO_HOST=your-mongodb-host MONGO_PORT=27017 MONGO_USERNAME=your-username MONGO_PASSWORD=your-password MONGO_DATABASE=your-db-name MONGO_AUTH_SOURCE=admin MONGO_SSL=true
-
Git 忽略 .env 文件 (.gitignore)
-
读取环境配置数据
import os from dotenv import load_dotenv os.getenv('MONGO_USERNAME') MONGO_CONFIG = {'HOST': os.getenv('MONGO_HOST'),'PORT': int(os.getenv('MONGO_PORT', 27017)),'USERNAME': os.getenv('MONGO_USERNAME'),'PASSWORD': os.getenv('MONGO_PASSWORD'),'DATABASE': os.getenv('MONGO_DATABASE'),'OPTIONS': {'authSource': os.getenv('MONGO_AUTH_SOURCE', 'admin'),'ssl': os.getenv('MONGO_SSL', 'false').lower() == 'true',} }
使用示例
1. 视图操作 MongoDB
# myapp/views.py
from django.http import JsonResponse
from .db import get_dbdef create_item(request):db = get_db()collection = db['items']result = collection.insert_one({'name': request.POST.get('name'),'price': float(request.POST.get('price'))})return JsonResponse({'id': str(result.inserted_id)})def list_items(request):db = get_db()items = list(db['items'].find().limit(10))# 转换 ObjectId 为字符串for item in items:item['_id'] = str(item['_id'])return JsonResponse({'items': items})
2. 配置 URL 路由
# myapp/urls.py
from django.urls import path
from . import viewsurlpatterns = [path('items/', views.list_items),path('items/create/', views.create_item),
]# myproject/urls.py
from django.urls import includeurlpatterns = [path('api/', include('myapp.urls')),
]
运行项目
python manage.py runserver