django 入门笔记:Admin 管理系统及表单

django 及 rest_framework 笔记链接如下:
django 入门笔记:环境及项目搭建
django 入门笔记:数据模型
django 入门笔记:视图及模版
django 入门笔记:Admin 管理系统及表单
django 入门笔记:通用视图类重构视图
django_rest_framework 入门笔记:Serializer
django_rest_framework 入门笔记:视图函数重构
django_rest_framework 入门笔记:分页,多条件筛选及权限认证设置
django 自带 user 字段扩展及头像上传

django 的强大之处还有自带后台管理系统,真心给力!!
这一部分将介绍 django 自带的后台管理系统,以及如何通过表单提交数据

一. django admin 后台管理系统
  1. 在后台管理系统注册创建的模型

    from django.contrib import admin
    from blog.models import Post, Category, Tag
    
    # 在应用目录下的 admin.py 文件中,对创建的模型进行注册,可以一起用列表注册,也可以分开注册
    admin.site.register([Post, Category, Tag])
    

    然后运行项目,python manager.py runserver 192.168.x.xxx:8080
    可以通过 "http://192.168.x.xxx:8080/admin" 打开 admin 管理系统,登录的账号密码就是我们第一部分通过命令行 createsuperuser时所创建的,登陆后我们可以找到站点管理,对模型进行管理操作

    admin 登录界面

    admin 主界面

    当然,django 自带的 admin 管理系统不止那么点功能,接着我们通过定义一些参数,来定制 admin 界面

  1. 自定义 admin
    # 在使用后台管理的时候,可能需要自己定制 admin 的显示内容,可以通过如下进行定制
    @admin.register(Post)
    class PostAdmin(admin.ModelAdmin)
     list_display = ['title', 'category', 'author'] # 需要展示的字段
     
    # 或者通过以下方式注册,效果是一样的
    class PostAdmin(admin.ModelAdmin)
     list_display = ['title', 'category', 'author'] 
     
    admin.site.register(Post, PostAdmin)
    
    @admin.register(Category)
    class CategoryAdmin(admin.ModelAdmin)
        # 显示的标签字段,字段不能是 ManyToManyField 类型
        list_display = ('title', 'publisher')
        
     # 设置每页显示多少条记录,默认是100条
        list_per_page = 20
        
        # 设置默认可编辑字段
        list_editable = ['title', 'author']
        
        # 排除一些不想被编辑的 fields, 没有在列表的不可被编辑
        fields = ('title', 'author')
        
        # 设置哪些字段可以点击进入编辑界面
        list_display_links = ('tag', 'title')
        
        # 进行数据排序,负号表示降序排序
        ordering = ('-id',)
        
        # 显示过滤器
        list_filter = ('author', 'title')
        
        # 显示搜索框,搜索框大小写敏感
        search_fields = ('title',)
        
        # 详细时间分层筛选
        date_hierarchy = 'create_time'
        
        # 增加多选框 filter_horizaontal 和 filter_vertical 作用相同,只是方向不同,只用于
        # ManyToManyField 类型的字段
        filter_horizontal = ('authors',)
        
    # 修改 admin 页面显示标题
    admin.site.site_header = "Blog Manager System"
    # 修改 admin 页面头部标题
    admin.site.site_title = "Blog Manager"
    

    修改以后,我们的界面可以看到是以下这样的


    修改后 admin 登录界面
    admin 管理界面

为了可以和用户进行交流,我们需要获取用户的一些评论之类的,所以我们需要通过表单让用户提交信息,接下来我们将了解下 django 的表单

