django admin后台管理
Xadmin组件: 参照django admin而来
如何使用django admin后台管理
- 在app01中的admin.py中注册想要管理的模型类(表)
- 注册超级用户: python admin.py createsuperuser
- admin会自动给所有注册了的模型表加一个s后缀
- admin会通过
url(r'^admin/', admin.site.urls),
语句, 给注册了的模型表自动生成增删改查四条url, - 路由分发本质: url函数嵌套
# app01-->admin.py
from django.contrib import admin
from app01 import models
# Register your models here.
admin.site.register(models.UserInfo)
'''
# 设置django admin后台表名显示
class UserInfo(AbstractUser):
...
class Meta:
verbose_name_plural = '用户表' # 显示结果: 用户表
# verbose_name = '用户表' # 显示结果: 用户表s
'''
数据录入
phone = models.BigIntegerField(null=True, blank=True)
# blank告诉admin后台管理中的phone可以为空, 不会影响数据库, 不需要执行迁移命令
文章表: 分类, 个人站点
用户和个人站点
文章与分类的关系
'''
{% for article_obj in article_queryset %}
<div class="media">
<h4 class="media-heading"><a href="">{{ article_obj.title }}</a></h4> # 标题
<div class="media-left media-middle">
<a href="#">
<img class="media-object" src="/static/img/default.jpg" alt="..." height="60"> # 图片
</a>
</div>
<div class="media-body">
{{ article_obj.digest }} # 摘要
</div>
<br>
{# 北京老雷 发布于 2019-12-10 21:09 评论(0)阅读(0)#}
<div>
<span><a href="">{{ article_obj.blog.userinfo.username }} </a></span> # 文章表跨到站点表跨到用户表查询用户名
<span>发布于 </span>
<span>{{ article_obj.create_time|date:'Y-m-d' }} </span> # 筛选器展示文章表中的创建时间
<span><span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_num }}) </span>
<span><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article_obj.up_num }})</span>
</div>
</div>
<hr>
{% endfor %}
'''
MEDIA用户配置及文件资源开放
网站所用到的静态文件统一放在static文件夹下
用户上传的静态文件也要用一个统一的文件夹存储
'''
# MEDIA用户配置: 能够将用户上传的所有静态文件统一放到指定的文件夹下
# settings.py
MEDIA_ROOT = os.path.join('media') # media文件夹-->avatar文件夹(upload_to参数控制)
# urls.py
...
from BBS import settings
from django.views.static import serve
urlpatterns = [
...
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}), # 固定写法, 将media文件夹的资源向外界开放
# url(r'^app01/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
# MEDIA_ROOT = os.path.join('app01'), # http://127.0.0.1:8000/app01/views.py/, 开放app01文件夹的资源
]
'''
图片防盗链
通过判断GET请求中的referer参数中的前缀url, 如果是本网站, 那么正常访问, 否则禁止
GET请求中的user-agent参数用来标识是否为浏览器
个人站点页面搭建
'''
# urls.py
url(r'^(?P<username>\w+)/$', views.site, name='username'),
# site.html
<head>
...
<link rel="stylesheet" href="/media/css/{{ user_obj.blog.site_theme }}"> <!--引入用户上传的css样式文件-->
</head>
'''
文章展示及侧边栏分类筛选
'''
# urls.py
from app01 import views
from django.views.static import serve
urlpatterns = [
...
url(r'^(?P<username>\w+)/$', views.site, name='username'),
# url(r'^(?P<username>\w+)/category/(?P<param>\d+)/', views.site),
# url(r'^(?P<username>\w+)/tag/(?P<param>\d+)/', views.site),
# url(r'^(?P<username>\w+)/archive/(?P<param>\w+)/', views.site),
# 正则表达式优化
url(r'^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<param>.*)/', views.site) # .*为贪婪模式(最大跨度)
]
# views.py
def site(request, username, **kwargs):
user_obj = models.UserInfo.objects.filter(username=username).first() # username由home页面对应的a标签发GET请求时传入
if not user_obj:
return render(request, 'error.html') # 返回404报错页面
blog = user_obj.blog # <class 'app01.models.Blog'>, blog为一个blog对象
article_list = models.Article.objects.filter(blog=blog) # 筛选出个人站点中所有文章
if kwargs:
condition = kwargs.get('condition') # condition为对应的a标签发GET请求时, src参数中表示筛选类别的第二段url
param = kwargs.get('param') # param为对应的a标签发GET请求时, src参数中表示筛选条件的第三段url
if condition == 'category':
article_list = article_list.filter(category_id=param)
elif condition == 'tag':
article_list = article_list.filter(tag__id=param)
else:
year, month = param.split('-') # 2019, 10
article_list = article_list.filter(create_time__year=year, create_time__month=month)
category_list = models.Category.objects.filter(blog=blog).annotate(num=Count('article')).values_list('name', 'num', 'pk')
# <QuerySet [('jason的分类一', 2, 1), ('jason的分类二', 1, 2), ('jason的分类三', 1, 3)]>, 后两个数字分别为该分组下的数量和主键
tag_list = models.Tag.objects.filter(blog=blog).annotate(num=Count('article')).values_list('name', 'num', 'pk')
# <QuerySet [('jason的标签一', 1, 1), ('jason的标签二', 2, 2), ('jason的标签三', 2, 3)]>, 后两个数字分别为该分组下的数量和主键
date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time'), num=Count('pk')).values_list('month', 'num')
# <QuerySet [(datetime.date(2019, 10, 1), 1), ...]>, 分别为日期, 数量, 用不到主键
return render(request, 'site.html', locals())
# site.html
{% for category in category_list %} # 渲染文章标签
<p><a href="/{{ username }}/category/{{ category.2 }}/{{ category.pk }}">{{ category.0 }} ({{ category.1 }})</a></p>
{% endfor %}
{% for tag in tag_list %} # 渲染文章分类
<p><a href="/{{ username }}/tag/{{ tag.2 }}">{{ tag.0 }} ({{ tag.1 }})</a></p>
{% endfor %}
{% for date in date_list %} # 渲染日期归档
<p><a href="/{{ username }}/archive/{{ date.0|date:'Y-m' }}">{{ date.0|date:'Y年m月' }} ({{ date.1 }})</a></p>
{% endfor %}
# date.0|date:'Y-m', 日期筛选器控制a标签发GET请求时第三段url的参数格式
'''