Django搭建个人博客:给文章加个漂亮的标题图

3584阅读 · 50评论 · 2019/02/27发布   前往评论

现在虽然博客的功能大都实现了,但是界面还是比较朴素,特别是首页的文章列表几乎全是文字,看多了难免疲劳。因此,给每个文章标题配一张标题图,不仅美观,用户也能通过图片快速了解文章内容。实际上大部分社交网站也都是这么干的,毕竟人的天性就是懒,能看图就坚决不看字。

上传用户头像章节中,我们已经接触过上传、展示图片了。标题图的实现也差不多,不同的是本章会更近一步,对图片进行缩放等处理,使页面整洁美观、并且高效。

准备工作

与用户头像类似,标题图是属于每篇博文自己的“资产”,因此需要修改model,新建一个字段:

article/models.py

class ArticlePost(models.Model):
    ...

    # 文章标题图
    avatar = models.ImageField(upload_to='article/%Y%m%d/', blank=True)

    ...

注意上传地址中的%Y%m%d是日期格式化的写法。比如上传时间是2019年2月26日,则标题图会上传到media/article/20190226这个目录中。

记得数据迁移

标题图通常在创建新文章的时候就设置好了,而新文章是通过表单上传到数据库中的。因此接下来就是修改发表文章的表单类

article/forms.py

...
class ArticlePostForm(forms.ModelForm):
    class Meta:
        ...
        fields = ('title', 'body', 'tags', 'avatar')

增加了avatar字段而已,没有新内容。

下一步就是修改视图。因为POST的表单中包含了图片文件,所以要将request.FILES也一并绑定到表单类中,否则图片无法正确保存:

article/views.py

...
def article_create(request):
    if request.method == "POST":
        # 增加 request.FILES
        article_post_form = ArticlePostForm(request.POST, request.FILES)

        ...

很好,功能差不多已经通了,接下来就是对图片进行处理。

处理图片

写代码之前先构思一下需要进行怎样的处理:

  • 标题图对画质没有太高的要求,因此需要缩小图片的体积,以便提高网页的加载速度。
  • 其次还需要对图片的长宽进行规范化。我比较喜欢将图片的宽度设置得相同,这样标题可以比较整齐。

下一个问题是,代码应该写到什么地方呢?似乎在modelform或者view里处理图片都可以。在这里我打算把代码写到model中去,这样不管你在任何地方上传图片(包括后台中!),图片都会得到处理。

想好之后,就要行动了。还记得Pillow这个库吗,我们很早就把它安装好了,现在是使用它的时候了:

article/models.py

...

# 记得导入!
from PIL import Image

class ArticlePost(models.Model):
    ...
    # 前面写好的代码
    avatar = models.ImageField(upload_to='article/%Y%m%d/', blank=True)

    # 保存时处理图片
    def save(self, *args, **kwargs):
        # 调用原有的 save() 的功能
        article = super(ArticlePost, self).save(*args, **kwargs)

        # 固定宽度缩放图片大小
        if self.avatar and not kwargs.get('update_fields'):
            image = Image.open(self.avatar)
            (x, y) = image.size
            new_x = 400
            new_y = int(new_x * (y / x))
            resized_image = image.resize((new_x, new_y), Image.ANTIALIAS)
            resized_image.save(self.avatar.path)

        return article

...

代码不多,但是有很多细节,值得仔细推敲。不急,一行一行来:

  • save()是model内置的方法,它会在model实例每次保存时调用。这里改写它,将处理图片的逻辑“塞进去”。

  • super(ArticlePost, self).save(*args, **kwargs)的作用是调用父类中原有的save()方法,即将model中的字段数据保存到数据库中。因为图片处理是基于已经保存的图片的,所以这句一定要在处理图片之前执行,否则会得到找不到原始图片的错误。

  • 博文的标题图不是必须的,if中的self.avatar剔除掉没有标题图的文章,这些文章不需要处理图片。

  • 不太好理解的是if中的这个not kwargs.get('update_fields')。还记得article_detail()视图中为了统计浏览量而调用了save(update_fields=['total_views'])吗?没错,就是为了排除掉统计浏览量调用的save(),免得每次用户进入文章详情页面都要处理标题图,太影响性能了。

