上一篇主要讲了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
本文地址:https://blog.jixiaob.cn/?post=45
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。