Django基础四⼆(OneToMany和ManyToMany,ModelForm)上⼀篇博⽂是关于setting.py⽂件数据库的配置以及model与数据库表关系,实现了通过操作BlogUser,把BlogUser的信息存⼊后台数据库中.实际开发中有许多东西是相互联系的,除了数据的显⽰和存储之外,我们也要理清各种数据对象之间的关系.Django框架定义了三种关系模型:
OneToOne
OneToOne(⼀对⼀) :这种对应关系最简单,就是字⾯的意思⼀对⼀.django⽤OneToOneField来表⽰这种对应关系.
OneToMany
OneToMany(⼀对多) :也是常见关系中的⼀种,现实⽣活中有很多⼀对多的关系,例如:学⽣与书本的关系:⼀个学⽣可以有很多本书,但是⼀本书的持有者⼀般只有⼀个.这种关系也⽐较容易理解,Django⽤ForeignKey来表⽰⼀对多的关系.
ManyToMany
ManyToMany(多对多):这个也很常见,⽐如学⽣和任课⽼师之间的关系.⼀个学⽣⼀般有多个任课⽼师,任课⽼师也教授多个学⽣.Django⽤ManyToManyField表⽰多对多的关系
本⽂主要关注OneToMany和ManyToMany这两中关系.
1 添加model
我们定义⼀个标签类别的model(例如数学,语⽂,编程等),再定义⼀个博客标签model.标签类别对象下⾯可以有多个博客标签(例如编程类别下⾯可以分为:C ,C++,C#,Java,Python等),⼀个博客标签下可以有多个博客.然后再定义⼀个博客model,⼀个博客可以有多个标签(这篇博⽂就贴了Django和python两个标签);
编辑myBlog⽂件⽬录下的models.py定义'TagType','BlogTag','Blog'三个model:
class TagType(models.Model):#⽂章⼤类
DEL_CHOICES=(
('YES','已停⽤'),
('NO','正常使⽤'),
)
typename=models.CharField('类别',max_length=100)
createDate=models.DateTimeField('创建时间',auto_now_add=True)
isdeleted=models.CharField('删除标志',max_length=10,default='NO',choices=DEL_CHOICES)
deleteDate=models.DateTimeField('删除时间',blank=True,null=True)
def __str__(self):
pename
class BlogTag(models.Model):#标签⼦类
DEL_CHOICES=(
('YES','已停⽤'),
('NO','正常使⽤'),
)
tagtype=models.ForeignKey(TagType,on_delete=models.SET_NULL,blank=True,null=True)#on_delete=models.SET_NULL删除⽗级记录时该字段置空,保留记 tagename=models.CharField('标签名',max_length=100)
createDate=models.DateTimeField('创建时间',auto_now_add=True)
isdeleted=models.CharField('删除标志',max_length=10,default='NO',choices=DEL_CHOICES)
deleteDate=models.DateTimeField('删除时间',blank=True,null=True)
def __str__(self):
return pename+self.tagename
class Blog(models.Model):#博客
title=models.CharField('标题',max_length=200)
tag=models.ManyToManyField(BlogTag)
content=models.TextField('正⽂',blank=True,null=True)
author=models.ForeignKey(BlogUser,on_delete=models.SET_NULL,blank=True,null=True)
createDate=models.DateTimeField('创建时间',auto_now_add=True)
lastmdfDate=models.DateTimeField('上次修改时间',blank=True,null=True)
def __str__(self):
return self.title +'作者:'+ self.author.username
这⾥主要说明⼀下models.ForeignKey()的参数,第⼀个参数是'⼀对多'关系中的'⼀'所对应的类别,BlogTag model的代码段.
tagtype=models.ForeignKey(TagType,on_delete=models.SET_NULL,blank=True,null=True)
的意思就是BlogTag实例的tagtype属性只能指向⼀个TagType类的实例.在BlogTag的tagtype属性指向同⼀个TagType类实例的情况下,我
们可以创建多个BlogType类的实例.这样就可以实现⼀个TagType对应多个BlogTag的关系.
Blog model 中的代码段:
tag=models.ManyToManyField(BlogTag)
是指Blog的tag属性指向多个BlogTag的实例,创建Blog实例的时候(ManyToManyField的指向默认是空).
这⾥需要注意:每次修改或者新增model之后,都要执⾏python manage.py makemigrations和python manage.py migrate把修改或者新增的
model同步到数据库中!
2 TestCase单元测试
数据库同步完成之后,就是做单元测试,不要觉得繁琐,⼀定要养成这样的习惯!!编辑myBlog⽂件⽬录下的tests.py,增加
对'TagType','BlogTag','Blog'三个model的测试类(因为这三类是有联系的,我把关于他们的测试都写在了⼀个测试类⾥):
class BlogTestCase(TestCase):
def create_test(self):
test_user,created=BlogUser.objects.update_or_create(username='test_blog_user',email='test@.163',password='test',gender='M') print(test_user)
test_type1,created=TagType.objects.update_or_create(typename='数学')#添加数学这个⼤类
test_type2,created=TagType.objects.update_or_create(typename='编程')#添加编程⼤类
print(TagType.objects.all())#TagType.objects.all()意思是取当前所有的TagType的实例
mat_test_tag1,created=BlogTag.objects.update_or_create(tagtype=test_type1,tagename='⾼等数学')
mat_test_tag2,created=BlogTag.objects.update_or_create(tagtype=test_type1,tagename='线性代数')
prm_test_tag1,created=BlogTag.objects.update_or_create(tagtype=test_type2,tagename='python')
prm_test_tag2,created=BlogTag.objects.update_or_create(tagtype=test_type2,tagename='Django')
django项目实例print(BlogTag.objects.all())
print(BlogTag.objects.filter(tagtype=test_type1))#取⾼数⼤类下的所有标签
print(BlogTag.objects.filter(tagtype=test_type2))#取编程⼤类下的所有标签
test_blog,created=Blog.objects.update_or_create(title='测试博客',author=test_user)#创建测试Blog实例
print(test_blog)
print(test_blog.tag.all())#列出test_blog实例的所有标签
test_blog.tag.add(prm_test_tag1,prm_test_tag2)#为test_blog添加标签
print(test_blog.tag.all())
./manage.py ate_test结果如图:
.
3 ModelForm
之前的博⽂说过了⾃定义form,这⾥再说另⼀类:ModelForm.
ModelForm是针对model的⼀种表单灵活性没有⾃定义Form那么⾼.ModelFrom也是Form的⼦类.编辑
myBlog⽂件⽬录下forms.py,
⾸先要导⼊Model:
dels import Blog, BlogTag, TagType
然后添加下⾯的代码,针对'TagType','BlogTag','Blog'三个model定义三个form:
class TagTypeForm(forms.ModelForm):
class Meta:
model=TagType#指向TagType这个model
fields=['typename']#前台的input框输⼊的是内容对应typename字段
class BlogTagForm(forms.ModelForm):
class Meta:
model=BlogTag
fields=['tagtype','tagename']
class BlogForm(forms.ModelForm):
class Meta:
model=Blog
fields=['title','tag','content','author']
4 template模板页⾯
在template⽂件⽬录下新增⼀个blog.html⽂件,⽤来显⽰form:
<!DOCTYPE html>
<html lang="en" dir="ltr">
{% load static %}
<head>
<meta charset="utf-8">
<title>编辑标签</title>
<script type="text/javascript",src="{% static 'JS/jquery-3.2.1.min.js' %}">
</script>
<script type="text/javascript">
</script>
</head>
<body>
<div class="">
<form class="tag_type_form" action="" method="post">
{% csrf_token %}
{{ type_form }}
<button type="submit" name="sub_btn">添加类别</button>
</form>
</div>
<div class="">
<form class="blog_tag_form" action="{% url 'btag' %}" method="post"><!--action="{% url 'btag' %}"是把请求提交到urls.py⽂件urlpatterns这个list中name='btag {% csrf_token %}
{{tag_form}}
<button type="submit" name="tag_btn" id='tag_btn'>添加标签</button>
</form>
</div>
<div class="">
<h4>现有博客:</h4>
{% for blog in blogs %}
{{blog.title}}<br>
{% endfor %}
</div>
<div class="">
<form class="" action="{% url 'blogedit' %}" method="post">
{% csrf_token %}
{{blog_form}}
<button type="submit" name="button">编辑完成</button>
</form>
</div>
</body>
</html>
5 views.py定义视图类
还是先导⼊model和form:
from myBlog.forms import RegisterForm, TagTypeForm,BlogTagForm,BlogForm#导⼊我们在forms.py⾃定义的form表单
dels import BlogUser, TagType, BlogTag, Blog
我们后⾯会⽤重定向,这⾥也先⼀并导⼊:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论