这种判断方法虽然简单,但会造成模型和视图的紧耦合。读者在实践中可探索更优雅的方法,比如专门设置一个参数,用来判断是哪类视图调用了save()。

  • 接下来都是Pillow处理图片的流程了:打开原始图片,取得分辨率,将新图片的宽度设置为400并根据比例缩小高度,最后用新图片将原始图片覆盖掉。Image.ANTIALIAS表示缩放采用平滑滤波。

  • 最后一步,将父类save()返回的结果原封不动的返回去。

完美!

模板与测试

剩下的工作就比较简单了。

修改发表文章的模板,让表单能够上传图片:

templates/article/create.html

...

<!-- 记得增加 enctype ! -->
<form ... enctype="multipart/form-data">
    ...

    <!-- 文章标题图 -->
    <div class="form-group">
        <label for="avatar">标题图</label>
        <input type="file" class="form-control-file" name="avatar" id="avatar">
    </div>

    ...
</form>
...

然后修改文章列表模板,让其能够展现标题图。

为了美观,这里稍微改动了列表循环的整体结构:

templates/article/list.html

...

<!-- 列表循环 -->
<div class="row mt-2">
    {% for article in articles %}
        <!-- 标题图 -->
        {% if article.avatar %}
            <div class="col-3">
                <img src="{{ article.avatar.url }}" 
                     alt="avatar" 
                     style="max-width:100%; border-radius: 20px"
                >
            </div>
        {% endif %}

        <div class="col">
            <!-- 栏目 -->
            ...

            <!-- 标签 -->
            ...

            ...

        <hr style="width: 100%;"/>
    {% endfor %}
</div>

...

接下来又是喜闻乐见的测试环节。

启动服务器,打开发表文章页面:

选择几张分辨率各不相同的图片作为标题图,

发表几篇文章并回到文章列表页面:

看起来似乎不错。

查看一下media目录下实际保存的图片:

确实保存到想要的目录下,并且左下角显示图片的宽度全都为400了。

扫尾工作

功能已经实现了,但还有扫尾工作需要去做:

  • 需要对上传的图片做更多的验证工作,比如上传的文件是否为图片、分辨率是否满足要求。虽然在个人博客项目中这些验证并不是特别重要,但在其他项目中就说不好了:谁知道用户会上传些什么奇奇怪怪的东西?

  • 编辑文章、删除文章也同样需要处理上传的图片。你还可以将缩放分辨率的技术应用到用户头像上,比如裁剪成方形。

注意:删除数据库中的avatar条目只是断开了数据表和图片的链接而已,实际上图片还保存在原来的位置。要彻底删除图片,你还得写操作系统文件的代码才行。

怎么实现这些功能就不赘述了,留给读者自己去折腾吧。

编辑文章

2019/06/24 新增本节

有不少读者在将标题图标签功能添加到编辑文章页面时遇到了困难,所以提示一下如何实现。

其实大家的思路是没错的,编辑和创建差不太多,唯一区别是编辑功能还需要把旧的数据给展现出来。关键是要注意几个问题:

  • 标题图是文件,你应该在request.FILES里获取它,而不是request.POST
  • tags不是普通的字段,article.tags是取不到值的,你应该用官方文档给的接口去获取、设置数据

所以视图相关代码应该这样写:

article/views.py

# 更新文章
@login_required(login_url='/userprofile/login/')
def article_update(request, id):
    ...
    if request.method == "POST":
        ...
        if article_post_form.is_valid():
            ...

            if request.FILES.get('avatar'):
                article.avatar = request.FILES.get('avatar')

            article.tags.set(*request.POST.get('tags').split(','), clear=True)
            article.save()

        ...

    else:
        ...
        context = { 
            ...
            'tags': ','.join([x for x in article.tags.names()]),
        }

        ...
  • tags.set()tags.names()就是库提供的接口了,分别用于更新数据和获取标签名。注意tags.set()是如何将序列分隔并解包的。
  • 渲染空表单时用到了列表生成器将数据转换为字符串。

模板相关代码:

templates/article/update.html


<form method="post" action="." enctype="multipart/form-data">
    {% csrf_token %}

    ...

    <!-- 文章标题图 -->
    <div class="form-group">
       <label for="avatar">标题图</label>
       <input type="file" class="form-control-file" name="avatar" id="avatar">
    </div>

    <!-- 文章标签-->
    <div class="form-group">
         <label for="tags">标签</label>
         <input type="text" class="form-control col-3" id="tags" name="tags"
            value="{{ tags }}">
    </div>

    ...
