学习朔宁夫开发工程师课程笔记。
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 View
class IndexView(View):
def get(self, request):
return render(self.request, 'index.html', locals())
12. urls
from django.urls import path
from index.views import IndexView
app_name = 'index'
urlpatterns = [
path("", IndexView.as_view(), name="home")
]
13. 加载static index.html
{% load static %}
修改为正确{% static 'subpath' %}
可创建一个新的base_template,把公用模块写成block,用于后续course继承。
2 user_app编码(①记录用户登录状态;②登录/注册按钮显示为用户名):
21. views
from django.shortcuts import render
from django.views import View
class LoginRegisterView(View):
def get(self, request):
return render(request, 'my-account.html')
22. url
from django.urls import path
from users.views import LoginRegisterView
app_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 hashlib
def gen_md5(string: str) -> str:
md5 = hashlib.md5()
md5.update(string.encode('utf-8'))
return md5.hexdigest()
25. models 迁移
from django.db import models
class 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_name
def __str__(self):
return self.user_name
@classmethod
def 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 time
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from users.models import User
from utils.utils import gen_md5
class 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) # queryset
if users:
user = users.filter()
user.token = gen_md5(user.user_name) + str(time.time())
user.save()
self.request.session['user_name'] = user.user_name
self.request.session['user_token'] = user.token
return 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 View
class IndexView(View):
def get(self, request):
user_name = self.request.session["user_name"]
return render(self.request, 'index.html', locals())
28. index temps
{% if user_name %}
{{ user_name }}
{% else %}
Login / Register
{% endif %}
3 course_app编码(①名称、分类、售价、日期;②可以admin后台管理;③验证登录,否则跳转;④查询页面有搜索及排序功能):
31. models 一对多,在多方 课程 写入外键。便于维护:将课程的固定信息和变动信息写成一对一的两张表。迁移。
from django.db import models
class 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_name
def __str__(self):
return self.category_name
@classmethod
def get_one_by_name(cls, category_name):
return cls.objects.filter(category_name=category_name).first()
@classmethod
def 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_name
def __str__(self):
return self.name
@classmethod
def 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_name
def __str__(self):
return self.course.name
32. 视图类
from django.core.paginator import Paginator, InvalidPage
from django.shortcuts import render
from django.views import View
from course.models import *
from djangoProject.settings import PAGE_SIZE
class 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'] = name
courses = 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_name
def __str__(self):
return self.name
@classmethod
def 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_name
def __str__(self):
return self.course.name
@classmethod
def 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 path
from course.views import CourseListView, CourseDetailView
app_name = 'course'
urlpatterns = [
path('list/', CourseListView.as_view(), name='list'),
path('detail//', 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 MiddlewareMixin
class 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",
]
“无论什么语言的后端,无非“增删改查”。”