# 在根目录创建Django项目
django-admin startproject mysite
# 启动Django
python manage.py runserver
一、应用
创建应用
-
在根目录执行
```bash python manage.py startapp polls
该命令会产生如下结构:
polls/ init.py admin.py apps.py migrations/ init.py models.py tests.py views.py ```
-
在
mysite的urls.py中注册该app```python
mysite/urls.py
from django.contrib import admin from django.urls import include, path
urlpatterns = [ path("polls/", include("polls.urls")), # 注册 path("admin/", admin.site.urls), ] ```
-
在
mysite的setting.py下载该apppython INSTALLED_APPS = [ "polls.apps.PollsConfig", # 注册 "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ]
视图view
要创建一个视图,需要
-
在
view文件写视图函数```python from django.http import HttpResponse
def index(request): return HttpResponse("Hello, world. You're at the polls index.") ```
-
在同
app的urls.py中注册```python from django.urls import path
from . import views
urlpatterns = [ path("", views.index, name="index"), # 注册 # 分别是 对应的url 函数引用 名字 ] ```
模型model
Django默认SQLite
-
在
app的model文件中编写数据库,一个类代表一个数据库表格,类的字段代表列。会默认构建主键id```python from django.db import models
class 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) ```
-
字段类型
Django 字段类型 用途说明 对应 MySQL 类型 BooleanField存储真/假值 tinyint(1)CharField存储较短字符串,需指定 max_lengthvarchar(max_length)DateField存储日期 dateDateTimeField存储日期和时间 datetimeDecimalField存储高精度数值,需指定 max_digits和decimal_placesdecimal(max_digits, decimal_places)EmailField存储邮箱地址,自带格式校验 varchar(254)FileField处理文件上传,需配置 MEDIA_ROOT和MEDIA_URLvarchar(100)FloatField存储浮点数 doubleIntegerField存储整数 intJSONField存储 JSON 数据,适合存放不固定结构的配置(Django 3.1+) json(MySQL 5.7+)PositiveIntegerField存储正整数 int unsignedTextField存储大段文本,无长度限制 longtextTimeField存储时间 time- 字段参数 参数 作用 null=True数据库层面允许存储 NULL 值(注意:CharField/TextField 不推荐与 null=True 并用) blank=True表单验证时允许字段为空(与 null 是不同概念) choices=CHOICES_TUPLE限定字段可选值,前端显示为下拉框,是枚举数据的最佳方案 default=value为字段设置默认值,应尽量设置以避免 NULL 引发的异常 db_index=True为该字段创建数据库索引,提升查询性能 unique=True确保字段值在整张表中唯一(如用户名、邮箱) primary_key=True将该字段设为主键(默认 Django 会自动创建 id 主键) max_length=整数字符串类型字段的最大长度(CharField 必填) max_digits=整数DecimalField 的总位数(必填) decimal_places=整数DecimalField 的小数位数(必填) auto_now_add=TrueDateField/DateTimeField 在创建对象时自动设为当前时间 auto_now=TrueDateField/DateTimeField 在每次保存对象时自动更新为当前时间 - Meta内部类:元数据配置在 Model 内部定义
class Meta,可以配置很多全局行为:```python class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField("date published")
class Meta: # 默认排序:按发布时间倒序 ordering = ['-pub_date'] # 数据库表名(默认是 app名_类名小写) db_table = 'my_question' # 联合唯一约束(例如,保证同一个用户下的同一篇文章标题唯一) unique_together = ['user', 'title'] # 联合索引(提升多条件查询的性能) indexes = [models.Index(fields=['pub_date', 'question_text'])]```
-
建议使用
__str__与get_absolute_url__str__:定义对象在 admin 后台、shell 调试时的显示内容,务必实现它。get_absolute_url:定义对象详情页的 URL。在模板中可以通过{% url %}反向解析,让代码更整洁,也符合 DRY(Don't Repeat Yourself)原则。
- 也可以在model类的内部封装一些可能用到的方法,当然数据层的方法不会太复杂
- 对model修改之后,执行
bash python manage.py makemigrations xxx # 可后接 --name xxx生成迁移文件。
检查无误后,运行
bash python manage.py migrate # 执行迁移 -
-
数据库的CRUD
-
CREATE
```bash
方式1:创建并保存
question = Question( question_text="What is Django?", pub_date=timezone.now() ) question.save() # 必须调用 save()
方式2:使用 create(一步到位)
question = Question.objects.create( question_text="What is Django?", pub_date=timezone.now() )
方式3:批量创建(bulk_create,性能高)
questions = [ Question(question_text=f"Question {i}", pub_date=timezone.now()) for i in range(100) ] Question.objects.bulk_create(questions) # 只执行一次 SQL ```
-
READ
```bash
基础读取,返回生成器--懒加载,链式调用
questions = Question.objects.all() # 可切片[0:10]
只取某些字段(values)
titles = Question.objects.values('id', 'question_text') # 返回字典列表:[{'id': 1, 'question_text': '...'}, ...] titles = Question.objects.values_list('id', 'question_text') # 返回元组列表:[(1, '...'), ...]
单个字段的元组可拍平
titles = Question.objects.values_list('question_text', flat=True) # 返回列表:['...', '...'] ```
-
UPDATE
```bash
方式1:获取->更新->保存
question = Question.objects.get(id=1) question.question_text = "Updated question" question.save(update_fields=['question_text']) # update_fields指定更新某些字段,没有则更新全部
方式2:F 表达式原子更新---建议!
from django.db.models import F Question.objects.filter(id=1).update( vote_count=F('vote_count') + 1 # 数据库层面自增 ) ```
-
DELETE
```bash
方式1:单个删除
question = Question.objects.get(id=1) question.delete() # 返回 (1, {'app.Question': 1})
方式2:批量删除
deleted_count = Question.objects.filter( pub_date__year=2020 ).delete() # 返回 (2, {'app.Question': 2})
更多采用软删除
```
-
管理员admin
-
创建管理员
bash python manage.py createsuperuser -
添加至admin界面
```python
admin.py
from django.contrib import admin
from .models import Question
注册
admin.site.register(Question) ```
二、前端渲染
在app内创建目录templates/polls
然后在此处写入html模板
此时在view函数写入
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by("-pub_date")[:5]
context = {"latest_question_list": latest_question_list}
# 返回渲染,传入request,html文件位置,字典格式的该模板所需的参数
return render(request, "polls/index.html", context)
表单form
-
表单层
建议创建
form.py文件单独管理```bash
forms.py
from django import forms
class ContactForm(forms.Form): # 继承自Form # 常用字段类型 name = forms.CharField(max_length=100, label='您的姓名', required=True) email = forms.EmailField(label='邮箱地址', required=False) age = forms.IntegerField(min_value=0, max_value=120, label='年龄') content = forms.CharField(widget=forms.Textarea, label='留言内容')
# 自定义验证方法:以 clean_ 开头,针对单个字段 def clean_name(self): data = self.cleaned_data['name'] if '测试' in data: raise forms.ValidationError('姓名中不能包含"测试"') return data # 全局验证:依赖多个字段 def clean(self): cleaned_data = super().clean() # 如果 age 和 name 有某种关联逻辑 return cleaned_data```
-
视图层
```bash
views.py
from django.shortcuts import render, redirect from .forms import ContactForm
def contact_view(request): if request.method == 'POST': # 1. 将 POST 数据绑定到表单 form = ContactForm(request.POST)
# 2. 验证数据是否合法(调用 is_valid()) if form.is_valid(): # 3. 获取清洗后的数据(字典) cleaned_data = form.cleaned_data print(cleaned_data['name'], cleaned_data['email']) # 4. 业务处理:发送邮件或存入数据库 # 5. 重定向到成功页面(防止重复提交) return redirect('success_url') else: # 验证失败,返回错误信息给前端 # 此时 form 带有 errors 属性 return render(request, 'contact.html', {'form': form}) else: # GET 请求:展示空表单(或初始数据) initial_data = {'name': '默认访客'} form = ContactForm(initial=initial_data) return render(request, 'contact.html', {'form': form})```
-
渲染层
```html
```
本文由 tazume-sans 原创,转载请注明出处。