前言:本文是学习网易微专业的《python全栈工程师 - Django快速建站》课程的笔记,欢迎学习交流。同时感谢老师们的精彩传授!
models.py
:Course
增加两个字段:video = models.FileField(blank=True, upload_to='videos/')
attach = models.FileField(blank=True, upload_to=user_directory_path)
说明:这里
blank=True
都默认为空,是因为数据库已经有数据了,如果新增的字段不默认为空,则需要为它们添加数据,为图省事,这里都默认为空。
python3 manage.py makemigrations course
python3 manage.py migrate
settings.py
,配置文件存储位置MEDIA_URL='/media/'
MEDIA_ROOT=os.path.join(BASE_DIR, 'media')
forms.py
增加字段fields = ('title', 'overview', 'video', 'attach')
views.py
,修改类视图CourseCreateView
fields = ['title', 'overview', 'video', 'attach' ]
form = CourseCreatedForm(request.POST, request.FILES)
course_create.html
,修改模板
实操一: 上传课程文件
step1
:新增字段。编辑文件myproject/course/models.py
from django.db import models
from django.contrib.auth.models import User
# new
def user_directory_path(instance, filename):
return 'courses/user_{0}/{1}'.format(instance.user.id, filename)
class Course(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='course_user')
title = models.CharField(max_length=30)
overview = models.TextField()
created = models.DateTimeField(auto_now_add=True)
video = models.FileField(blank=True, upload_to='videos/') # new
attach = models.FileField(blank=True, upload_to=user_directory_path) # new
class Meta:
"""
内部类设置排序字段,以创建时间的倒序排序
"""
ordering = ('-created',)
def __str__(self):
return self.title
说明
1).新增函数user_directory_path
,返回附件的上传路径。
2).新增字段video、attach
,注意upload_to
的不同写法。
Step2
:迁移数据
python3 manage.py makemigrations course
python3 manage.py migrate
Step3
:配置文件存储位置。
# myproject/mysite/settings.py文件
.
.
.
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Step4
:创建目录myproject/media/
Step5
:增加字段。修改文件myproject/course/forms.py
from django import forms
from .models import Course
class CourseCreateForm(forms.ModelForm):
class Meta:
model = Course
fields = ('title', 'overview', 'video', 'attach') # new
Step6
:修改文件myproject/course/views.py
中的类视图CourseCreateView
.
.
.
class CourseCreateView(UserCourseMixin, CreateView):
fields = ['title', 'overview', 'video', 'attach'] # modified
template_name = 'course/course_create.html'
def post(self, request, *args, **kwargs):
form = CourseCreateForm(request.POST, request.FILES) #modified
if form.is_valid():
new_course = form.save(commit=False)
new_course.user = self.request.user
new_course.save()
return redirect('course:course_list')
return self.render_to_response({'form': form})
.
.
.
Step7
:修改模板文件myproject/templates/course/course_create.html
{% extends 'base.html' %}
{% block title %}Create Course{% endblock %}
{% block content %}
<div class="container">
<form action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
<div style="margin-top: 10px">
<div class="col-md-2 text-left">课程标题:div>
<div class="col-md-10 text-left">{{ form.title }}div>
div>
<div style="margin-top: 10px">
<div class="col-md-2 text-left">课程介绍:div>
<div class="col-md-10 text-left">{{ form.overview }}div>
div>
<div style="margin-top: 10px">
<div class="col-md-2 text-left">上传视频:div>
<div class="col-md-10 text-left">{{ form.video }}div>
div>
<div style="margin-top: 10px">
<div class="col-md-2 text-left">上传附件:div>
<div class="col-md-10 text-left">{{ form.attach }}div>
div>
<input type="submit" value="发布课程">
form>
div>
{% endblock %}
说明:
1).添加enctype="multipart/form-data"
属性,上传文件表单必须设置的,否则无法接收文件。
course_list.html
<a href="{% url 'course:course_detail' course.id %}">
<span class="glyphicon glyphicon-search" style="margin-left: 20px;">span>
a>
views.py
,创建类视图from django.views.generic import DetailView
class CourseDetailView(UserCourseMixin, DetailView)
course/course_detail.html
URL
mysite/urls.py
中为上传文件创建url
course/urls.py
配置查看路由实操二: 查看课程内容
Step1
:修改模板文件myproject/templates/course/course_list.html
,添加查看课程详情按钮。
.
.
.
<td>
<a href="{% url 'course:course_delete' course.id %}" class="delete" name="delete">
<span class="glyphicon glyphicon-trash" style="margin-left:20px;">span>
a>
<a href="{% url 'course:course_detail' course.id %}">
<span class="glyphicon glyphicon-search" style="margin-left:20px;">span>
a>
td>
tr>
{% endfor %}
table>
div>
<script src="{% static 'js/jquery-3.4.1.js' %}">script>
.
.
.
Step2
:创建类视图。修改文件myproject/course/view.py
from django.shortcuts import render
from django.views.generic import TemplateView, ListView, DetailView # modified
from .models import Course
from braces.views import LoginRequiredMixin
.
.
.
# new
class CourseDetailView(UserCourseMixin, DetailView):
template_name = 'course/course_detail.html'
Step3
:创建模板文件。myproject/templates/course/course_detail.html
{% extends 'base.html' %}
{% block title %}Course Detail{% endblock %}
{% block content %}
<div class="row vertical-middle-sm">
<h1 class="text-center">{{ object.title }}h1>
<p class="text-center">讲师:{{ object.user.username }}p>
<p>简介:{{ object.overview }}p>
{% if object.video %}
<div class="text-center">
<video src="{{ object.video.url }}" class="text-center" controls="controls" width="800">video>
div>
{% else %}
<p>没有视频p>
{% endif %}
{% if object.attach %}
<p>下载课件:<a href="{{ object.attach.url }}">{{ object.attach.name|slice:"15:" }}a>p>
{% endif %}
div>
{% endblock %}
说明:
1).由于类视图CourseDetailView
中没有声明类似这个变量context_object_name="courses"
,所以模板中渲染时用object
。
2).因为视频和附件可有可无,所以渲染模板时需要做if
判断。
3).slice:"15:"
中|
后面的是过滤器,类似切片,表示从第15个字符后开始显示。
Step4
:配置路由1,myproject/mysite/urls.py
:
from django.contrib import admin
from django.urls import path, include
# new
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls', namespace='blog')),
path('account/', include('account.urls', namespace='account')),
path('course/', include('course.urls', namespace='course')),
]
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) # new
配置路由2,myproject/course/urls.py
# -*- coding=utf-8 -*-
from django.urls import path
# from django.views.generic import TemplateView
from .views import CourseHome, CourseListView, CourseCreateView, CourseDeleteView, CourseDetailView #new
app_name = 'course'
urlpatterns = [
# path('', TemplateView.as_view(template_name='course/home.html')),
path('', CourseHome.as_view()),
path('course-list/', CourseListView.as_view(), name='course_list'),
path('course-create/', CourseCreateView.as_view(), name='course_create'),
path('course-delete//' , CourseDeleteView.as_view(), name='course_delete'),
path('course-detail//' , CourseDetailView.as_view(), name='course_detail'), #new
]