</form>

enctype="multipart/form-data"这个属性的意思是表单提交时不对字符编码。表单里带有文件时,一定要加上它。

核心代码大概就这样,我的GitHub仓库master分支更新了此部分的完整代码,提供给大家参考。

此外还有些细节问题可以优化,读者就自己去试试看吧!

轮子

虽然本文是自己动手写的代码(严格说来Pillow也是轮子),但想必你也猜到了,还有更加智能的轮子:django-imagekit,这个库可以直接集成到model里面,比如这样:

article/models.py

# 引入imagekit
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFit

class ArticlePost(models.Model):
    ...

    avatar = ProcessedImageField(
        upload_to='article/%Y%m%d',
        processors=[ResizeToFit(width=400)],
        format='JPEG',
        options={'quality': 100},
    )

字段中定义好了上传位置、处理规则、存储格式以及图片质量,你不需要写任何处理图片的代码了。

更多的用法见官方介绍

总结

本章学习了如何上传并处理文章的标题图,从此博客首页就有了漂亮的外观。

需要指出的是,个人博客所采用的服务器通常性能不佳,用来保存文章缩略图等小尺寸的图片倒还好,但是千万不要存储大尺寸的图片文件,否则用户等待几分钟都刷不开你的图片,那是很悲剧的。

因此建议你将大尺寸的图片、视频等放到专业的云对象存储服务商中,比如七牛云又拍云等,在你存储量很小时(10G以内)是花不了多少钱的。





本文作者: 杜赛
发布时间: 2019年02月27日 - 20:50
最后更新: 2019年06月24日 - 21:56
知识共享许可协议   转载请保留原文链接及作者


登录 后回复

共有50条评论

avatar
Python 么么哒! 4

你好!我发现有个问题:1、博客首页--所有文章,展示文章过多的时候footer不能自适应,翻页按钮会被footer遮住。

8个月前 回复


avatar
杜赛 [博主] Python 么么哒! 3

你说得对,这是Bootstrap的固定底部栏造成的。

写下一篇文章时会把这个小bug修正,感谢指出smiley

8个月前 回复


avatar
Python 杜赛 [博主] 么么哒! 3

好的。以后的博文可否加入富文本编辑器。昨天自己找了djangoueditor,发现总是出现问题,这个第三方作者好像已经停止开发了。有人说python2.7可以通过,3.7是否不支持?

8个月前 回复


avatar
Python 杜赛 [博主] 么么哒! 3

还有一个小问题(不知道是我错了,还是有bug):进入文章详情页--编辑文章,栏目里面不显示文章所属的栏目。但是后台写文章可以选择栏目。

8个月前 回复


avatar
杜赛 [博主] Python 么么哒! 3

富文本编辑器马上就会讲,可能下一篇教程吧。

文章栏目的实现肯定已经讲过了,但是有没有在编辑文章中实现我有点记不清了。如果没有,那就应该是留给读者的课后作业哦wink

8个月前 回复


avatar
Python 杜赛 [博主] 么么哒! 3

是的,重新去看了下教程,是我把这一步跳过去了!!已经解决!感谢!

8个月前 回复


avatar
tata 么么哒! 4

博主下次讲什么内容啊,什么时候更新呢

8个月前 回复


avatar
杜赛 [博主] tata 么么哒! 4

预计下周吧,讲富文本编辑器。

8个月前 回复


avatar
tata 杜赛 [博主] 么么哒! 3

博主,前端上传标题图没有保存到后台数据库,在后端上传倒是可以,会是哪里的问题呢?

8个月前 回复


avatar
杜赛 [博主] tata 么么哒! 4

视图、模板、表单类都有可能,不好说。

逐项检查吧。合理利用print( )、console( )

8个月前 回复


avatar
tata tata 么么哒! 3

8个月前 回复


avatar
Leavesdan tata 么么哒! 3

因为html的form表单没有添加

enctype="multipart/form-data"

这个属性吧,前面博主在上传用户头像的时候有标注过,我也遇到了这个问题,调试了半个小时,还是学的不够认真devil

这个属性表示将表单以二进制的方式传输,否则默认情况下,enctype的值是application/x-www-form-urlencoded,这是不能用来提交文件数据的

