django admin后台管理

Xadmin组件: 参照django admin而来

如何使用django admin后台管理

  1. 在app01中的admin.py中注册想要管理的模型类(表)
  2. 注册超级用户: python admin.py createsuperuser
  3. admin会自动给所有注册了的模型表加一个s后缀
  4. admin会通过url(r'^admin/', admin.site.urls),语句, 给注册了的模型表自动生成增删改查四条url,
  5. 路由分发本质: 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 }}&nbsp;&nbsp;</a></span>  # 文章表跨到站点表跨到用户表查询用户名
            <span>发布于&nbsp;&nbsp;</span>
            <span>{{ article_obj.create_time|date:'Y-m-d' }}&nbsp;&nbsp;</span>  # 筛选器展示文章表中的创建时间
            <span><span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_num }})&nbsp;&nbsp;</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的参数格式
'''