欢迎食用『主界面』~,这里是赵苦瓜的看板娘desu~

#
【点滴记录】Django框架的入门 - 第六篇(模型迁移原理、模型关系、静态文件、文件上传、邮件发送)
首页 > 点滴记录    作者:赵苦瓜   2021年2月2日 15:37 星期二   热度:5683°   百度已收录  
时间:2021-2-2 15:37   热度:5683° 

上一篇主要讲了Cookie,Session,Token等会话技术,戳链接==>https://blog.jixiaob.cn/?post=44

————————————————————————————————————————

模型迁移的原理

迁移的记录都会被记录在数据表django_migrations里面,每次执行会在表中进行比对。

如果误删了已经迁移的数据表,在这个表里面删除对应的记录再重新迁移即可。

迁移:分两步实现。第一步生成迁移文件,第二步执行迁移文件。

迁移文件的生成:

根据models文件生成对应的迁移文件

根据models和已有迁移文件的差别生成新的迁移文件

执行迁移文件:

先去迁移记录中查找,那些文件未迁移过

app_lable + 迁移文件的名字

执行为迁移的文件

执行完毕,记录执行过的迁移文件


为指定的app生成迁移文件(后面加上app的名字):

python manage.py makemigrations appname

————————————————————————————————————————

模型关系

1:1

场景:拆分、扩展

比如创建一个一对一,拿身份证号绑定人

class Person(models.Model):
    p_name = models.Model.CharField(max_length=16)
    p_sex = models.BooleanField(default=False)

class IDCard(models.Model):
    id_num = models.Charfield(max_length=18, unique=True)
    id_person = models.OneToOneField(Person, null=True, blank=True)


Django中的OneToOneField
使用的时候,关系声明还是有细微差别的

实现:使用外键实现,对外键添加了唯一约束

数据删除:级联表,主表,从表。谁声明关系,谁就是从表。开发中如何确认主从?留的一般都是主表。


默认特性(CASECADE):从表数据删除,主表不受影响。

主表数据删除,从表数据直接删除。


PROTECT受保护,

可以在创建id_person的时候设置为on_delete=models.PROTECT(直接设置删除的时候有级联数据会引发异常)

开发中为了防误操作,经常这样做。

如果主表存在级联数据,删除动作受保护,不能成功。

主表不存在级联数据,可以删除成功


SET

也可以设置

on_delete=models.SET(value) 【指定值】    SET_DEFAULT()【存在默认值】   SET_NULL【允许为NULL】


级联数据的获取:

从获取主:显性属性,直接就是属性的名字

主获取从:隐形属性,默认就是级联模型的名字


def get_person(request):
    idcard = IDCard.objects.last()     # 实际要用filter筛选
    person = idcard.id_person
    return HttpResponse(person.p_name)


def get_idcard(request):
    person = Person.objects.last()
    idcard =  person.idcard     # 隐形属性
    return HttpResponse(idcard.id_num)




1:M

——————————————————————————————————————————————

ForeignKey   

主从获取:

主获取从:隐形属性,级联模型_set

student_set  Manager的子类  all  filter  exclude  Manager上能用的函数都能用

从获取主:显性属性



M:N

实际上最复杂,开发中很少直接使用多对多属性,而是自己维护多对多的关系。

产生表的时候会产生单独的关系表

关系表中存储关联表的主键,通过外键实现。

多个外键值不能同时相等

级联数据获取:

从获取主:使用属性,属性是一个Manager子类。

主获取从:隐形属性。也是Manager的一个子类,和从获取主操作一样。


Models的面向对象

在Models中添加Meta,指定是否抽象,然后进行继承。

class Meta:

    abstract = True


跨app建立级联数据:app名.类名  直接引用



Unix时间戳转换为DateTimeField:

import datetime

#First i will convert timestamp into seconds format by dividing by 1000.0
ts = ts/1000.0
#Then i will use this 'ts' in the following line of code.
datetime.datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') 


Unix时间戳转换:

>>> import datetime
>>> datetime.datetime.utcfromtimestamp(1549366296.466).strftime('%Y-%m-%d %H:%M:%S')
'2019-02-05 11:31:36'
>>> 



Django中模板支持继承

默认继承会将通用字段放到父表中,特定字段放在自己的表中,中间使用外键连接。

关系型数据库关系越复杂,效率越低,查询越慢

父类表中也会存储过多数据,导致效率低下

使用元信息来解决这个问题

使模型抽象化,抽象的模型就不会在数据库中产生映射了,子模型映射的表中包含父模型的字段。


在企业开发中

model -> sql

都可以使用

sql -> model

django也提供了很好的支持

python manage.py inspectdb   这样直接复制models即可,也可以重定向输出  > App/models.py

可以直接根据表生成模型,元信息包含一个属性manage=False(如果自己的模型不想被系统迁移管理,也可以写这个元信息。


静态文件

————————————————————————————————————————

配置:

在settings.py最底下

STATIC_URL = '/static/'

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]