6个月前 回复


avatar
杜赛 [博主] Leavesdan 么么哒! 3

解释得很到位yes

6个月前 回复


avatar
ac1864 么么哒! 3

过关了。

老大,应该布置一些家庭作业,如何修改文章时,修改标题图。

5个月前 回复


avatar
杜赛 [博主] ac1864 么么哒! 3

这个建议很好,我仔细研究一下

5个月前 回复


avatar
Foolike 么么哒! 4

感谢博主~~  请问一下,如果想在“编辑文章”界面加入上传文章图片,该怎么操作呢?我模仿“创建文章”页面代码加入了request.FILES,也在对应html中修改了 但还是实现不了。如果方便的话 可不可以也说一下“编辑文章”界面如何添加文章标签呢?十分感谢!!!

5个月前 回复


avatar
杜赛 [博主] Foolike 么么哒! 3

编辑文章和新建文章实现上是差不多的,区别就是编辑文章需要把旧的内容显示出来。

实现不了是指什么?有报错信息吗?

5个月前 回复


avatar
Foolike 杜赛 [博主] 么么哒! 3

     您上传文章标题图的代码我已经能完全实现了,就是说有关图片裁剪、文件上传的代码部分没问题。我是想在update界面 再增加两个功能:修改文章标题图,修改标签。(这样其实就是创建的全部功能)

     但是我在您的代码的基础上做了以下修改,还是实现不了我想要的功能。

template/article/update.html 中也增加了对应的前端代码

<!-- 文章标题图 -->
<div class="form-group">
   <label for="avatar">标题图</label>
   <input type="file" class="form-control-file" name="avatar" id="avatar" 
     value="{{ article.avatar }}">
</div>

<!-- 文章标签-->
<div class="form-group">
     <label for="tags">标签</label>
     <input type="text" class="form-control col-3" id="tags" name="tags" 
        value="{{ article.tags }}">
</div>

 article/views.py中的article_update部分

@login_required(login_url='/userprofile/login/')
def article_update(request, id):
    """
    更新文章的视图函数
    通过POST方法提交表单,更新titile、body字段
    GET方法进入初始表单页面
    id:文章的id
    """
    # 获取需要修改的具体文章对象
    article = ArticlePost.objects.get(id=id)
    # (第二次鉴权)过滤已登录、但非作者本人的用户
    if request.user != article.author:
        return HttpResponse('抱歉,你无权修改这篇文章。')
    # 判断用户是否为 POST 提交表单数据
    if request.method == "POST":
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(request.POST, request.FILES) //增加了request.FILES
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存新写入的 title、body 数据并保存
            article.title = request.POST['title']
            article.body = request.POST['body']
            //增加了tags和avatar
            article.tags = request.POST['tags']
            article.avatar = request.POST['avatar']
            # 类别
            if request.POST['column'] != 'none':
                article.column = ArticleColum.objects.get(id=request.POST['column'])
            else:
                article.column = None
            article.save()
            # 完成后返回到修改后的文章中。需传入文章的 id 值
            return redirect("article:article_detail", id=id)
        # 如果数据不合法,返回错误信息
        else:
            return HttpResponse("表单内容有误,请重新填写。")

    # 如果用户 GET 请求获取数据
    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm(request.FILES)
        columns = ArticleColum.objects.all()
        # 赋值上下文,将 article 文章对象也传递进去,以便提取旧的内容
        context = {'article': article, 'article_post_form': article_post_form, 'columns': columns}
        # 将响应返回到模板中
        return render(request, 'article/update.html', context)

 

5个月前 回复


avatar
杜赛 [博主] Foolike 么么哒! 3

思路是没错,但是有问题没解决:

  • 标题图是文件,应该在request.FILES里获取它
  • tags也不是普通的字段,article.tags是取不到值的,你应该用官方文档给的接口去获取、设置数据
  • 表单里带有文件时,记得加enctype="multipart/form-data"属性

视图相关代码你试试这样写:

article/views.py


# 更新文章
@login_required(login_url='/userprofile/login/')
def article_update(request, id):
    ...
    if request.method == "POST":
        ...
        if article_post_form.is_valid():
            ...

            if request.FILES.get('avatar'):
                article.avatar = request.FILES.get('avatar')

            article.tags.set(*request.POST.get('tags').split(','), clear=True)
            article.save()

        ...

    else:
        ...
        context = { 
            ...
            'tags': ','.join([x for x in article.tags.names()]),
        }

        ...

