首页 > 其他分享 >Django基础 - 06Model模型的关联关系及对象继承

Django基础 - 06Model模型的关联关系及对象继承

时间:2023-04-16 20:35:58浏览次数:45  
标签:verbose models price 关联 06Model pk Django self name

 

一、 一对一关系: 实名认证表

一对一关系: 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

相关文章

  • django保存图片并返回url
    场景描述前端传递一个表单,表单中有title,description,以及image等信息,image在这里传递的是二进制文件后端需要将这些数据保存到一个数据库中。image需要保存到指定文件夹下,并且数据库中保存的是image的路径,之后我们可以通过浏览器访问类似127.0.0.1:8000/xxx/a.jpg访问到这......
  • JMeter 关联、录制脚本、连接数据库
    一、JMeter关联关联:当请求之间有依赖关系,比如一个请求的响应数据是另一个请求的参数数据,这时候就需要用到关联处理。JMeter中常用到的关联方法:正则表达式提取器Xpath提取器JSON提取器1、正则表达式提取器作用:针对任......
  • 敏捷开发领域里的 Epic 以及和 User Story 的关联关系
    在敏捷软件开发领域,Epic(史诗)通常是指一个大型的、跨越多个迭代周期的用户需求或者业务功能。Epic通常包含多个相关的故事(UserStory),这些故事描述了Epic所包含的具体功能和需求。Epic是敏捷开发中用于管理大型需求和复杂业务的一种方式。它可以帮助团队更好地理解用户需求、制......
  • Qt5.9 UI设计(五)——将Tabwidget与treeWidget相互关联
    前言前面一章介绍了ControlTabWidgetControlTreeWidgetmaintitlebar三个子页面同时布局到mainwindow的方法,本章介绍如何将ControlTreeWidget与ControlTabWidget联动。(一)TabWidget子页面实现在maincontent目录下创建otaparatarnsmittelnettester五个目录,用来......
  • Django框架基础3
      本节主要分为两个内容:Django模板加载与响应模板精讲(模板变量、模板标签、判断逻辑(if和for))一、Django模板加载与响应  Django的模板系统将Python代码与HTML代码解耦,动态地生成HTML页面。Django项目可以配置一个或多个模板引擎,但是通常使用Django的模板系统......
  • django中配置favicon.ico
    方法一:使用重定向在项目的urls.py中添加规则:fromdjango.urlsimportpathfromdjango.views.generic.baseimportRedirectViewurlpatterns=[...path('favicon.ico',RedirectView.as_view(url='static/img/favicon.ico')),]复制这种方式我认为是最......
  • Django练手小项目1:云笔记
    Django练手小项目1:云笔记1、创建项目专业版pycharm:新建项目->Django->路径下加上项目名python环境:manage.pystartproject项目名2、创建数据库,设计表结构3、新建应用专业版:点击:tools->运行manage.py->startapp应用名4、注册应用5、配置数据库6、更......
  • 编写你的第一个 Django 应用程序,第1部分
    让我们通过示例来学习。在本教程中,我们将引导您完成基本投票应用程序它将由两部分组成:一个公共网站,允许人们查看投票并在其中投票。允许您添加、更改和删除投票的管理网站。一、开发环境搭建第一步当然就是安装python,网上教程太多了,不再赘述。第二步当然就是安装django......
  • Django中使用session,并设置过期时间
    Django中session的使用使用背景django中自带了一个数据库,名字是djang_session,用户做用户凭证。它有三个字段session_keysession_dataexpire_data这个数字会返回给客户端存储的相关信息过期时间流程:1.用户首次输入账户名和密码,服务端判断正确之后创建一个sesi......
  • django渲染模版时比实际少了8小时?
    这是因为django的时间是UTC时间.我们通过改配置文件将其改成本地时间修改配置文件#将时间从UTC转化成当前时间TIME_ZONE='Asia/Shanghai'#USE_TZ=Truehtml页面上面渲染<td>{{foo.create_datetime|date:"Y-m-dH:i:s"}}</td>......