関係
-1-オン(水平サブテーブル)
母表: UserInfo id name age 子表: private id salary sp
モデル文を作成します。
class UserInfo(models.Model): name = models.CharField(max_length=32, null=True) age = models.IntegerField(null=True) class Private(models.Model): salary = models.CharField(max_length=32, null=True) sp = models.OneToOneField("UserInfo", null=True) # OneToOneField 一对一
データの作成:
models.UserInfo.objects.create(name="潘立府",age="18") # 注意字段sp_id才是Private表的真实字段。sp则是一个对象 models.Private.objects.create(salary='50000',sp_id='1')
需要:親テーブルから子テーブルのクエリデータ(給与名に関するお問い合わせ=「XXXX」)されます
res = models.UserInfo.objects.filter(name='plf').first() # 语法: res.子表表名小写.子表字段名 print(res.private.salary)
要件:子テーブルから女性のテーブルのクエリデータ(給与= xxxxの名前と年齢に関するお問い合わせ)
# 从子表查询母表中的数据 res = models.Private.objects.filter(salary=5000).first() # 语法: 对象.关联的字段.母表的字段 print(res.sp.name,res.sp.age)
2.多
相亲的模型 Boy: id name Girl: id name 1 真真 2 连连 3 爱爱 4 凤姐 5 乔碧萝 boy2girl(bid和gid应该是联合唯一) id bid gid 1 1 1 2 1 2 3 1 3 4 2 2 5 2 4 6 2 5
table文の構築:
# 第一种创建方式 """ class Boy(models.Model): bname = models.CharField(max_length=32,null=True) class Girl(models.Model): gname = models.CharField(max_length=32,null=True) class Boy2Girl(models.Model): b = models.ForeignKey("Boy",null=True) g = models.ForeignKey("Girl",null=True) # 联合唯一索引 class Meta: unique_together = [ ('b','g') ] # 联合索引 #class Meta: # index_together = [ # ('b','g') # ] """ # 第二种创建方式 """ class UserInfo(models.Model): name = models.CharField(max_length=32, null=True) age = models.IntegerField(null=True) class Private(models.Model): salary = models.CharField(max_length=32, null=True) sp = models.OneToOneField("UserInfo", null=True) class Boy(models.Model): bname = models.CharField(max_length=32,null=True) g = models.ManyToManyField('Girl',null=True) class Girl(models.Model): gname = models.CharField(max_length=32,null=True) """ # 两种方式的区别 ''' 第一种方式比较的灵活,自己可以添加任意的字段 第二种方式比较死板,只能生成两个字段。如果将来业务扩展,就需要重新打破重来 因此,推荐使用第一种方式。 '''
データの作成:
boyinfo = [ models.Boy(bname='雷俊'), models.Boy(bname='雷鸣'), models.Boy(bname='雷震子'), models.Boy(bname='雷锋'), models.Boy(bname='雷军'), ] models.Boy.objects.bulk_create(boyinfo) girlinfo = [ models.Girl(gname="真真"), models.Girl(gname="练练"), models.Girl(gname="爱爱"), models.Girl(gname="凤姐"), models.Girl(gname="乔碧萝"), ] models.Girl.objects.bulk_create(girlinfo) b2ginfo = [ models.Boy2Girl(b_id=1,g_id=1), models.Boy2Girl(b_id=1,g_id=2), models.Boy2Girl(b_id=1,g_id=3), models.Boy2Girl(b_id=2,g_id=4), models.Boy2Girl(b_id=2,g_id=5), models.Boy2Girl(b_id=1,g_id=5), ] models.Boy2Girl.objects.bulk_create(b2ginfo)
要件:レイJunとの出会い系の女の子を見て
# 第一种方式:从Boy表中开始查询 res = models.Boy.objects.filter(bname='雷俊').first() # res 是一个对象: Boy object res = res.boy2girl_set.all() for i in res: # i对象是 Boy2Girl 的对象 # i.g 是一个对象。然后直接使用.获取gname print(i.g.gname) print(res) # 第二种方式:从Boy2Girl表开始查询 res = models.Boy2Girl.objects.filter(b__bname='雷俊').all() print(res) for love in res: print(love.g.gname) # 第三种方式:在第二种方式的基础上进行改进 res = models.Boy2Girl.objects.filter(b__bname='雷俊').values('g__gname') print(res) ''' <QuerySet [{'g__gname': '真真'}, {'g__gname': '练练'}, {'g__gname': '爱爱'}, {'g__gname': '乔碧萝'}]> ''' # 第四种方式: res = models.Boy.objects.filter(bname='雷俊').values('boy2girl__g__gname') print(res)
列のデータ型
デジタルタイプ(キー)
mysqlの 蛇 TINYINT 存在しません。 SMALLINT SmallIntegerField MEDIUMINT 存在しません。 int型(符号なし) IntegerFieldと(PositiveIntegerField) BIGINT(符号なし) BigIntegerField(PositiveBigIntegerField) 小数 DecimalFieldは 浮く FloatField ダブル 存在しません。 弦
mysqlの 蛇 CHAR 存在しません。 VARCHAR CharFieldです テキスト テキストフィールド 時間
mysqlの 蛇 日付 DateFieldに 日付時刻 DateTimeField型 ORMデータタイプ:
EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 - 参数: protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串)
制約のデータタイプ
パラメータ
MySQLの制約
null 数据库中字段是否可以为空 db_column 数据库中字段的列名 default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
ORMの制約
verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '优先错信息1', 'c2': '优先错信息2', 'c3': '优先错信息3', }, validators=[ RegexValidator(regex='root_\d+', message='错误了', code='c1'), RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'), EmailValidator(message='又错误了', code='c3'), ] )
ページング
A:ページネーションを建てジャンゴ
urls.py
urlpatterns = [ url(r'^test2/', views.test2), ]
views.py
def test2(request): cur_page = request.GET.get('cur_page') print(cur_page,type(cur_page)) cur_page = int(cur_page) userlist = models.UserInfo.objects.all() from django.core.paginator import Paginator paginator = Paginator(userlist,10) users = paginator.page(cur_page) return render(request,'index.html',{'users':users})
index.htmlを
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for foo in users.object_list %} <li>{{ foo.name }}</li> {% endfor %} {% if users.has_previous %} <a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a> {% endif %} {% for num in users.paginator.page_range %} <a href="/test2/?cur_page={{ num }}">{{ num }}</a> {% endfor %} {% if users.has_next %} <a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a> {% endif %} </ul> </body> </html>
II:カスタムのページング
urls.py
urlpatterns = [ url(r'^test3/', views.test3), ]
views.py
class PageInfo(): def __init__(self,cur_page,total,per_page=10,show_page=11): self.cur_page = cur_page # 当前页 self.per_page = per_page # 一页显示多少行数据 self.total = total # 总数据有多少行 self.show_page = show_page # 页面显示多少索引 a,b = divmod(self.total,self.per_page) if b: a = a + 1 self.total_page = a # 总页数 def get_start(self): start = (self.cur_page - 1) * self.per_page return start def get_end(self): return self.cur_page * self.per_page def get_page(self): half = (self.show_page - 1) // 2 #### taotal_page = 5 < show_page = 11 if self.total_page < self.show_page: begin = 1 end = self.total_page else: #### 左边极值判断 if self.cur_page - half <= 0: begin = 1 # end = self.cur_page + half end = self.show_page #### 右边极值的判断 elif self.cur_page + half > self.total_page: # begin = self.cur_page - half begin = self.total_page - self.show_page + 1 end = self.total_page ### 31 #### 正常页码判断 else: begin = self.cur_page - half end = self.cur_page + half page_list = [] if self.cur_page == 1: astr = "<li><a href='#' aria-label='Previous'><span aria-hidden='true'>«</span></a></li>" else: astr = "<li><a href='/test3/?cur_page=%s' aria-label='Previous'><span aria-hidden='true'>«</span></a></li>" % ( self.cur_page - 1) page_list.append(astr) for i in range(begin, end + 1): if self.cur_page == i: # astr = "<a style='display:inline-block; padding:5px;margin:5px;background-color:red;' href='/custom/?cur_page=%s'>%s</a>" % (i, i) astr = "<li class='active'><a href='/test3/?cur_page=%s'>%s</a></li>" % (i, i) else: # astr = "<a style='display:inline-block; padding:5px;margin:5px' href='/custom/?cur_page=%s'>%s</a>" % (i, i) astr = "<li><a href='/test3/?cur_page=%s'>%s</a></li>" % (i, i) page_list.append(astr) if self.cur_page == self.total_page: astr = "<li><a href='#' aria-label='Next'><span aria-hidden='true'>»</span></a></li>" else: astr = "<li><a href='/test3/?cur_page=%s' aria-label='Next'><span aria-hidden='true'>»</span></a></li>" % ( self.cur_page + 1) page_list.append(astr) s = " ".join(page_list) return s def test3(request): # mysql中limit的分页公式 ''' cur_page: 当前页 show_page_num: 显示多少页 start_page: 起始页 limit 起始位置a, 显示多少页b a = ( cur_page - 1 ) * show_page_num b = show_page_num ''' # 在django中的分页公式(models.UserInfo.objects.filter(id__lte=44)[start:end]) """ show_page_num = 10 cur_page = 1 start = 0 end = 10 cur_page = 2 start = 10 end = 20 cur_page = 3 start =20 end = 30 start = (cur_page - 1) * show_page_num end = cur_page * show_page_num """ cur_page = request.GET.get("cur_page") cur_page = int(cur_page) total = models.UserInfo.objects.count() obj = PageInfo(cur_page,total) start = obj.get_start() end = obj.get_end() # 获取总数据 user_list = models.UserInfo.objects.all()[start:end] return render(request,'custom.html',{"user_list":user_list,"page":obj})
custom.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for foo in users.object_list %} <li>{{ foo.name }}</li> {% endfor %} {% if users.has_previous %} <a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a> {% endif %} {% for num in users.paginator.page_range %} <a href="/test2/?cur_page={{ num }}">{{ num }}</a> {% endfor %} {% if users.has_next %} <a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a> {% endif %} </ul> </body> </html>