注意看看tags.set()是如何将序列分隔并解包的。

模板相关代码

templates/article/update.html


<form method="post" action="." enctype="multipart/form-data">
    {% csrf_token %}

    ...

    <!-- 文章标题图 -->
    <div class="form-group">
       <label for="avatar">标题图</label>
       <input type="file" class="form-control-file" name="avatar" id="avatar">
    </div>

    <!-- 文章标签-->
    <div class="form-group">
         <label for="tags">标签</label>
         <input type="text" class="form-control col-3" id="tags" name="tags"
            value="{{ tags }}">
    </div>

    ...
</form>

核心代码大概就这样。

此外还有些细节问题可以优化,比如tags用其他符号分隔等,你自己去试试看吧

5个月前 回复


avatar
Foolike 杜赛 [博主] 么么哒! 3

已经实现了  十分感谢!!!我要给您搞个大鸡腿!

4个月前 回复


avatar
杜赛 [博主] Foolike 么么哒! 3

哈哈,鸡腿就不用了,好好把django学会

4个月前 回复


avatar
shenhanlin 么么哒! 3
本回复已被 shenhanlin 删除

5个月前 回复


avatar
shenhanlin shenhanlin 么么哒! 3
本回复已被 shenhanlin 删除

5个月前 回复


avatar
shenhanlin 么么哒! 3

博主model层执行这两句代码报错,但是能保存图片,就是操作图片报错,这是什么问题?

image = Image.open(self.avatar)
resized_image.save(self.avatar.path)

FileNotFoundError at /article/article-create/

[Errno 2] No such file or directory: 'article/20190624/7_6qdW3hI.jpg'

Request Method:POSTRequest URL:http://127.0.0.1:8000/article/article-create/Django Version:2.2.2Exception Type:FileNotFoundErrorException Value:

[Errno 2] No such file or directory: 'article/20190624/7_6qdW3hI.jpg'

Exception Location:D:\PycharmProjects\my_blog\venv\lib\site-packages\PIL\Image.py in open, line 2652Python Executable:D:\PycharmProjects\my_blog\venv\Scripts\python.exePython Version:3.6.7Python Path:

['D:\\PycharmProjects\\my_blog',
 'D:\\PycharmProjects\\my_blog',
 'D:\\PycharmProjects\\my_blog\\venv\\Scripts\\python36.zip',
 'D:\\Python36\\DLLs',
 'D:\\Python36\\lib',
 'D:\\Python36',
 'D:\\PycharmProjects\\my_blog\\venv',
 'D:\\PycharmProjects\\my_blog\\venv\\lib\\site-packages',
 'D:\\PycharmProjects\\my_blog\\venv\\lib\\site-packages\\setuptools-39.1.0-py3.6.egg',
 'D:\\PycharmProjects\\my_blog\\venv\\lib\\site-packages\\pip-10.0.1-py3.6.egg',
 'D:\\PyCharm 2018.2.4\\helpers\\pycharm_matplotlib_backend']

然后如果改成绝对路径的话,报存时就报这个错误

image = Image.open(os.path.join("D:\PycharmProjects\my_blog\media", self.avatar))
resized_image.save(os.path.join("D:\PycharmProjects\my_blog\media", self.avatar))

AttributeError: 'InMemoryUploadedFile' object has no attribute '_committed'

5个月前 回复


avatar
杜赛 [博主] shenhanlin 么么哒! 3

两条语句都报错吗?

感觉相对路径好像没设置好,媒体文件的设置写对了吗?

下面的绝对路径里用两个反斜杠试试(\\)

5个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

对,debug调试的时候,执行到那两句代码就报错,嗯好我试试换两个反斜杠试试

5个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

绝对路径改两个反斜杠可以了,没有报错了

5个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

有个问题,绝对路径不管是两个反斜杠还是一个反斜杠第一次不报错正常,第二次就报这个错误

AttributeError: 'InMemoryUploadedFile' object has no attribute '_committed'

5个月前 回复


avatar
杜赛 [博主] shenhanlin 么么哒! 3

就是说你保存的是原始尺寸的图片对吧?遇到PIL有关的代码就出错了,所以图片没有正常压缩。

