首页页面轮播课程需要在课程的model中添加is_banner字段,说明是否是轮播课程:
1 class Course(models.Model):
2 """课程"""
3 DEGREE_CHOICES = (
4 ('cj', '初级'),
5 ('zj', '中级'),
6 ('gj', '高级')
7 )
8
9 name = models.CharField('课程名', max_length=50)
10 desc = models.CharField('课程描述', max_length=300)
11 detail = models.TextField('课程详情')
12 degree = models.CharField('课程难度', choices=DEGREE_CHOICES, max_length=2)
13 learn_times = models.IntegerField('学习时长(分钟数)', default=0)
14 students = models.IntegerField('学习人数', default=0)
15 fav_nums = models.IntegerField('收藏人数', default=0)
16 click_nums = models.IntegerField('点击数', default=0)
17 image = models.ImageField('封面图', upload_to='courses/%Y/%m', max_length=100)
18 course_org = models.ForeignKey(CourseOrg, verbose_name='所属机构', on_delete=models.CASCADE, null=True, blank=True)
19 category = models.CharField('课程类别', max_length=20, default='')
20 tag = models.CharField('标签', max_length=10, default='')
21 teacher = models.ForeignKey(Teacher, verbose_name='机构讲师', on_delete=models.CASCADE, null=True, blank=True)
22 courseneed_know = models.CharField('课程须知', max_length=300, default='')
23 teacher_tellyou = models.CharField('老师告诉你', max_length=300, default='')
24 is_banner = models.BooleanField('是否轮播', default=False)
25 add_time = models.DateTimeField('添加时间', default=datetime.now)
26
27 class Meta:
28 verbose_name = '课程'
29 verbose_name_plural = verbose_name
30
31 # 获取章节数
32 def get_zj_nums(self):
33 return self.lesson_set.all().count()
34
35 # 获取学习用户
36 def get_learn_users(self):
37 return self.usercourse_set.all()[:5]
38
39 # 获取章节
40 def get_course_lesson(self):
41 return self.lesson_set.all()
42
43 def __str__(self):
44 return self.name
机构显示需要机构标签,在机构的model中添加tag字段:
1 class CourseOrg(models.Model):
2 """课程机构"""
3 CATEGORY_CHOICES = (
4 ('pxjg', '培训机构'),
5 ('gx', '高校'),
6 ('gr', '个人')
7 )
8 name = models.CharField('机构名称', max_length=50)
9 category = models.CharField('机构类别', max_length=20, choices=CATEGORY_CHOICES, default='pxjg')
10 desc = models.TextField('机构描述')
11 students = models.IntegerField('学习人数', default=0)
12 course_nums = models.IntegerField('课程数', default=0)
13 click_nums = models.IntegerField('点击数', default=0)
14 fav_nums = models.IntegerField('收藏数', default=0)
15 image = models.ImageField('封面图', upload_to='org/%Y/%m', max_length=100)
16 address = models.CharField('地址', max_length=150)
17 city = models.ForeignKey(CityDict, verbose_name='所在城市', on_delete=models.CASCADE)
18 tag = models.CharField('机构标签', max_length=10, default='全国知名')
19 add_time = models.DateTimeField('添加时间', default=datetime.now)
20
21 class Meta:
22 verbose_name = '课程机构'
23 verbose_name_plural = verbose_name
24
25 # 获取教师数量
26 def get_teacher_nums(self):
27 return self.teacher_set.all().count()
28
29 def __str__(self):
30 return self.name
迁移数据库。
首页的数据都是需要从后台获取的,先编写首页的接口:
1 class IndexView(View):
2 """首页"""
3 def get(self, request):
4 # 轮播图
5 all_banners = Banner.objects.all().order_by('index')
6
7 # 课程
8 courses = Course.objects.filter(is_banner=False)[:6]
9 # 轮播课程
10 banner_courses = Course.objects.filter(is_banner=True)[:3]
11
12 # 机构
13 orgs = CourseOrg.objects.all()[:15]
14 return render(request, 'index.html', {
15 'all_banners': all_banners,
16 'courses': courses,
17 'banner_courses': banner_courses,
18 'orgs': orgs
19 })
然后修改首页的url:
1 urlpatterns = [
2 path('', IndexView.as_view(), name='index'), # 首页
3 ]
修改前端首页页面中显示数据的代码:
1 {% extends 'base.html' %}
2
3 {% load staticfiles %}
4
5 {% block title %}
6 知能网 - 首页
7 {% endblock %}
8
9 {% block content %}
10 <div class="banner">
11 <div class="wp">
12 <div class="fl">
13 <div class="imgslide">
14 <ul class="imgs">
15 {# 遍历显示轮播图#}
16 {% for banner in all_banners %}
17 <li>
18 <a href="{{ banner.url }}">
19 <img width="1200" height="478" src="{{ MEDIA_URL }}{{ banner.image }}" />
20 </a>
21 </li>
22 {% endfor %}
23 </ul>
24 </div>
25 <div class="unslider-arrow prev"></div>
26 <div class="unslider-arrow next"></div>
27 </div>
28
29 </div>
30
31
32 </div>
33 <!--banner end-->
34 <!--feature start-->
35 <section>
36 <div class="wp">
37 <ul class="feature">
38 <li class="feature1">
39 <img class="pic" src="/static/images/feature1.png"/>
40 <p class="center">专业权威</p>
41 </li>
42 <li class="feature2">
43 <img class="pic" src="/static/images/feature2.png"/>
44 <p class="center">课程最新</p>
45 </li>
46 <li class="feature3">
47 <img class="pic" src="/static/images/feature3.png"/>
48 <p class="center">名师授课</p>
49 </li>
50 <li class="feature4">
51 <img class="pic" src="/static/images/feature4.png"/>
52 <p class="center">数据真实</p>
53 </li>
54 </ul>
55 </div>
56 </section>
57 <!--feature end-->
58 <!--module1 start-->
59 <section>
60 <div class="module">
61 <div class="wp">
62 <h1>公开课程</h1>
63 <div class="module1 eachmod">
64 <div class="module1_1 left">
65 <img width="228" height="614" src="/static/images/module1_1.jpg"/>
66 <p class="fisrt_word">名师授课<br/>专业权威</p>
67 <a class="more" href="{% url 'course:course_list' %}">查看更多课程 ></a>
68 </div>
69 <div class="right group_list">
70 <div class="module1_2 box">
71 <div class="imgslide2">
72 <ul class="imgs">
73 {# 遍历显示轮播课程#}
74 {% for banner_course in banner_courses %}
75 <li>
76 <a href="{% url 'course:course_detail' banner_course.id %}">
77 <img width="470" height="300" src="{{ MEDIA_URL }}{{ banner_course.image }}" />
78 </a>
79 </li>
80 {% endfor %}
81 </ul>
82 </div>
83 <div class="unslider-arrow2 prev"></div>
84 <div class="unslider-arrow2 next"></div>
85 </div>
86 {# 遍历显示课程#}
87 {% for course in courses %}
88 <div class="module1_{{ forloop.counter|add:2 }} box">
89 <a href="{% url 'course:course_detail' course.id %}">
90 <img width="233" height="190" src="{{ MEDIA_URL }}{{ course.image }}"/>
91 </a>
92 <div class="des">
93 <a href="{% url 'course:course_detail' course.id %}">
94 <h2 title="{{ course.name }}">{{ course.name }}</h2>
95 </a>
96 <span class="fl">难度:<i class="key">{{ course.get_degree_display }}</i></span>
97 <span class="fr">学习人数:{{ course.students }}</span>
98 </div>
99 <div class="bottom">
100 <span class="fl" title="慕课网">{{ course.course_org.name }}</span>
101 <span class="star fr">{{ course.fav_nums }}</span>
102 </div>
103 </div>
104 {% endfor %}
105 </div>
106 </div>
107 </div>
108 </div>
109 </section>
110 <section>
111 <div class="module greybg">
112 <div class="wp">
113 <h1>课程机构</h1>
114 <div class="module3 eachmod">
115 <div class="module3_1 left">
116 <img width="228" height="463" src="/static/images/module3_1.jpg"/>
117 <p class="fisrt_word">名校来袭<br/>权威认证</p>
118 <a class="more" href="{% url 'org:org_list' %}">查看更多机构 ></a>
119 </div>
120 <div class="right">
121 <ul>
122 {# 遍历显示机构#}
123 {% for org in orgs %}
124 <li class="{% if forloop.counter|divisibleby:5 %}five{% endif %}">
125 <a href="{% url 'org:org_home' org.id %}">
126 <div class="company">
127 <img width="184" height="100" src="{{ MEDIA_URL }}{{ org.image }}"/>
128 <div class="score">
129 <div class="circle">
130 <h2>{{ org.tag }}</h2>
131 </div>
132 </div>
133 </div>
134 <p><span class="key" title="{{ org.name }}">{{ org.name }}</span></p>
135 </a>
136 </li>
137 {% endfor %}
138 </ul>
139 </div>
140 </div>
141 </div>
142 </div>
143 </section>
144 {% endblock %}
145
146 {% block custom_js %}
147 <script type="text/javascript" src="/static/js/index.js"></script>
148 {% endblock %}
index.html
我们在登出然后登陆之后发现轮播图的数据不见了,需要修改登录接口中render首页的代码:
1 class LoginView(View):
2 """登录"""
3 def get(self, request):
4 return render(request, 'login.html')
5
6 def post(self, request):
7 # form实例化
8 login_form = LoginForm(request.POST)
9 if login_form.is_valid():
10 # form验证通过,获取用户提交的用户名和密码
11 user_name = request.POST.get('username', None)
12 pass_word = request.POST.get('password', None)
13
14 # 通过django的authenticate方法获取user对象,也就是验证用户是否存在
15 user = authenticate(username=user_name, password=pass_word)
16
17 if user is not None:
18 if user.is_active:
19 # 只有激活用户才能登录
20 # 验证通过,通过django的login方法去登录,然后返回首页
21 login(request, user)
22 return HttpResponseRedirect(reverse('index'))
23 else:
24 # 验证不通过,返回登录页面,并将错误信息返回去显示
25 return render(request, 'login.html', {'msg': '用户名或密码错误', 'login_form': login_form})
26 else:
27 # 验证不通过,返回登录页面,并将错误信息返回去显示
28 return render(request, 'login.html', {'msg': '用户名或密码错误', 'login_form': login_form})
29 else:
30 return render(request, 'login.html', {'login_form': login_form})
404、500页面,必须在setting.py中设置DEBUG = False:
1 DEBUG = False
2
3 ALLOWED_HOSTS = ['*']
4
5 # 静态文件
6 STATIC_URL = '/static/'
7 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
在设置DEBUG = False后,django就不会代管你的静态文件,所以要在urls.py文件中设置url处理静态文件的url:
1 urlpatterns = [
2 re_path(r'^static/(?P<path>.*)', serve, {"document_root": STATIC_ROOT}), # 静态文件显示
3 ]
然后将404、500页面的html文件放到templates下即可配置完成。
比如下面一段代码:
1 class LoginUnsafeView(View):
2 def get(self, request):
3 return render(request, "login.html", {})
4 def post(self, request):
5 user_name = request.POST.get("username", "")
6 pass_word = request.POST.get("password", "")
7
8 import MySQLdb
9 conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='root', db='mxonline', charset='utf8')
10 cursor = conn.cursor()
11 sql_select = "select * from users_userprofile where email='{0}' and password='{1}'".format(user_name, pass_word)
12
13 result = cursor.execute(sql_select)
14 for row in cursor.fetchall():
15 # 查询到用户
16 pass
17 print 'test'
用户在登录的时候用户名如果输入 ' OR 1=1, 密码随便输入,SQL语句就变成了这样:
select * from users_userprofile where email='' OR 1=1' and password='123',email='' or 1=1这条件就直接为True了,不用去执行后面的and语句了,那么是不是直接就将用户的信息拿到了呢,所以这种写法是非常危险的。
那么如何去防护呢?可以尽量不去使用SQL原生语句去获取数据,可以通过django的orm去查询数据,在登录的使用使用django的login函数,这个函数是安全的。
黑客将一段带有js代码的url发送给用户,用户点击这个url后发送请求到服务器,服务器返回数据给受害者,然后浏览器执行这段js脚本将用户的cookie信息发送给黑客,然后黑客拿着用户的cookie伪装成用户向服务器发送请求,这时黑客就可以进行任何攻击或者其他操作。
用户登录受信任的A服务器,服务器返回cookie,用户之后的每次请求都会带上cookie去访问A服务器,但是用户在同时的时候没有登出或者关闭A服务器的页面,直接去访问危险的B服务器,然后B服务器要求用户去访问A的一个url,这时信息就会泄露。
在每个form中加上{{ csrf_token }}即可