二. django 表单
存在相应模型(POST 方式)
  1. 在应用文件夹下创建 forms.py 文件存放表单

    from django import forms
    from .models import Post
    
    # 表单类必须继承 forms.ModelForm 或者 forms.Form 类,如果有相应的模型,则使用 ModelForm 更方便
    class PostForm(forms.ModelForm):
        class Meta:
            # 表单对应的数据库模型
            model = Post
            # 指定表单需要显示的字段
            fields = ['title', 'body']
    
  2. 创建表单视图

    from django.shortcuts import render, redict
    from blog.models import Post
    from blog.forms import PostForm
    
    def new_post(request):
        # Http 请求包括 POST 和 GET 两种,一般提交数据都是用 POST 请求
        # 因此当 request.method 为 POST 的时候才需要处理表单数据
        if request.method = 'POST':
            # 用户提交的信息存在 request.POST 中,相当于一个字典取值
            form = PostForm(request.POST)
            # 判断表单是否有效,django 自动校验表单数据是否合理,根据模型的字段类型来判断
            if form.is_valid():
                # commit=False 表示只生成模型类的实例,不马上保存到数据库
                post = form.save(commit=Flase)
                # 将作者和文章进行关联
                post.author = request.user
                # 通过调用 save() 方法将数据存入数据库
                post.save()
                # return render('post_detail', pk=post.pk)
                # 如果模型类中定义了 get_absolute_url 方法,可以用以下方式跳转
                # 会直接跳转 get_absolute_url 方法所指向的地址
                return redirect(post)
     else:
            # 如果不是 POST 重定向到空白的新建页面
            form = PostForm()
     return render(request, 'blog/post_new.html', locals())
    
  3. 绑定 URL

    urlpatterns = [url(r'^post/new/$', views.new_post, name='new_post'),]
    
  4. 通过模版进行表单的前端渲染

    <form action="{% url 'blog:new_post' %}" method="post" >
        {# 防止被攻击,使表单更加安全 #}
        {% csrf_token %}
        <div class="row">
            <div class="col-md-12">
                <label for="{{ form.title.id_for_label }}">标题:</label>
                {# 根据模型的字段类型自动渲染成表单 #}
                {{ form.title }}
                {# 渲染表单对应的错误 #}
                {{ form.title.errors }}
            </div>
            
            <div class="col-md-12">
                <label for="{{ form.text.id_for_label }}">标题:</label>
                {{ form.body }}
                {{ form.body.errors }}
            </div>
            
            <div>
                <button type="submit" class="submit-btn">发表:</button>
            </div>
        </div>
    </form>
    

    我们打开界面可以看到新加文章的表单界面,当提交的信息发生错误的时候,就会显示错误让用户改正


    提交表单
    提交表单错误
不存在对应模型(POST 方式)
  1. 在 forms.py 中创建表单
    # 假设有个信息反馈的表单
    class ContractForm(forms.Form):
        subject = forms.CharField(max_length=100)
        email = forms.EmailField(required=False, label='Your Email')
        message = forms.CharField(widget=forms.Textarea(attrs={'clos': 80, 'rows': 20}))
        
        # 自定义校验规则,以 clean 开头,字段名结尾,校验时候自动调用方法
        # 例如过滤信息长度小于 4 个字的信息,提示用户修改
     def clean_message(self):
            message = self.cleaned_data['message']
            num_word = len(self.message.split())
            if num_word < 4:
                raise forms.ValidationError('Not Enough words')
            return message
    
  2. 创建表单视图
    def post_contract(request):
     if request.method = 'POST':
            form = ContractForm(request.POST)
            if form.is_valid():
                # 只打印查看提交的结果是否正确
                cd = form.cleaned_data
                print(cd)
                # 提交成功后跳转 home 页面,通过 spacename 和 name 值指定页面
                return redict('blog:home')
        else:
            # 不是 POST 方式则重定向到空白页面
            form = ContractForm()
     return render(request, 'blog/contact_post.html', locals())
    
  3. 绑定 URL
    urlpatterns = [url(r'^contract/$', 'contract_us.html', name='contract_us'),]
    
  4. 通过模版进行表单的前端渲染
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Contact us</title>
    </head>
    
    <body>
    <h1>Contact Us</h1>
        
    {% if form.errors %}
        <p style="color: red;">
            Please correct the error{{ form.errors|pluralize }} below.
        </p>
    {% endif %}
    
    <form action="" , method="post">
        {% csrf_token %}
        <table>
            {{ form.as_table }}
        </table>
        <input type="submit" value="Submit">
    </form>
    </body>
    </html>
    

打开反馈界面我们可以看到
提交反馈
提交反馈错误
类似搜索的表单(GET)
  1. 创建表单视图
    def search(request):
        # 获取到用户提交的搜索关键词,字典的键值同模版中的 name 属性值
        q = request.GET.get('q')
        error_message = ''
     # 根据 q 的值是否空设置相关信息
        if not q:
            error_message = 'Input Keyword'
            return render(request, 'blog/home.html', locals())
    
        # Q 对象用于包装查询表达式,其作用是为了提供复杂的查询逻辑
        post_list = Post.objects.filter(Q(title__icontains=q) | Q(body__icontains=q))
        return render(request, 'blog/home.html', locals())
    
  2. 绑定 URL
    urlpatterns = [url(r'^search/$', views.search, name='search'),]
    
  3. 通过模版进行表单的前端渲染
    {# ...... #}
    <div id="search-form" class="search-form">
     <form role="search" method="get" id="searchform" action="{% url 'blog:search' %}">
         <input type="search" name="q" placeholder="搜索" required>
         <button type="submit"><span class="ion-ios-search-strong"></span></button>
     </form>
    </div>
    {# ...... #}
    

    我们可以看到搜索框
    搜索表单

最后附上整个项目的地址:blog_project

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容