Django笔记

未分类 2026-08-04 14
预计阅读时间:9 分钟

官方文档

# 在根目录创建Django项目
django-admin startproject mysite
# 启动Django
python manage.py runserver

一、应用

创建应用

  1. 在根目录执行

    ```bash python manage.py startapp polls

    该命令会产生如下结构:

    polls/ init.py admin.py apps.py migrations/ init.py models.py tests.py views.py ```

  2. mysiteurls.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), ] ```

  3. mysitesetting.py下载该app

    python INSTALLED_APPS = [ "polls.apps.PollsConfig", # 注册 "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ]

视图view

要创建一个视图,需要

  1. view文件写视图函数

    ```python from django.http import HttpResponse

    def index(request): return HttpResponse("Hello, world. You're at the polls index.") ```

  2. 在同appurls.py中注册

    ```python from django.urls import path

    from . import views

    urlpatterns = [ path("", views.index, name="index"), # 注册 # 分别是 对应的url 函数引用 名字 ] ```

模型model

Django默认SQLite

  • appmodel文件中编写数据库,一个类代表一个数据库表格,类的字段代表列。会默认构建主键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_length varchar(max_length)
      DateField 存储日期 date
      DateTimeField 存储日期和时间 datetime
      DecimalField 存储高精度数值,需指定 max_digits 和 decimal_places decimal(max_digits, decimal_places)
      EmailField 存储邮箱地址,自带格式校验 varchar(254)
      FileField 处理文件上传,需配置 MEDIA_ROOT 和 MEDIA_URL varchar(100)
      FloatField 存储浮点数 double
      IntegerField 存储整数 int
      JSONField 存储 JSON 数据,适合存放不固定结构的配置(Django 3.1+) json(MySQL 5.7+)
      PositiveIntegerField 存储正整数 int unsigned
      TextField 存储大段文本,无长度限制 longtext
      TimeField 存储时间 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=True DateField/DateTimeField 在创建对象时自动设为当前时间
      auto_now=True DateField/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

    1. 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 ```

    2. 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) # 返回列表:['...', '...'] ```

    3. 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 # 数据库层面自增 ) ```

    4. 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

    {% csrf_token %} {% for field in form %}
    {{ field.label_tag }} {{ field }} {{ field.errors }} {% if field.help_text %} {{ field.help_text }} {% endif %}
    {% endfor %}

    {% csrf_token %}
    {{ form.name.errors }}
    ```


本文由 tazume-sans 原创,转载请注明出处。

相关推荐