技术笔记——Django+Nginx+uwsgi搭建自己的博客(十三)

在上一篇博文中,我们使用django自带的auth.user重写了users App的所有相关功能,并且将旧模型的user全部迁移到了新的model下。在这篇博文中,我们继续将blog App中与user相关的功能迁移到auth.User中。这样,在这篇博文结束时,我们整个博客的用户系统均会迁移到auth.User下。

首先是对数据模型的更改。blog App涉及到user相关的数据模型为Blog和Comment,我们需要对这两个类的外键作修改,使其指向新的auth.user:

# blogs/models.py
# ......
from django.contrib.auth.models import User
class Blog(models.Model):
    # ...
    auther = models.ForeignKey(User,default='',on_delete=models.CASCADE)
    # ...


class Comment(models.Model):
    # ...
    auther = models.ForeignKey(User,default='',on_delete=models.CASCADE)
    # ...

我们将原本的auther的指向改为auth.User。

然后我们逐个修改blogs/views.py中的函数,使用request.user替换掉原本获得user的方法:

# blogs/views.py
# ...
from django.contrib.auth.models import User
def content(request,blogId):
    # ...
    currentusername = request.user.username
    # ...

def saveComment(request):
    comment_content = request.POST['blogcomment']
    blog = Blog.objects.get(pk=request.session['currblogId'])
    result_info = ''
    try:
        auther = User.objects.get(username=request.user.username)
    except:
        auther = User.objects.get(username='anony')
    # ...

def addBlog(request):
    if request.method == 'POST':
        if 'currentblogId' in request.session:
            blogId = request.session['currentblogId']
            tmpBlog = Blog.objects.get(id=blogId)

            if tmpBlog:
                form = BlogForm(request.POST,instance=tmpBlog)
                tmpBlog = form.save(commit=False)
                tmpBlog.draft = False
                tmpBlog.save()
                result_info = 'Success'
            else:
                form = BlogForm(request.POST)
                if form.is_valid():
                    newBlog = form.save(commit=False)
                    newBlog.auther = User.objects.get(username=request.user.username)
            # ...
        else:
            form = BlogForm(request.POST)
            if form.is_valid():
                newBlog = form.save(commit=False)
                newBlog.auther = User.objects.get(username=request.user.username)
            # ...

这里只将获取user的改动列出来,因为程序的其他部分并没有改动,只是获取用户的方式发生了变化。

以下的几个小函数也是如此,使用新的user来获取相关信息:

# blogs/views.py
def articlelist(request):
    if request.user.username == 'anony':
        return render(request, 'blogs/failedoperation.html')
    else:
        blogList = Blog.objects.filter(auther=request.user)
    return render(request,'blogs/articleList.html',{'blogList':blogList})

def blogmanage(request):
    if request.user.username == 'anony':
        return render(request, 'blogs/failedoperation.html')
    else:
        blogList = Blog.objects.filter(auther=request.user)
    return render(request, 'blogs/blogmanage.html', {'blogList': blogList})
def commentmanage(request):
    blogList = Blog.objects.filter(auther=request.user)
    commentList = []
    for blog in blogList:
        commentList.append(Comment.objects.filter(attachedblog=blog))
    return render(request,'blogs/commentmanage.html',{'commentList':commentList})
def deletecomment(request,commentId):
    comment = Comment.objects.get(id=commentId)
    attachedBlog = comment.attachedblog
    if attachedBlog.auther.username == request.user.username:
        comment.delete()
        attachedBlog.commentcount -= 1
        attachedBlog.save()
    else:
        return render(request, 'blogs/failedoperation.html')
    return HttpResponseRedirect(reverse('blogs:commentmanage'))


def draftmanage(request):
    blogList = Blog.objects.filter(auther=request.user.username).filter(draft=True)
    return render(request, 'blogs/draftmanage.html', {'blogList': blogList})

然后,我们就可以回到主页,打开迁移好的博客了!

等等......这是什么鬼:

从报错信息看,该错误出现在content函数中,似乎django将test2试图转成10进制的数字从而导致出错!

由于从这个报错信息上看不出什么更多的东西,我们直接到后台数据库中看看有什么发现。

在myblog目录下输入sqlite3 blog.sqlite,登入后台数据库:

在sqlite3环境下,输入.tables可以查看数据库中所有的表。我们可以看到,现在数据库中已有了不少表:auth_user是我们的新user表;以blogs_开头的表都是Blog App中的表;以users_开头的表都是users App中的表。

我们输入.schema可以看到所有表的表结构,现在让我们来看一下:

我们来重点关注一下blogs_blog和blogs_comment这两张表的结构,因为它们就是问题的原因所在:

--blogs_blog:
CREATE TABLE IF NOT EXISTS "blogs_blog" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(32) NOT NULL, "content" text NOT NULL, "createdate" datetime NOT NULL, "readcount" integer NOT NULL, "commentcount" integer NULL, "draft" bool NOT NULL, "auther_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "category_id" integer NULL REFERENCES "blogs_category" ("id") DEFERRABLE INITIALLY DEFERRED, "modifydate" datetime NOT NULL);

--blogs_comment
CREATE TABLE IF NOT EXISTS "blogs_comment" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content" text NOT NULL, "createtime" datetime NOT NULL, "attachedblog_id" integer NOT NULL REFERENCES "blogs_blog" ("id") DEFERRABLE INITIALLY DEFERRED, "auther_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);

注意这两个表里都有一个名为auther_id的列,其类型是integer,作为指向auth_user的外键。

我们在sqlite环境下输入以下sql:

select * from blogs_blog where title="test3";

会得到以下结果:

55|test3|<p>test3</p>|2018-01-16 21:30:15.815229|6|1|0|12|2|2018-01-16 21:30:15.815253

这样,我们可以通过test3的id55来查看属于它的所有comment:

select * from blogs_comment where attachedblog_id="55";

会得到以下结果:

33|ff|2018-02-10 14:45:58.608942|55|test2

根据上文的schema得知,最后一列应该是integer类型,为什么这里是个test2?

原因就在于我们之前的迁移动作。

让我们回顾一下旧的User模型:

# users/models.py
class Users(models.Model):
    username = models.CharField(max_length=8,primary_key=True,unique=True,verbose_name=u'用户名')
    password = models.CharField(max_length=16,verbose_name=u'密码')
    logoimage = models.ImageField(upload_to='logoimages',null=True,blank=True,verbose_name=u'头像')
    # new field
    birthday = models.DateTimeField(null=True,blank=True,verbose_name=u'生日')
    email = models.CharField(max_length=255,null=True,blank=True,verbose_name=u'电子邮件')
    mobilephone = models.CharField(max_length=11,null=True,blank=True,verbose_name=u'手机号码')
    # new field end
    registertime = models.DateTimeField(default=timezone.now())

在我们旧的User模型中,我们使用自己的username作为主键,而没有采用django提供的id作为主键。并且,username显然应为字符型。

然后,在旧的User模型下,我们使用它作为了Blog和Comment中auther的外键,即在旧的模型下auther的外键字段类型为字符型而不是integer类型。

然而,当我们使用了新的auth.User作为Blog和Comment的auther外键后,在执行make migrations和migrates后,django改变了表的结构,但却保留了原本的数据,并且也没有任何提示。因此,旧的字符类型的username就作为了新的integer类型的外键存储在了新的数据类型下。

为了能正常打开我们的test3博客,我们需要把那个test2的username变为正确的userId:

执行以下sql拿到test2的userId:

select * from auth_user where username="test2";
15|pbkdf2_sha256$100000$gMenQmP4fqaw$qU75xLETHu9fDfxUfBcwZKut+7JNZgL/DC51PpmDvPA=|2018-07-28 20:55:03.129047|0|test2|||0|1|2018-07-21 20:51:28.046726|

再执行以下sql将test2更正为15:

update blogs_comment set auther_id=15 where attachedblog_id="55";

这样,我们就可以打开我们的博客了!

好了,在本篇博文中,我们将新的user应用到了blog App中,同时带着大家踩了一个django后台数据库的坑:当数据类型变化时django的migrate功能会将旧类型的数据保存在新数据类型的表中并且没有提示。至此,我们的博客已经完全迁移到新的user模型下。在下期博文中,我将使用BootStrap主题对博客的前端部分进行美化,敬请期待~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值