我没遇到过这种情况,所以也不清楚哪里有问题

试试重装另一个PIL版本,或者把我GitHub的代码下载下来跑一下,看看正常不

4个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

是的,遇到PIL有关代码就出错了。

4个月前 回复


avatar
杜赛 [博主] shenhanlin 么么哒! 3

试试我的代码能运行不

或者用django-imagekit

4个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

我运行了下博主你的代码也是不行,也是执行PIL的相关代码的操作时也会报错,然后我用django-imagekit也有问题

#文章标题图
avatar = models.ImageField(upload_to='article/%Y%m%d/', blank=True)

# 注意:ImageSpecField不会生成数据库中的表
# 处理后的图片
picture_400x400 = ImageSpecField(
    source="avatar",
    processors=[ResizeToFill(400, 400)],  # 处理后的图像大小
    format='JPEG',  # 处理后的图片格式
    options={'quality': 95}  # 处理后的图片质量
)

4个月前 回复


avatar
杜赛 [博主] shenhanlin 么么哒! 3

django-imagekit都不行吗..把DjangoPIL换个版本试试

环境问题是有点麻烦的

4个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

博主Django和PIL换什么版本的会比较好?

4个月前 回复


avatar
杜赛 [博主] shenhanlin 么么哒! 3

你是都安装的最新版本吗?

就都降一个版本试试,比如django2.2变成2.1

4个月前 回复


avatar
shenhanlin 杜赛 [博主] 么么哒! 3

我讲Django和PIL都降级了,也还是第一次正常运行,然后第二次就这个错

'InMemoryUploadedFile' object has no attribute '_committed'

这个百度了好久也没找到解决方法。

4个月前 回复


avatar
杜赛 [博主] shenhanlin 么么哒! 3

我也搞不清楚怎么回事了,主要没遇到过。

你把项目打包Email给我,我有空也看看。记得生成requirements.txt

4个月前 回复


avatar
wangycgood 么么哒! 3

laugh博主你好,在你目前版本的代码中并没有关于文章导航图片以及用户头像上传后即可实时预览的这类功能,请问这里是如何实现的呢?期待博主的解答!

3个月前 回复


avatar
杜赛 [博主] wangycgood 么么哒! 3

头像实时预览这个跟Django没啥关系,是前端的内容,所以暂时没讲,以后可能会提一下。

文章导航图片是指哪个功能?

3个月前 回复


avatar
wangycgood 杜赛 [博主] 么么哒! 3

就是文章标题图cheeky,和头像上传页面性质一样,因为在新上传或更换现有图片时,上传后无法即时查看,所以感觉这点会影响用户体验。

3个月前 回复


avatar
杜赛 [博主] wangycgood 么么哒! 3

这个跟头像上传一样的,是JavaScript的内容。我博客用的是cropper.js这个插件,您可以去了解一下

3个月前 回复


avatar
wangycgood 杜赛 [博主] 么么哒! 3

yes好的,非常感谢博主的解答。

3个月前 回复


avatar
sys0613 么么哒! 3
本回复已被 sys0613 删除

3个月前 回复


avatar
ligang123 么么哒! 1

博主 就是标题图怎么变成圆角的了,我想改回原图那种直角的应该在哪里改动。

2个月前 回复


avatar
杜赛 [博主] ligang123 么么哒! 1

去掉 border-radius 属性

2个月前 回复


avatar
ligang123 杜赛 [博主] 么么哒! 1

感谢感谢,现在感觉舒服多了

2个月前 回复


avatar
liuchangfu 么么哒! 1

老师,这个位置 <div class='col-9'>,要这样写,不然要样式会有问题。。。

        <div class="col">
            <!-- 栏目 -->
            ...

            <!-- 标签 -->
            ...

            ...

1个月前 回复


avatar
zpz liuchangfu 么么哒! 1

1个月前 回复


avatar
StanleyGao2018 么么哒! 1

article = super(ArticlePost, self).save(*args, **kwargs)

你好,我的这一行一直在vscode有这个报错

Assigning result of a function call, where the function returns None pylint(assignment-from-none)

但是不影响正常功能,请问博主有什么解决方案么?

28天前 回复


avatar
杜赛 [博主] StanleyGao2018 么么哒! 1

百度 vs code pylint 配置项

28天前 回复