Django基础篇 07-Django后端和html交互
一、上下文管理器
context_processors 执行顺序是 先执行views.py中代码,在views返回之前在走到TEMPLATES.OPTIONS.context_processors的方法中
1.1、在应用./user下新增context_process.py文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from . import models # 上下文管理器 def title_process(request): return {'title':'童玲的博客'} def category_process(request): categories = models.Category.objects.all() return {'categories':categories} def tag_process(request): tag_list = ['python','django','自动化测试'] return {'tag_list':tag_list}
1.2、在工程的sky/settings.py下添加如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
'user.context_process.category_process', 'user.context_process.tag_process', 'user.context_process.title_process'
整个settings.py的代码为:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
""" Django settings for sky project. Generated by 'django-admin startproject' using Django 3.2.6. For more information on this file, see https://docs.djangoproject.com/en/3.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.2/ref/settings/ """ import os 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/3.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-&9dmdfb5o_3ckyzo$s)b(-b37%x!f3l3jb7n+ukji5)$avh216' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = ['*'] #配置允许哪些ip访问的 *允许所有的 # Application definition INSTALLED_APPS = [ 'simpleui', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'user', 'order' ] #app注册 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 = 'sky.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(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', 'user.context_process.category_process', 'user.context_process.tag_process', 'user.context_process.title_process' ], }, }, ] # 设置模板的 前后端不分离的时候它有用 # context_processors 执行顺序是 先执行views.py中代码,在views返回之前在走到TEMPLATES.OPTIONS.context_processors的方法中 WSGI_APPLICATION = 'sky.wsgi.application' # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR,'db.sqlite3'), } } #配置数据库的地方 默认是sqlite3 # Password validation # https://docs.djangoproject.com/en/3.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/3.2/topics/i18n/ LANGUAGE_CODE = 'zh-Hans' # 设置语言,'en-us':英文,'zh-Hans':中文 TIME_ZONE = 'Asia/Shanghai' # 设置时区,'UTC':标准时区 格林威治时间,'Asia/Shanghai':亚洲上海时区 USE_I18N = True USE_L10N = True USE_TZ = False # 设置是否使用标准时区时间,我们设置为False 不适用标准时区 # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' # 设置静态文件目录 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
二、后端和html交互、重定向例子
2.1 编写前端表单代码:
样式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/add" method="post"> {% csrf_token %} <div>title: <input name = "title"></div> <div>content: <input name = "content"></div> <select name="category_id"> {% for category in categories %} <option value="{{ category.id }}">{{ category.name }}</option> {% endfor %} </select> <button type="submit">提交</button> </form> </body> </html>
{% csrf_token %} 为可以保存django后端返回的csrf token值 或者注释掉:settings.py中MIDDLEWARE[
'django.middleware.csrf.CsrfViewMiddleware'
]
settings.py代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
""" Django settings for sky project. Generated by 'django-admin startproject' using Django 3.2.6. For more information on this file, see https://docs.djangoproject.com/en/3.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.2/ref/settings/ """ import os 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/3.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-&9dmdfb5o_3ckyzo$s)b(-b37%x!f3l3jb7n+ukji5)$avh216' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = ['*'] #配置允许哪些ip访问的 *允许所有的 # Application definition INSTALLED_APPS = [ 'simpleui', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'user', 'order' ] #app注册 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 = 'sky.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(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', 'user.context_process.category_process', 'user.context_process.tag_process', 'user.context_process.title_process' ], }, }, ] # 设置模板的 前后端不分离的时候它有用 # context_processors 执行顺序是 先执行views.py中代码,在views返回之前在走到TEMPLATES.OPTIONS.context_processors的方法中 WSGI_APPLICATION = 'sky.wsgi.application' # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR,'db.sqlite3'), } } #配置数据库的地方 默认是sqlite3 # Password validation # https://docs.djangoproject.com/en/3.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/3.2/topics/i18n/ LANGUAGE_CODE = 'zh-Hans' # 设置语言,'en-us':英文,'zh-Hans':中文 TIME_ZONE = 'Asia/Shanghai' # 设置时区,'UTC':标准时区 格林威治时间,'Asia/Shanghai':亚洲上海时区 USE_I18N = True USE_L10N = True USE_TZ = False # 设置是否使用标准时区时间,我们设置为False 不适用标准时区 # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' # 设置静态文件目录 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
前端add_article.html代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/add" method="post"> {# {% csrf_token %}#} <div>title: <input name = "title"></div> <div>content: <input name = "content"></div> <select name="category_id"> {% for category in categories %} <option value="{{ category.id }}">{{ category.name }}</option> {% endfor %} </select> <button type="submit">提交</button> </form> </body> </html>
2.2 编写后端代码
views.py中添加视图函数:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.http import JsonResponse, HttpResponseRedirect from django.shortcuts import render from django.shortcuts import HttpResponse from django.shortcuts import get_object_or_404 from django.core.paginator import Paginator def add_article(request): if request.method.upper() == 'GET': return render(request,'add_article.html') title = request.POST.get('title') content = request.POST.get('content') category_id = request.POST.get('category_id') models.Article.objects.create(title=title,content=content,category_id=category_id) return HttpResponseRedirect('/')
2.3 urls.py注册路由
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.contrib import admin from django.urls import path from user import views urlpatterns = [ path('add',views.add_article) ]
三、ORM
/sky/user/models_test.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import os,django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sky.settings') django.setup() from user import models from django.db.models import Q """ 新增 """ # 新增 models.Category.objects.create(name = 'Oracle') c = models.Category(name='RabbitMQ') c.save() # 有外键的情况下 插入数据 models.Article.objects.create(title='orm学习', content='orm学习,content' ,read_count=1, category_id=1) # 指定外键 category = models.Category.objects.get(id =2) models.Article.objects.create(title='orm学习', content='orm学习,content' ,read_count=1, category_id=category.id) # 指定外键 models.Article.objects.create(title='orm学习', content='orm学习,content' ,read_count=1, category = category) # 指定外键 """ 修改 """ # 修改 # update user set name = 'tongling'; # update user set sex = 1 where age >19; c = models.Category.objects.get(id = 1) c.name = 'java' c.save() # 修改单条数据 models.Category.objects.all().update(name ='abc') # 修改全表数据的某个字段 # 按照过滤条件修改一批数据的 某些字段值 models.Category.objects.filter(name='abc').update(name='cc',age=13) """ 删除 """ c = models.Category.objects.get(id = 1) c.delete() # 删除一条数据 # 删除全表数据 models.Category.objects.all().delete() # 按照过滤条件删除一批数据 models.Category.objects.filter(id<5).delete() """ 复杂的查询 """ # 大于 小于 大于等于 in not 小于等于 或 print(models.Article.objects.filter(read_count__gt=0)) # 大于 print(models.Article.objects.filter(read_count__gte=0)) # 大于等于 print(models.Article.objects.filter(read_count__lt=0)) # 小于 print(models.Article.objects.filter(read_count__lte=0)) # 小于等于 print(models.Article.objects.exclude(read_count=0)) # read_count != 0 print(models.Article.objects.filter(id__in=[1,2,3])) # 在[1,2,3]中 print(models.Article.objects.filter(id=1).first()) # 查询出多条 取第一条 print(models.Article.objects.filter(title__contains='orm')) # like包含某个字符串的查询方式 print(models.Article.objects.filter(title__icontains='ORM')) # 忽略大小写 包含某个字符串的查询方式 print(models.Article.objects.filter(title__startswith='xxx')) # 以xx开头的查询条件 """ get()和 filter().first()的用法的比较,一般优先使用filter().first() """ models.Article.objects.get(id=1) # 如果id不存在,查询无数据 则此条语句会报错 需要try expection ,可以考虑使用filter().first()代替 query_set = models.Article.objects.filter(id=80) if query_set: article = query_set.first() # 第一条 query_set.last() # 最后一条 else: print('这条数据不存在') # read_count()>0 或者 title中包含orm的条件 query_set = models.Article.objects.filter( Q(read_count__gt=0) | Q(title__contains='orm')) print(query_set) print(models.Article.objects.filter(read_count__isnull=True)) #判断是否为null print(models.Article.objects.filter(title ='')) # 判断是否为空字符串
四、分页
/sky/user/views.py 添加视图函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def index(request): 2 articles = models.Article.objects.all() 3 page_num = request.GET.get('page',1) 4 limit = request.GET.get('limit',5) 5 page = Paginator(articles,limit) # 分页后的对象 6 articles = page.page(page_num) # 当前页的数据 7 8 # print(articles.has_next()) # 有没有下一页 有返回True 否则False 9 # print(articles.next_page_number()) # 获取下一页的页码,如果没有下一页 则会报错 10 # print(articles.has_other_pages()) # 有没有其他页,有则True,否则False 11 # print(articles.has_previous()) # 有没有上一页,有则True, 否则False 12 # print(articles.previous_page_number()) # 获取上一页的页码 13 # print(articles.number) # 获取当前页的页码 14 # print(articles.start_index()) # 当前页第一条数据的下标 15 # print(articles.end_index()) # 当前页最后一条数据的下标 16 # articles.paginator # 分页后的对象 相当于page 17 # print(page.num_pages) # 总共多少页 18 # print(page.page_range) # 分页的范围 1 2 3 4 5 ....
/sky/templates/index.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <div class="text-center mt-2 mt-sm-1 mt-md-0 mb-3 f-16"> 2 {% if articles.has_previous %} 3 <a class="text-success" href="?page={{ articles.previous_page_number }}">上一页</a> 4 {% else %} 5 <span class="text-secondary" title="当前页已经是首页">上一页</span> 6 {% endif %} 7 8 <span class="mx-2">第 {{ articles.number }} / {{ articles.paginator.num_pages }} 页</span> 9 {% if articles.has_next %} 10 <a class="text-success" href="?page={{ articles.next_page_number }}">下一页</a> 11 {% else %} 12 <a class="text-secondary" title="当前页已经是最后一页">下一页</a> 13 {% endif %} 14 15 </div>
效果图: