PythonWeb框架djiango第二章

PythonWeb框架djiango第二章

模版

在前面的案例中,我们都是通过HttpResponse对象来响应用户的请求,同时在响应时返回的是数据,并不是视图,在django中,我们可以定义模版,通过视图函数来为用户响应视图,视图默认定义在templates中,在settings.py中规定了默认查找视图的路径

EMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates']  # 这里规定默认在项目的templates目录中查找模版
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

方式1(推荐)

定义视图函数

def index(request):
    # render的第一个参数必须是request,参数2为响应的视图
    return render(request, "index.html")

定义路由

path("",user.userview.index)

定义模版

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方式2

def index2(request):
    # 通过模版引擎将指定的模版转为html
    html = render_to_string("index.html")
    # 通过response输出html
    return HttpResponse(html)

注意:需要导入reder_to_string

from django.template.loader import render_to_string

render方法详解

def render(
    request, template_name, context=None, content_type=None, status=None, using=None
):
    """
    Return an HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)

分析:

通过分析发现render方法是render_to_string的封装方式,当前在企业开发过程中采用render方法的比较多,推荐使用。

参数1: request

参数2: 模版名称,

参数3:context ,字典类型,是需要在模版中显示的数据

参数4: content_type可选参数。一个字符串,表示返回的HTTP响应的内容类型(MIME类型)。例如,'text/html''application/json'等。如果未提供,Django会根据模板文件的扩展名来猜测内容类型(默认为'text/html'

参数5: status可选参数。一个整数,表示HTTP响应的状态码。例如,200表示成功,404表示未找到等。如果未提供,Django将使用默认的200状态码。

参数6: using可选参数。一个字符串,表示用于加载模板的模板引擎的别名。如果未提供,Django将使用默认的模板引擎。

ef index(request):
    # render的第一个参数必须是request,参数2为响应的视图
    # 向作用域中存放id为100,在模版页中通过{{}}来获取数据
    context = {"id": 100}
    return render(request, "index.html",context = context)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>还原来到python世界</title>
</head>
<body>
<h1>欢迎来到python世界</h1>
<h2>{{ id }}</h2>
</body>
</html>

模版语法

{{contxt中字典的key}}

相等于vue中的文本插值的写法,可以在html任意位置使用

{%%}标签

标签用 {% %} 表示,用于执行一些逻辑操作,如循环、条件判断等

if elif else endif 条件选择
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>还原来到python世界</title>
</head>
<body>
<h1>欢迎来到python世界</h1>
<h2>{{ u_id }}</h2>
{% if u_id > 0 and u_id < 100 %}
    <p>The number {{ u_id }} is between 0 and 100.</p>
{% elif u_id > 100 and u_id < 1000 %}
    <p>The number {{ u_id }} is  between 100 and 1000.</p>
{% else %}
    <p>The number {{ u_id }} is not between 0 and 1000.</p>
{% endif %}
</body>
</html>

*注意: 判断时 > <等逻辑运算符要增加空格,否则报错

for

{% for %} 允许我们在一个序列上迭代。

与Python的 for 语句的情形类似,循环语法是 for X in Y ,Y是要迭代的序列而X是在每一个特定的循环中使用的变量名称。

每一次循环中,模板系统会渲染在 {% for %} 和 {% endfor %} 之间的所有内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>还原来到python世界</title>
</head>
<body>
<h1>欢迎来到python世界</h1>
<h2>{{ u_id }}</h2>
{% if u_id > 0 and u_id < 100 %}
    <p>The number {{ u_id }} is between 0 and 100.</p>
{% elif u_id > 100 and u_id < 1000 %}
    <p>The number {{ u_id }} is  between 100 and 1000.</p>
{% else %}
<p>The number {{ u_id }} is not between 0 and 1000.</p>
{% endif %}
<br>
<h1>用户列表</h1>
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
<h1>用户列表反向</h1>
<!-- 增加reversed可以对列表进行反向迭代-->
<ul>
{% for user in user_list reversed %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
</body>
</html>
ef index(request):
    # render的第一个参数必须是request,参数2为响应的视图
    # 向作用域中存放id为100,在模版页中通过{{}}来获取数据
    user_list = []
    i = 0
    for i in range(10):
        user_list.append({"id": i+100, "name": 'admin'+str(i)})

    ct = {"u_id": int(request.GET.get("id")), "user_list": user_list}
    return render(request, "index.html", ct)
{##}

Django 注释使用 {# #}。

常用标签
  • with 在页面中定义变量
  • {{url 路由名称}} 一般用在href中 一般用于跳转

url为路由反转的结果

<a href="{%url 路由名称 1%}"> 1为参数
<a href="{%url 路由名称 book_id=1%}"> resful的请求参数
<a href="{%url 路由名称}?id=1==">
过滤器
  • add
<h2>{{ u_id|add:10 }}</h2>

  • capfirst: 将变量的第一个字母转换为大写。

    {{ value|capfirst }}
    

    如果 value 是 “hello”,那么输出将是 “Hello”。

  • cut: 从字符串中移除指定的字符。

    {{ value|cut:" " }}
    

    如果 value 是 “hello world”,那么输出将是 “helloworld”(移除了空格)。

  • date: 格式化日期/时间值。

    {{ value|date:"Y-m-d" }}
    

    如果 value 是一个日期对象,那么输出将按照指定的格式显示。

  • length: 返回字符串、列表等的长度。

    {{ value|length }}
    

    如果 value['a', 'b', 'c'],那么输出将是 3。

  • lower: 将字符串转换为小写。

    {{ value|lower }}
    

    如果 value 是 “HELLO”,那么输出将是 “hello”。

  • upper: 将字符串转换为大写。

    {{ value|upper }}
    

模版结构

{%include “xxx.html”%}

{% include %} 标签允许在模板中包含其它的模板的内容。被引入的模版可以使用父模版中的变量

模版继承

模板可以用继承的方式来实现复用。

接下来我们先创建之前项目的 templates 目录中添加 base.html 文件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是父模版</h1>
<h2>模版继承测试</h2>
{% block main %}
<p>这是模版内容</p>
{% endblock %}
</body>
</html>

以上代码中,名为 main 的 block 标签是可以被继承者们替换掉的部分。

所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。

hello.html 中继承 base.html,并替换特定 block,hello.html 修改后的代码如下

{% extends 'base.html' %}

{% block main %}
  我是来自父模版的 {{ block.super }}
    <a href="base.html">百度</a>
{% endblock %}
静态文件

官网:https://docs.djangoproject.com/en/5.1/intro/tutorial06/

  1. 配置静态文件设置
    settings.py文件中,确保你已经配置了静态文件的设置。这包括STATIC_URLSTATICFILES_DIRS

    # settings.py
    STATIC_URL = '/static/'  # URL前缀,用于访问静态文件
    STATICFILES_DIRS = [
        BASE_DIR / "static",  # 静态文件的目录,可以包含多个目录
    ]
    

    BASE_DIR是Django自动生成的,指向你的项目根目录。

  2. 创建静态文件目录
    在你的项目根目录下创建一个名为static的文件夹(如果你的配置与上述示例一致)。然后,你可以在这个文件夹下组织你的静态文件,比如CSS、JavaScript和图片等。

  3. 在模板中加载静态文件
    在你的Django模板中,使用{% load static %}模板标签来加载静态文件。然后,使用{{ static 'path/to/your/file' }}来获取静态文件的URL。

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
     <link rel="stylesheet" href="{% static 'css/index.css'  %}">
</head>
<body>
<h1>这是父模版</h1>
<h2>模版继承测试</h2>
{% block main %}

<p>这是模版内容</p>
{% endblock %}
</body>
</html>

在settings.py中增加

"""
Django settings for djangoProject project.

Generated by 'django-admin startproject' using Django 4.2.16.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-@7y-i+smm-9vt#_h)1e5*r78(5@wfr6w!x_5+&17&3q&^xpq%w'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'djangoProject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates']
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            # 增加builtins可以在页面中去除`{%load static%}`
            'builtins': ['django.templatetags.static']
        },
    },
]

WSGI_APPLICATION = 'djangoProject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    BASE_DIR / "static",  # 静态文件的目录,可以包含多个目录
]

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

模型

模型安装和配置

  1. 安装PyMySQL

    (推荐用于Django项目,因为它是一个纯Python实现的MySQL客户端,兼容性好且易于安装):

    • 你可以通过pip来安装PyMySQL:

      pip install pymysql
      
  2. 在Django设置中使用PyMySQL:

    • 安装完PyMySQL后,你需要在Django的设置文件中(通常是settings.py

      )添加以下代码来告诉Django使用PyMySQL作为其数据库后端:

      import pymysql
      pymysql.install_as_MySQLdb()
      
    • 确保你的DATABASES配置指向你的MySQL数据库。

  3. python manage.py startapp appname

创建app

  1. 修改settings中的数据源的配置
ATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_python',
        'USER': 'root',
        'HOST': '127.0.0.1',
        'PASSWORD': 'xxx',
        'PORT': '3306'
    }
}
  1. 将app引入到模块中
NSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'dept'
]
  1. 创建模型
from django.db import models


# Create your models here.

class DeptModel(models.Model):
    name = models.CharField(max_length=20)
    sex = models.IntegerField(default=0)


class RoleModel(models.Model):
    name = models.CharField(max_length=20)
    flag = models.IntegerField(default=0)

  1. python manage.py makemigrations dept

通知django模型有修改,执行完成后在migration文件夹下生成变更记录

  1. python manage.py migrate dept

生成数据库中对应的表

单表crud

from django.shortcuts import render,HttpResponse
from .models import DeptModel
import json
# Create your views here.


# 创建DeptModel对象,默认包含了所有参数的构造方法,通过模型的save方法保持数据  相等于执行insert语句
def add_dept(request):
    dept = DeptModel(name='部门1', sex=1)
    dept.save()
    return HttpResponse('保持成功')


# all()相等于执行select * from ,返回集合
def dept_query(request):
    depts = DeptModel.objects.all();
    print(type(depts))
    for dept in depts:
        print(dept.id, dept.name, dept.sex)
    return HttpResponse('查询成功')


# 根据id查询单个对象,get返回对象  
def dept_query_one(request):
    # 获取单个对象,如果没有查询到对象,跑出异常,一般用户登录,通过try except来处理
    dept = DeptModel.objects.get(id=1)
    print(dept.id, dept.name, dept.sex)
    # 获取到集合 ,集合长度为1
    dept = DeptModel.objects.filter(id=1)
    print(dept)
    return HttpResponse('success')


# 更新
def dept_update(request):
    dept = DeptModel.objects.get(id=1)
    dept.name='helloWorld'
    dept.save()
    return HttpResponse('success')


# 删除
def dept_delete(request):
    dept = DeptModel.objects.get(id=2)
    dept.delete()
    return HttpResponse('success')

Meta

用于配置模型的其他信息

table_name: 指定模型对应的数据的名称

Field API

字段类默认小组件说明
AutoFieldN/A根据 ID 自动递增的 IntegerField
BigIntegerFieldNumberInput64 位整数,与 IntegerField 很像,但取值范围是 -9223372036854775808 到 9223372036854775807 。
BinaryFieldN/A存储原始二进制数据的字段。只支持 bytes 类型。注意,这个字段的功能有限。
BooleanFieldCheckboxInput真假值字段。如果想接受 null 值,使用 NullBooleanField 。
CharFieldTextInput字符串字段,针对长度较小的字符串。大量文本应该使用 TextField 。有个额外的必须参数:max_length ,即字段的最大长度(字符个数)。
DateFieldDateInput日期,在 Python 中使用 datetime.date 实例表示。有两个额外的可选参数: auto_now ,每次保存对象时自动设为当前日期 auto_now_add ,创建对象时自动设为当前日期。
DateTimeFieldDateTimeInput日期和时间,在 Python 中使用 datetime.datetime 实例表示。与 DateField 具有相同的额外参数。
DecimalFieldTextInput固定精度的小数,在 Python 中使用 Decimal 实例表示。有两个必须的参数: max_digits 和 decimal_places 。
DurationFieldTextInput存储时间跨度,在 Python 中使用 timedelta 表示。
EmailFieldTextInput一种 CharField ,使用 EmailValidator 验证输入。max_length 的默认值为 254 。
FileFieldClearableFileInput文件上传字段。详情见下面。
FilePathFieldSelect一种 CharField ,限定只能在文件系统中的特定目录里选择文件。
FloatFieldNumberInput浮点数,在 Python 中使用 float 实例表示。注意, field.localize 的值为 False 时,默认的小组件是 TextInput 。
ImageFieldClearableFileInput所有属性和方法都继承自 FileField ,此外验证上传的对象是不是有效的图像。增加了 height 和 width 两个属性。需要 Pillow 库支持。