使用:

先加载
{% load static %}  或{% load staticfiles %}
再使用
<link rel="stylesheet" href="{% static 'css/show.css' %}">


静态文件和模板文件的区别:

静态文件里面的HTML只支持原生HTML,不支持模板语法


文件上传

————————————————————————————————————————

必须使用提交的方式(如POST)

原生上传保存方式:

def upload_file(request):
    if request.method == 'GET':
        return render(request, "upload.html")
    elif request.method == 'POST':
        icon = request.FILES.get('icon')
        print(type(icon))
        with open('static/image/icon.jpg', 'wb') as save_file:   # wb:写二进制文件
            for part in icon.chunks():
                save_file.write(part)         # 分成小块写
                save_file.flush()          # 写完就冲
    return HttpResponse('文件上传成功')


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>

<form action="{% url 'upload_file' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<span>文件:</span>
<input type="file" name="icon">
<br>
<input type="submit" value="上传">
<br>
</form>
</body>
</html>
还可以用模型的一个属性(需要Pillow)


u_icon = models.ImageField(upload_to='icons')   写的是相对路径,相对于MEDIA_ROOT媒体根目录

在设置里面设置媒体根目录:

MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')]

def image_filed(request):
    if request.method == "GET":
        return render(request, 'image_filed.html')
    elif request.method == 'POST':
        username = request.POST.get('username')
        icon = request.FILES.get('icon')
        user = User()
        user.s_name = username
        user.s_icon = icon
        user.save()
        return HttpResponse('上传成功!%d' % user.id)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{% url 'image_filed' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <span>用户名:</span><input type="text" name="username" placeholder="请输入用户名">
    <br>
    <span>头像:</span><input type="file" name="icon">
    <br>
    <button>上传</button>
</form>
</body>
</html>
上传的文件如果有同名文件,会自动在后面加上_混串


怎么获取呢?

user = UserModel.objects.get('u_name'=username)

path = '/static/upload/' + user.u_icon.url



Linux有路径中直接子文件不能超过65535个的BUG,超过就再也打不开了

可以创建文件夹分类,可以按首字母,可以按时间

在模型中的uploadto='%Y/%m/%d/icons'   年月日


邮件发送

————————————————————————————————————————

Django中自带一个邮件发送。注意,这个邮件发送并不是自己生成一个邮件服务器,而是使用smtp登录其它已经有的邮箱来进行发送操作。

from django.core.mail import send_mail

def send_email(request):
    # 邮件主题
    subject = 'Test Mail'
    # 信息
    message = 'This 是一个测试'
    # 从哪个地址发(为防止邮箱爬取,我把@改为了#,实际上要写成@
    from_email = 'zkg#moeact.com'
    # 接收方list(为防止邮箱爬取,我把@改为了#,实际上要写成@
    recipient_list = ['1066168689#qq.com']
    send_mail(subject=subject, message=message, from_email=from_email, recipient_list=recipient_list)
    # 还可以指定html_message来发送HTML内容
    return HttpResponse('邮件发送成功!')

也可以使用templates里面的模板当作邮件的html模板发送。要注意的是,不能只提供html_message参数,同时也要提供一个message的参数,内容是什么似乎没有影响,但是没有这个参数会报错。


html_message = render_to_string('forget_pwd_mail.html', context={'code': code})



然后在settings.py里面设置发送方邮箱的账号和密码:

EMAIL_HOST = 'stmp.moeact.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = 'zkg#moeact.com'
EMAIL_HOST_PASSWORD = 'This_is_password'



然后就可以成功发送邮件啦~

另外,如果你遇到了这个报错:pycharm [Errno 11001] getaddrinfo failed
可能是EMIL_HOST填写错误导致。可以到邮件服务商那里查看地址是否正确。



还有一点是,现在大多服务器都由于法律法规禁用了25端口,导致发不出去

这时候可以试试其它可用端口

但是使用加密端口的时候要注意,settings.py里面要多加一行:EMAIL_USE_SSL = True

EMAIL_HOST = 'smtp.qiye.aliyun.com'
EMAIL_PORT = 465
EMAIL_HOST_USER = 'miao@miaomiao.com'
EMAIL_HOST_PASSWORD = 'This is password'
EMAIL_USE_SSL = True


本文作者:赵苦瓜      文章标题: 【点滴记录】Django框架的入门 - 第六篇(模型迁移原理、模型关系、静态文件、文件上传、邮件发送)
本文地址:https://blog.jixiaob.cn/?post=45
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。

返回顶部    首页    后花园  
版权所有:赵苦瓜のBlog~    站长: 赵苦瓜    程序:emlog   鲁ICP备20030743号-1   鲁公网安备37048102006726 萌ICP备20222268号    sitemap