一、博客案例
1.配置准备
#配置模板文件夹
'DIRS': [os.path.join(BASE_DIR,'templates')],
#导入数据库
import pymysql
pymysql.install_as_MySQLdb()
# 数据库配置文件准备
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myblog9_10',
'USER':'admin',
'PASSWORD':'qwe123',
'HOST':'127.0.0.1',
'POST':3306
}
}
#创建app,并分配路由
2.代码展示
- 首先要构建一个网站的大致思路
- 模板HTML文件
- 添加页面,列表页面,详情页面,索引页面
- 创建模型类和数据库,并存入类型。
- 接下来就是边写视图函数,边写跳转的页面
1.视图函数
from django.shortcuts import render,redirect,reverse
from django.http import HttpResponse
# Create your views here.
from .models import BlogModel
def index(request):
return render(request,'blog/demo_index.html')
def blog_add(request):
#访问页面
if request.method=='GET':
return render(request,'blog/demo_add.html')
# 如果是页面添加的的数据,则要得到
elif request.method=='POST':
title = request.POST.get('title')
content = request.POST.get('content')
blog = BlogModel(title=title,content=content)
blog.save()
b_list = BlogModel.objects.all()
return render(request,'blog/demo_list.html',context={'b_list':b_list})
def blog_show(request):
b_list = BlogModel.objects.all()
return render(request, 'blog/demo_list.html', context={'b_list': b_list})
def blog_detail(request,blog_id):
blog = BlogModel.objects.get(id = blog_id)
return render(request,'blog/demo_detail.html',context={'blog':blog})
def blog_delete(request,blog_id):
blog = BlogModel.objects.filter(id=blog_id)
# 在这里不能用get
if blog:
blog.delete()
return redirect(reverse('list')) #重定向,无法确定是哪一个过来的
else:
return HttpResponse('无法删除')
def blog_update(request,blog_id):
blog = BlogModel.objects.filter(id=blog_id)
if request.method=='GET':
return render(request,'blog/demo_update.html',context={'blog':blog})
elif request.method=='POST':
title = request.POST.get('title')
content = request.POST.get('content')
BlogModel.objects.filter(id = blog_id).update(title=title,content=content)
return redirect(reverse('update'))
2. demo_base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}
模板文件
{% endblock %}</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
3.demo_add.html
{% extends 'blog/demo_base.html' %}
{% block title %}
添加博客
{% endblock %}
{% block body %}
{# 防止跨域请求#}
<form action="{% url 'add' %}" method="post"> {% csrf_token %}
标题 <input type="text" id="title" name="title" placeholder="请输入文章标题"> <br>
内容 <textarea name="content" id="content" cols="30" rows="10" placeholder="请输入文章"></textarea> <br>
<button type="submit">发布文章</button>
<button type="reset">重置</button>
</form>
<br>
<a href="{% url 'index' %}">返回首页</a>
{% endblock %}
4.demo_detail.html
{% extends 'blog/demo_base.html' %}
{% block title %}
文章详情
{% endblock %}
{% block body %}
<h1>{{ blog.title }}</h1>
<p>{{ blog.content }}</p>
<br>
<a href="{% url 'list' %}">返回列表页</a>
{% endblock %}
5.demo_index.html
{% extends 'blog/demo_base.html' %}
{% block title %}
博客首页
{% endblock %}
{% block body %}
<p><a href="{% url 'add' %}">添加博客</a></p>
<p><a href="{% url 'list' %}">博客列表</a></p>
{% endblock %}
6.demo_list.html
{% extends 'blog/demo_base.html' %}
{% block title %}
博客列表
{% endblock %}
{% block body %}
<h1>文章列表</h1>
<table>
<tr>
<th>标题</th>
<th>操作</th>
</tr>
{% for b in b_list %}
<tr>
<td><a href="{% url 'detail' b.id %}">{{ b.title }}</a></td>
<td><a href="">编辑</a> <a href="{% url 'delete' b.id %}">删除</a></td>
</tr>
{% endfor %}
</table>
<a href="{% url 'index' %}">返回首页</a>
{% endblock %}
7.demo_update.html
{% extends 'blog/demo_base.html' %}
{% block title %}
修改博客
{% endblock %}
{% block body %}
{# 防止跨域请求#}
<form action="{% url 'update' blog.id %}" method="post"> {% csrf_token %}
标题 <input type="text" id="title" name="title" value="{{ blog.title }}"> <br>
内容 <textarea name="content" id="content" cols="30" rows="10">{{ blog.content }}</textarea> <br>
<button type="submit">修改文章</button>
</form>
<br>
<a href="{% url 'list' %}">返回列表页</a>
{% endblock %}
二、查询补充
from django.db.models import Count,Max,Min,Q,F,Avg,Sumdef model_info(request): # 聚合查询 res = Stu_datail.objects.all().aggregate(Avg('age')) #分组查询,根据学院ID,统计每个学院有多少个学生 res = Student.objects.values('dept_id').annotate(Count('dept_id')) #F查询,查询学号和学院ID号相等的数据 res = Student.objects.filter(s_id=F('dept_id')) Stu_datail.objects.all().update(age=F('age')+1) #Q查询 & | ~——与或取反 res = Student.objects.filter(Q(s_name='小黄') & Q(s_id=5)) res = Student.objects.filter(Q(s_name='小黄') | Q(s_id=5)) res = Student.objects.filter(Q(s_name='小黄') & ~Q(s_id=5)) print(res) return HttpResponse("数据查询成功")
三、请求与响应
1.request的对象内容
def index(request): print(request) #对象 print(request.path) #请求的路由 print(request.method) print(request.encoding) print(request.get_host()) #IP和端口 print(request.get_port()) #端口 return render(request,'get_post/index.html')
-
一般渲染页面用get方式,提交数据用post方式
-
用request.post.getlist()——获取多选的内容。
-
# 类视图函数——可以区分post和getfrom django.views import Viewclass Blog_update(View): def get(self): pass def post(self): pass#路由#views.Blog_update.as_view()
2.文件上传:
- 存储文件一般都不会存储在数据库中,而是存一个链接
settings文件配置
STATIC_URL = '/static/'STATICFILES_DIRS=[ os.path.join(BASE_DIR,'static')]MEDIA_ROOT=os.path.join(BASE_DIR,'static/media')
- 上传音频
from django.views import Viewimport osfrom myblog9_10.settings import MEDIA_ROOTclass Upload(View): def get(self,request): return render(request,'get_post/index.html') def post(self,request): f = request.FILES.get('file') #获取文件名 f_name=os.path.join(MEDIA_ROOT,f.name) #拼接文件名 with open(f_name,'wb+') as fp: for i in f.chunks(): #读取文件的内容 fp.write(i) return HttpResponse('当前文件上传完毕')
3.HTTP协议
可以返回一个json格式的数据。return JsonResponse({‘一个’:‘两盒’})——严格的键值对的形式。
客户端和服务器记录登陆状态、
4.cookie
import datetime# 设置cookiedef set_ck(request): response = HttpResponse('设置cookie') # response.set_cookie('name','anyan') # 浏览器就过期。 # response.set_cookie('name','anyan',max_age=5) # 浏览器打开5秒后就过期。 response.set_cookie('name','anyan',expires=datetime.datetime(2021,10,1)) #指定过期时间 return response #获取cookiedef get_ck(request): ck = request.COOKIES name = ck.get('name') return HttpResponse(name)# 删除cookiedef dele_ck(request): response = HttpResponse('删除cookie') response.delete_cookie('name') return response
5. session状态表单
- session存在服务器当中,cookie存在于客户端中。
# Create your views here.def home(request): username = request.session.get('username','用户未登录') if username=='用户未登录': return redirect(reverse('login')) return render(request,'form_session/home.html',context={'username':username})class Lodin(View): def get(self,request): return render(request,'form_session/login.html') def post(self,request): username = request.POST.get('user') request.session['username'] = username request.session.set_expiry(0)#0表示关闭页面就过期 return redirect(reverse('home'))def logout(request): request.session.flush() return redirect(reverse('home'))
6.生成表单
forms.py
from django import formsclass RegisterForm(forms.Form): username = forms.CharField(max_length=30,min_length=4) password = forms.CharField(max_length=16,min_length=6,widget=forms.PasswordInput(attrs={'placeholder':'请输入密码'})) password_confirm = forms.CharField(max_length=16,min_length=6,widget=forms.PasswordInput(attrs={'placeholder':'请再次输入密码'})) email = forms.EmailField()
视图函数
from .forms import RegisterFormfrom .models import *def logout(request): request.session.flush() return redirect(reverse('home'))class RegisterTest(View): def get(self,requset): form = RegisterForm() return render(requset,'form_session/register.html',context={'form':form}) def post(self,request): form = RegisterForm(request.POST) #获取表单数据 if form.is_valid(): #判断数据是否合法 username = form.cleaned_data.get('username') # 保存数据 pwd = form.cleaned_data.get('password') # 保存数据 pwd_confirm = form.cleaned_data.get('password_confirm') # 保存数据 email = form.cleaned_data.get('email') # 保存数据 if pwd==pwd_confirm: Usermodel.objects.create(username=username) else: return HttpResponse('用户注册失败') else: return HttpResponse('数据不合法')
四、中间件
创建中间件函数文件,并将文件添加到配置文件中的MIDDLEWARE
settings文件
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', 'myblog9_10.mymiddleware.MyException']
在中间件的地方加入直接返回视图的话,就到不了视图函数。
mymiddleware文件
from django.http import HttpResponsefrom django.utils.deprecation import MiddlewareMixin# 用已经定义好了的方式来改写class MyException(MiddlewareMixin): def process_request(self,request): print('中间件被调用') request.name = 'anyan' return None # return HttpResponse(111)# 用自身的魔法方法来修改class UserMiddleware(MiddlewareMixin): def __init__(self,get_response): self.get_response = get_response def __call__(self,request): #请求到达视图函数之前 username = request.session.get('username','用户未登录') if username!='用户未登录': setattr(request,'myuser',username) else: setattr(request,'myuser','用户未登录') print('==============request===========') response = self.get_response(request) print('==========response==========') return response
五、上下文处理器
创建上下文函数文件,并将文件添加到配置文件中的TEMPLATES
settings文件
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(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', 'myblog9_10.mycontext.my_user', ], }, },]
mycontext 文件
#可以在项目中的所有位置使用myuser这个属性def my_user(request): user = request.session.get('username','用户未登录') if user !='用户未登录': return {'myuser':user} else: return {'myuser':'用户未登录,请先登录!'}
1.admin
- 创建超级用户管理员——在run manage.py中运行,createsuperuser,
- 界面在admin视图函数中
管理界面中文显示——settings文件中
LANGUAGE_CODE = 'zh-Hans'TIME_ZONE = 'Asia/Shanghai'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = False
在管理后台的表中添加app中的其他表,要在app下的admin.py中修改数据如下
models.py文件
from django.db import models# Create your models here.class Usermodel(models.Model): username = models.CharField(max_length=20)#学院信息表class Department(models.Model): d_id = models.AutoField(primary_key=True) d_name = models.CharField(max_length=30,unique=True) def __str__(self): return f'd_id={self.d_id},d_name={self.d_name}'#学生表格class Student(models.Model): s_id = models.AutoField(primary_key=True) s_name = models.CharField(max_length=30) dept_id=models.ForeignKey('Department',on_delete=models.SET_NULL,null=True) def __str__(self): return f's_id={self.s_id},s_name={self.s_name},dept_id={self.dept_id}'#学生详情表class Stu_datail(models.Model): sd_id =models.AutoField(primary_key=True) age = models.IntegerField() sex = models.BooleanField(default=True) intro = models.TextField(null=True) s_id = models.OneToOneField('Student',on_delete=models.CASCADE) def __str__(self): return f'sd_id={self.sd_id},sd_name={self.sd_name},age={self.age},sex={self.sex},intro={self.intro}'# 学生课程表class Course(models.Model): c_id = models.AutoField(primary_key=True) c_name = models.CharField(max_length=30,unique=True) stu_course = models.ManyToManyField('Student') def __str__(self): return f'c_id={self.c_id},c_name={self.c_name}'
admin.py文件
from django.contrib import admin# Register your models here.from .models import Student,Usermodel,Stu_datail,Course,Departmentclass StudentAdmin(admin.ModelAdmin): list_display = ['s_id','s_name'] #显示字符,只显示名字和id,但是要注册进去 list_filter = ['s_id'] #设置过滤字段 search_fields = ['s_id'] #设置搜索字段 list_per_page = 2 #分页,一页两条数据class StuDetailAdmin(admin.ModelAdmin): fields = ['age','intro'] #属性显示的先后顺序,决定你要显示几个字段 #属性分组,与上面的显示方式二选一 fieldsets = [ ('第一列',{'fields':['age']}), ('第一列',{'fields':['intro','sex']}), ]#将表注册进后台管理中admin.site.register(Usermodel)admin.site.register(Stu_datail,StuDetailAdmin)admin.site.register(Student,StudentAdmin)admin.site.register(Course)admin.site.register(Department)