字段选项

  • 通过字段选项,可以实现对字段的约束
  • 在字段对象时通过关键字参数指定
  • null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False
  • blank:如果为True,则该字段允许为空白,默认值是 False
  • 对比:null是数据库范畴的概念,blank是表单验证证范畴的
  • db_column:字段的名称,如果未指定,则使用属性的名称
  • db_index:若值为 True, 则在表中会为此字段创建索引
  • default:默认值
  • primary_key:若为 True, 则该字段会成为模型的主键字段
  • unique:如果为 True, 这个字段在表中必须有唯一值

外键ForeignKey

参数1: 关联的外键对应的模型名称,如果是不同app下,需要appname.模型名称

参数2: on_delete 级连删除策略

参数3:related_name 反向调用的属性名,默认是小写的模型名_set.all()可以获取全部,也可以过滤

from django.db import models


# Create your models here.

class DeptModel(models.Model):
    name = models.CharField(max_length=20)
    sex = models.IntegerField(default=0)


class RoleModel(models.Model):
    name = models.CharField(max_length=20)
    flag = models.IntegerField(default=0)


class UserModel(models.Model):
    name = models.CharField(max_length=200)
    pwd = models.CharField(max_length=200)
    real_name = models.CharField(max_length=200)
    # 外键定义 可以实现以对多
    dept = models.ForeignKey("DeptModel", on_delete=models.CASCADE)

# 喜能
def foreign_add(request):
    dept = DeptModel(name='测试部门1', sex=1)
    dept.save()
    user = UserModel(name='user1', pwd='password1', real_name='用户1')
    user.dept = dept
    user.save()
    return HttpResponse('success')


# 查询用户并关联显示部门
def query_user_dept(request):
    user = UserModel.objects.get(id=1)
    dept = user.dept
    print(dept)
    return HttpResponse('success')


# 反向关联查询
def query_dept_users(request):
    dept = DeptModel.objects.get(id=6)
    # print(dept.query)
    # 写法一,users是related_name定义的值
    # users = dept.users.all()
    # 如果realted_namem没有定义值,可以使用默认的模型名首字母小写_set
    # 注意这里模型不能大写  UserModel_set报错,必须是usermodel_set
    users = dept.usermodel_set.all()
    print(users)
    for user in users:
        print(user.id,user.name,user.real_name)
    return HttpResponse('success')

一对一 OneToOneField

class UserDetailModel(models.Model):
    address = models.CharField(max_length=200)
    user = models.OneToOneField("UserModel",on_delete=models.CASCADE)
# 根据userid获取明细信息
def one_to_none_get(request):
    user_detail = UserDetailModel.objects.get(id=1)
    print(user_detail.user.name)
    user = UserModel.objects.get(id=4)
    detail = user.userdetailmodel
    print(str(detail.address))
    return HttpResponse('success')

多对多ManyToManyField

def many_to_many_get(request):
    user = UserModel.objects.get(id=6)
    roles = user.roles.all()
    print(len(roles))
    role = RoleModel.objects.get(id=12)
    users = role.users.all()
    print(len(users))
    return HttpResponse('success')
# 保存多对多的数据
def one_to_noe_save(request):
    dept = DeptModel(name='odept')
    dept.save()
    user = UserModel(name='oneToOne',pwd='oneTowo')
    user.dept = dept
    role = RoleModel(name='role111')
    role.save()
    roles =set()
    roles.add(role)
    role2 = RoleModel(name='role222')
    role2.save()
    roles.add(role2)
    user.save()
    # 必须先保存role和user
    user.roles.add(role, role2)
    return HttpResponse('success')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_AndyLau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值