一、 一对一关系: 实名认证表
一对一关系: models.OneToOneField
主表的数据是相对重要的(UserEntity), 从表 需要 主动声明关系(RealProfile)
对象获取: 从表获取主表数据, 直接使用字段, 对象.字段名.属性名; 主表获取从表数据: 隐性的, 对象.模型名.属性名
1.1 声明一对一关系
class RealProfile(models.Model): # 声明一对一的关联关系 OneToOneField user = models.OneToOneField(UserEntity, verbose_name='账号', on_delete=models.CASCADE) real_name = models.CharField(max_length=20, verbose_name='真实姓名') id_number = models.CharField(max_length=18, verbose_name='证件号') id_type = models.IntegerField(choices=((0, '身份证'), (1, '护照'), (2, '驾驶证')), verbose_name='证件类型') image1 = models.ImageField(verbose_name='正面照片', upload_to='user/real') image2 = models.ImageField(verbose_name='反面照片', upload_to='user/real') class Meta: db_table = 't_real_profile' verbose_name = '实名认证' verbose_name_plural = verbose_name
class RealProfileAdmin(admin.ModelAdmin): list_display = ('user', 'real_name', 'id_number', 'id_type') admin.site.register(RealProfile, RealProfileAdmin)
1.2 从表获取主表的数据、 主表获取从表的数据
>>> from mainapp.models import UserEntity, RealProfile >>> u1 = RealProfile.objects.filter(real_name='李哪吒').first() >>> u1.user.phone # 从表访问主表数据 '15577778888'
>>> login_u1 = UserEntity.objects.get(pk=1) >>> login_u1.realprofile.id_number # 主表访问从表数据, 模型类的全小写 '3900110011'
1.3 级联关系
on_delete=models.CASCADE 级联删除/ models.SET_NULL级联关系设置为null
class CartEntity(models.Model): user = models.OneToOneField(UserEntity, verbose_name='账号', on_delete=models.CASCADE) no = models.CharField(primary_key=True, max_length=10, verbose_name='购物车编号') class Meta: db_table = 't_cart' verbose_name = verbose_name_plural = '购物车表' def __str__(self): return self.user.name + "(" + self.no + ")"
class CartEntityAdmin(admin.ModelAdmin): list_display = ('user', 'no') admin.site.register(CartEntity, CartEntityAdmin)
二、 一对多关系: 声明购物车与水果的关系表
一对多关系: 使用ForeignKey关系实现; models.ForeignKey
对象获取: 从表获取主表数据, 字段属性
主表获取从表数据: 对象.模型名_set; 结果是数据集合, Manager类型, 支持filter,exclude,all,last,first等方法
2.1 定义一对多关系
class FruitCartEntity(models.Model): cart = models.ForeignKey(CartEntity, on_delete=models.CASCADE, verbose_name='购物车') fruit = models.ForeignKey(FruitEntity, on_delete=models.CASCADE, verbose_name='水果') cnt = models.IntegerField(verbose_name='数量', default=1)
@property def price(self): return round(self.cnt * self.fruit.price, 2) # 显式单个商品的合计
class Meta: db_table = 't_fruit_cart' verbose_name = verbose_name_plural = '购物车详情表' def __str__(self): return self.fruit.name + ':' + self.cart.no
class FruitCartEntityAdmin(admin.ModelAdmin): list_display = ('cart', 'fruit', 'cnt', 'price') admin.site.register(FruitCartEntity, FruitCartEntityAdmin)
2.2 展示计算属性的verbose_name名称
2.2.1 属性方法def price(self) 在后台显示时没有verbose_name, 如何解决
list_display = ('cart', 'fruit', 'cnt', 'price', 'fruit.price') # 使用fruit.price报错 ERRORS: <class 'mainapp.admin.FruitCartEntityAdmin'>: (admin.E108) The value of 'list_display[4]' ref ers to 'fruit.price', which is not a callable, an attribute of 'FruitCartEntityAdmin', or an attribute or method on 'mainapp.FruitCartEntity'.
2.2.2 解决办法: 显示字段可以引用关系实体对象的属性
class FruitCartEntity(models.Model): @property def price(self): return round(self.cnt * self.fruit.price, 2) @property def price_v(self): return self.fruit.price class FruitCartEntityAdmin(admin.ModelAdmin): list_display = ('cart', 'fruit', 'cnt', 'price_v_title', 'price_title') def price_title(self, obj): return obj.price def price_v_title(self, obj): return obj.price_v price_title.short_description = '小计' price_v_title.short_description = '单价'
2.3 主表 读取 从表数据
>>> from mainapp.models import UserEntity >>> login_u = UserEntity.objects.get(pk=1)
# UserEntity 与 CartEntity 是一对一关系, CartEntity 与 FruitCartEntity是 一对多关系
>>> login_u.cartentity.fruitcartentity_set <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals> .RelatedManager object at 0x0000006F5513C4F0>
>>> login_u.cartentity.fruitcartentity_set.all() <QuerySet [<FruitCartEntity: 苹果:CT001>, <FruitCartEntity: 神仙果:CT001>]>
2.4 一对多关系案例: 一个种类对应多种水果
class FruitEntity(models.Model): # category = models.ForeignKey(CategoryEntity, on_delete=models.CASCADE) category = models.ForeignKey(CategoryEntity, related_name='fruits', to_field='id', on_delete=models.CASCADE)
>>> from mainapp.models import CategoryEntity >>> f1.category.name '南方水果' >>> c1 = f1.category >>> c1.fruitentity_set <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager. <locals>.RelatedManager object at 0x000000C8C826E370> >>> cat1 = CategoryEntity.objects.get(pk=1) >>> cat1.name '热带水果' >>> cat1.fruits.values() <QuerySet [{'id': 1, 'name': '火龙果', 'price': 11.50, 'source': '泰国', 'category_id': 1}, {'id': 3, 'name': '神仙果', 'price': 395.59, 'source': '非洲', 'category_id': 1}, {'id': 4, 'name': '荔枝', 'price': 10.78, 'source': '福州', 'category_id': 1}]>
>>> cat1.fruits.values_list() <QuerySet [(1, '火龙果', 11.50, '泰国', 1), (3, '神仙果', 395.59, '非洲', 1),(4, '荔枝', 10.78, '福州', 1)]>
三、 多对多关系
使用第三方表建立多对多关系
3.1 定义多对多关系: 用户收藏商品
class FruitEntity(models.Model): # 默认情况下, 反向引用的名称是当前类的名称(小写)_set,可以通过 related_name 来指定; # db_table='t_collect' 使用第三张表建立 fruit 和user 的多对多关系 users = models.ManyToManyField(UserEntity, db_table='t_collect', related_name='fruits', verbose_name='收藏用户列表', blank=True, null=True)
准备数据
>>> from mainapp.models import UserEntity, FruitEntity >>> FruitEntity.objects.get(pk=1) <FruitEntity: 火龙果> >>> FruitEntity.objects.get(pk=2) <FruitEntity: 苹果> >>> u1 = UserEntity.objects.get(pk=1) >>> u1.name '哪吒' >>> u2 = UserEntity.objects.get(pk=2) >>> u2.name '宋江' >>> f1 = FruitEntity.objects.get(pk=2) >>> f1.name '苹果'
3.2 多对多关系的CRUD操作
### 给用户u1/u2 添加水果 >>> u1.fruits.add(FruitEntity.objects.get(pk=1)) >>> u1.fruits.add(FruitEntity.objects.get(pk=2)) >>> u2.fruits.add(FruitEntity.objects.get(pk=2)) ### 查找水果f1 有哪些用户收藏, 查询用户的信息 >>> f1.users.all() <QuerySet [<UserEntity: 哪吒>, <UserEntity: 宋江>]>
>>> f1.users.values_list() <QuerySet [(1, '哪吒', 3, '15577778888'), (2, '宋江', 47, '15566660000')]>
>>> f1.users.values() <QuerySet [{'id': 1, 'name': '哪吒', 'age': 3, 'phone': '15577778888'}, {'id': 2, 'name': '宋江', 'age': 47, 'phone': '15566660000'}]> ### 查询用户收藏了 哪些水果 >>> u1.fruits.values() <QuerySet [{'id': 1, 'name': '火龙果', 'price': 11.508304793776945, 'source': '泰国', 'category_id': 1}, {'id': 2, 'name': '苹果', 'price': 2.013953338910966, 'source': '烟台', 'category_id': 2}]>
### 用户取消收藏的水果 >>> u1.fruits.remove(FruitEntity.objects.get(pk=1)) >>> u1.fruits.values() <QuerySet [{'id': 2, 'name': '苹果', 'price': 2.013953338910966, 'source': '烟台', 'category_id': 2}]>
3.3 多对多关系案例: 水果与标签
3.3.1 定义标签类
class TagEntity(models.Model): name = models.CharField(max_length=50, unique=True, verbose_name='标签名') order_num = models.IntegerField(default=1, verbose_name='序号') class Meta: db_table = 't_tag' verbose_name = verbose_name_plural = '标签管理' ordering = ['-order_num'] def __str__(self): return self.name
3.3.2 定义多对多关系
class FruitEntity(models.Model): tags = models.ManyToManyField(TagEntity, db_table='t_fruit_tags', related_name='tag_fruits', verbose_name='所有标签')
3.3.3 多对多关系的CRUD操作
### pk=1的水果 添加 两个标签
>>> FruitEntity.objects.get(pk=1).tags.add(TagEntity.objects.get(pk=1)) >>> FruitEntity.objects.get(pk=1).tags.add(TagEntity.objects.get(pk=2))
### pk=1的标签对应的水果 >>> TagEntity.objects.get(pk=1).tag_fruits.values() <QuerySet [{'id': 1, 'name': '火龙果', 'price': 11.50, 'source': '泰国', 'category_id': 1}]>
### pk=1的水果 包含的标签 >>> FruitEntity.objects.get(pk=1).tags.values() <QuerySet [{'id': 1, 'name': '会员半价', 'order_num': 1}, {'id': 2, 'name': '七天包退', 'order_num': 1}]> ### pk=2的水果 包含的标签 >>> FruitEntity.objects.get(pk=2).tags.values() <QuerySet []>
四、模型类的对象继承
将父模型抽象; 父模型的字段会复制在子模型中
4.1 基础类
class BaseModel(models.Model): create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True, null=True) update_time = models.DateTimeField(verbose_name='更新时间', auto_now=True, null=True) class Meta: abstract = True # 抽象的模型类, 不会创建表
4.2 定义OrderModel, 继承BaseModel
class OrderModel(BaseModel): id = models.CharField(max_length=20, primary_key=True, verbose_name='订单号') title = models.CharField(max_length=100, verbose_name='订单名称') price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='金额')
pay_type = models.IntegerField(choices=((0, '余额'),(1,'银行卡'),(2, '微信支付'), (3, '支付宝')), verbose_name='支付方式', default=0) order_status = models.IntegerField(choices=((0, '待支付'), (1, '已支付'), (2, '待收货'), (3, '已收货'), (4, '完成'), (5, '取消')), verbose_name='订单状态', default=0) receiver = models.CharField(max_length=20, verbose_name='收货人姓名') receiver_phone = models.CharField(max_length=11, verbose_name='收货人手机号') receiver_addr = models.CharField(max_length=100, verbose_name='收货地址') class Meta: db_table = 't_order' verbose_name = '订单表' verbose_name_plural = verbose_name def __str__(self): return self.title
4.3 编写orderapp/admin.py
class OrderAdmin(admin.ModelAdmin): list_display = ('id', 'title', 'price', 'pay_type', 'order_status', 'create_time') fields = ('id', 'title', 'price') list_filter = ('order_status', ) admin.site.register(OrderModel, OrderAdmin)
五、 模型类的自关联
标签:verbose,models,price,关联,06Model,pk,Django,self,name From: https://www.cnblogs.com/kingdomer/p/17288942.html