学习朔宁夫开发工程师课程笔记。
0架构:
01. MyDoc\PycharmProjects\ProjOnline,注册一个index app备主页用。
02. python manage.py startapp users, python manage.py startapp course. install apps.
03. total url
urlpatterns = [# http://127.0.0.1:8000/path("", include("index.urls", namespace="index")),path("admin/", admin.site.urls),path("user/", include("users.urls", namespace="user")),path("course/", include("course.urls", namespace="course")),
]
04. sub url 创建。
架构完成。
1 index_app编码:(main task:渲染主页。4个temp已经写好了,涉及2个文件夹’templates,static‘放到app目录下。删除temp下4个temp以外的文件。将temp文件夹复制到corse及user app下,然后3个app只保留相关temp即可。本次演示用默认的sqlite,不用mysql。setting LANGUAGE_CODE = "en-us" # "zh-hans" TIME_ZONE = "Asia/shanghai" # "UTC")
11. views 类视图
from django.shortcuts import render
from django.views import Viewclass IndexView(View):def get(self, request):return render(self.request, 'index.html', locals())
12. urls
from django.urls import pathfrom index.views import IndexViewapp_name = 'index'urlpatterns = [path("", IndexView.as_view(), name="home")
]
13. 加载static index.html
<!doctype html>
{% load static %}
<html lang="zxx">
修改为正确{% static 'subpath' %}
可创建一个新的base_template,把公用模块写成block,用于后续course继承。
2 user_app编码(①记录用户登录状态;②登录/注册按钮显示为用户名):
21. views
from django.shortcuts import render
from django.views import Viewclass LoginRegisterView(View):def get(self, request):return render(request, 'my-account.html')
22. url
from django.urls import pathfrom users.views import LoginRegisterViewapp_name = 'users'urlpatterns = [path("login_register/", LoginRegisterView.as_view(), name='login_register')
]
23. html相应post表单中加入登录或注册链接
24. proj层new utils pack/ new py: utils.py
import hashlibdef gen_md5(string: str) -> str:md5 = hashlib.md5()md5.update(string.encode('utf-8'))return md5.hexdigest()
25. models 迁移
from django.db import modelsclass User(models.Model):user_name = models.CharField(max_length=64, verbose_name="User's name", unique=True)password = models.CharField(max_length=128, verbose_name="User's password")token = models.CharField(max_length=256, verbose_name="User's token", null=True)class Meta:db_table = 'users'verbose_name = 'users'verbose_name_plural = verbose_namedef __str__(self):return self.user_name@classmethoddef get_list(cls, **kwargs):filters = {}if kwargs.get('user_name'):filters['user_name'] = kwargs.get('user_name')if kwargs.get('password'):filters['password'] = kwargs.get('password')return cls.objects.filter(**filters)
26. 完善views
import timefrom django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import Viewfrom users.models import User
from utils.utils import gen_md5class LoginRegisterView(View):def get(self, request):return render(self.request, 'my_account.html', locals())class LoginView(View):def post(self, request):name = self.request.POST.get('name')password = gen_md5(request.POST.get('password'))users = User.objects.filter(user_name=name, password=password) # querysetif users:user = users.filter()user.token = gen_md5(user.user_name) + str(time.time())user.save()self.request.session['user_name'] = user.user_nameself.request.session['user_token'] = user.tokenreturn redirect(reverse("index:home"))else:return HttpResponse("Invalid username or wrong password.")class RegisterView(View):def post(self, request):name = self.request.POST.get('name')password = gen_md5(request.POST.get('password'))users = User.objects.filter(user_name=name)if users:return HttpResponse("Occupied name.")User.create_one(user_name=name, password=password)return redirect(reverse("users:login_register"))
注意之后写的所有接口都需要从session中获取user name。
以下对主页写session验证(后端获取user name,前端作判断和选择展示):
27. index views
from django.shortcuts import render
from django.views import Viewclass IndexView(View):def get(self, request):user_name = self.request.session["user_name"]return render(self.request, 'index.html', locals())
28. index temps
<div class="register">{% if user_name %}{{ user_name }}{% else %}<a href="{% url 'users:login_register' %}" class="default-btn">Login / Register</a>{% endif %}</div>
3 course_app编码(①名称、分类、售价、日期;②可以admin后台管理;③验证登录,否则跳转;④查询页面有搜索及排序功能):
31. models 一对多,在多方 课程 写入外键。便于维护:将课程的固定信息和变动信息写成一对一的两张表。迁移。
from django.db import modelsclass CourseCategory(models.Model):category_name = models.CharField(max_length=32, unique=True, verbose_name='Category name')class Meta:db_table = 'course_category'verbose_name = 'course categories'verbose_name_plural = verbose_namedef __str__(self):return self.category_name@classmethoddef get_one_by_name(cls, category_name):return cls.objects.filter(category_name=category_name).first()@classmethoddef get_all(cls):return cls.objects.all()class Course(models.Model):name = models.CharField(max_length=32, unique=True, verbose_name='Course name')price = models.FloatField(verbose_name='Course price')category = models.ForeignKey(CourseCategory, on_delete=models.CASCADE)class Meta:db_table = 'course'verbose_name = 'Courses'verbose_name_plural = verbose_namedef __str__(self):return self.name@classmethoddef get_list(cls, **kwargs):# courses = [] # 实例化。避免报错。filters = {}if kwargs.get('name'):filters['name__contains'] = kwargs.get('name')if kwargs.get('category'):filters['category'] = kwargs.get('category')return cls.objects.filter(**filters)class CourseInfo(models.Model):start_date = models.DateField(verbose_name='Start date')end_date = models.DateField(verbose_name='End date')course = models.OneToOneField(Course, on_delete=models.CASCADE)class Meta:db_table = 'course_info'verbose_name = 'course info'verbose_name_plural = verbose_namedef __str__(self):return self.course.name
32. 视图类
from django.core.paginator import Paginator, InvalidPage
from django.shortcuts import render
from django.views import Viewfrom course.models import *
from djangoProject.settings import PAGE_SIZEclass CourseListView(View):def get(self, request):category_name = request.GET.get('category', "")name = request.GET.get('name', "")page_num = self.request.GET.get("page", 1)courses = Course.get_list(category_name=category_name, name=name)# 注意这里查询是有bug。若同时传了两个参数,则name优先。应当q查询。categories = CourseCategory.get_all()filters = {}if category_name:filters['category'] = CourseCategory.get_one_by_name(category_name)if name:filters['name'] = namecourses = Course.get_list(**filters)paginator = Paginator(courses, PAGE_SIZE)try:courses = paginator.page()except InvalidPage:courses = paginator.page(1)return render(request, 'courses.html', locals())
33. 课程详情页
models中写入course的get_one方法:
class Course(models.Model):name = models.CharField(max_length=32, unique=True, verbose_name='Course name')price = models.FloatField(verbose_name='Course price')category = models.ForeignKey(CourseCategory, on_delete=models.CASCADE)class Meta:db_table = 'course'verbose_name = 'Courses'verbose_name_plural = verbose_namedef __str__(self):return self.name@classmethoddef get_one(cls, category_id):try:return cls.objects.get(pk=category_id)except Exception:return None
写入courseinfo的查找方法:
class CourseInfo(models.Model):start_date = models.DateField(verbose_name='Start date')end_date = models.DateField(verbose_name='End date')course = models.OneToOneField(Course, on_delete=models.CASCADE)class Meta:db_table = 'course_info'verbose_name = 'course info'verbose_name_plural = verbose_namedef __str__(self):return self.course.name@classmethoddef get_list(cls, **kwargs):filters = {}if kwargs.get('course'):filters['course'] = kwargs.get('course')return cls.objects.filter(**filters)
视图类:
class CourseDetailView(View):def get(self, request, course_id):course = Course.get_one(course_id)course_info = CourseInfo.get_list(course=course)return render(self.request, "single-course.html", locals())
urls:
from django.urls import pathfrom course.views import CourseListView, CourseDetailViewapp_name = 'course'urlpatterns = [path('list/', CourseListView.as_view(), name='list'),path('detail/<course_id>/', CourseDetailView.as_view(), name='detail')
]
完善html
4 功能联调
41. course_app 下new middleware.py
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixinclass CourseDetailsMiddleware(MiddlewareMixin):def process_request(self, request):if "/course/detail/" in request.path:user_name = request.session["user_name"]if not user_name:return redirect(reverse("user:login_register"))
注册 setting
MIDDLEWARE = [,"course.middleware.CourseDetailsMiddleware",
]
“无论什么语言的后端,无非“增删改查”。”