
1 from django.db import models 2 3 # Create your models here. 4 5 from django.contrib.contenttypes.models import ContentType 6 from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation 7 8 ######################################## 课程表 ######################################## 9 10 class Course(models.Model): 11 """ 12 专题课程 13 """ 14 name = models.CharField(max_length=128, unique=True, verbose_name="模块") 15 course_img = models.CharField(max_length=255) 16 course_type_choices = ((0, '付费'), (1, 'VIP专享'), (2, '学位课程')) 17 course_type = models.SmallIntegerField(choices=course_type_choices) 18 brief = models.TextField(verbose_name="课程概述", max_length=2048) 19 level_choices = ((0, '初级'), (1, '中级'), (2, '高级')) 20 level = models.SmallIntegerField(choices=level_choices, default=1) 21 pub_date = models.DateField(verbose_name="发布日期", blank=True, null=True) 22 period = models.PositiveIntegerField(verbose_name="建议学习周期(days)", default=7) 23 order = models.IntegerField("课程顺序", help_text="从上一个课程数字往后排") 24 attachment_path = models.CharField(max_length=128, verbose_name="课件路径", blank=True, null=True) 25 status_choices = ((0, '上线'), (1, '下线'), (2, '预上线')) 26 status = models.SmallIntegerField(choices=status_choices, default=0) 27 28 order_details = GenericRelation("OrderDetail", related_query_name="course") 29 coupon = GenericRelation("Coupon") 30 price_policy = GenericRelation("PricePolicy") # 用于GenericForeignKey反向查询,不会生成表字段,切勿删除,如有疑问请联系老村长 31 32 def __str__(self): 33 return "%s(%s)" % (self.name, self.get_course_type_display()) 34 35 class CourseDetail(models.Model): 36 """课程详情页内容""" 37 38 course = models.OneToOneField("Course",on_delete=models.CASCADE) 39 hours = models.IntegerField("课时") 40 course_slogan = models.CharField(max_length=125, blank=True, null=True) 41 video_brief_link = models.CharField(max_length=255, blank=True, null=True) 42 why_study = models.TextField(verbose_name="为什么学习这门课程") 43 what_to_study_brief = models.TextField(verbose_name="我将学到哪些内容") 44 career_improvement = models.TextField(verbose_name="此项目如何有助于我的职业生涯") 45 prerequisite = models.TextField(verbose_name="课程先修要求", max_length=1024) 46 recommend_courses = models.ManyToManyField("Course", related_name="recommend_by", blank=True) 47 teachers = models.ManyToManyField("Teacher", verbose_name="课程讲师") 48 49 def __str__(self): 50 return "%s" % self.course 51 52 class Teacher(models.Model): 53 """讲师、导师表""" 54 55 name = models.CharField(max_length=32) 56 role_choices = ((0, '讲师'), (1, '导师')) 57 role = models.SmallIntegerField(choices=role_choices, default=0) 58 title = models.CharField(max_length=64, verbose_name="职位、职称") 59 signature = models.CharField(max_length=255, help_text="导师签名", blank=True, null=True) 60 image = models.CharField(max_length=128) 61 brief = models.TextField(max_length=1024) 62 63 def __str__(self): 64 return self.name 65 66 class PricePolicy(models.Model): 67 """价格与有课程效期表""" 68 content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE) # 关联course or degree_course 69 object_id = models.PositiveIntegerField() 70 content_object = GenericForeignKey('content_type', 'object_id') 71 # course = models.ForeignKey("Course") 72 valid_period_choices = ((1, '1天'), (3, '3天'), 73 (7, '1周'), (14, '2周'), 74 (30, '1个月'), 75 (60, '2个月'), 76 (90, '3个月'), 77 (120, '4个月'), 78 (180, '6个月'), (210, '12个月'), 79 (540, '18个月'), (720, '24个月'), 80 (722, '24个月'), (723, '24个月'), 81 ) 82 valid_period = models.SmallIntegerField(choices=valid_period_choices) 83 price = models.FloatField() 84 85 class Meta: 86 unique_together = ("content_type", 'object_id', "valid_period") 87 88 def __str__(self): 89 return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price) 90 91 class CourseChapter(models.Model): 92 """课程章节""" 93 course = models.ForeignKey("Course", related_name='coursechapters',on_delete=models.CASCADE) 94 chapter = models.SmallIntegerField(verbose_name="第几章", default=1) 95 name = models.CharField(max_length=128) 96 summary = models.TextField(verbose_name="章节介绍", blank=True, null=True) 97 is_create = models.BooleanField(verbose_name="是否创建题库进度", default=True) 98 pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True) 99 100 class Meta: 101 unique_together = ("course", 'chapter') 102 103 def __str__(self): 104 return "%s:(第%s章)%s" % (self.course, self.chapter, self.name) 105 106 class CourseSection(models.Model): 107 """课时目录""" 108 chapter = models.ForeignKey("CourseChapter", related_name='coursesections',on_delete=models.CASCADE) 109 name = models.CharField(max_length=128) 110 order = models.PositiveSmallIntegerField(verbose_name="课时排序", help_text="建议每个课时之间空1至2个值,以备后续插入课时") 111 section_type_choices = ((0, '文档'), (1, '练习'), (2, '视频')) 112 section_type = models.SmallIntegerField(default=2, choices=section_type_choices) 113 section_link = models.CharField(max_length=255, blank=True, null=True, help_text="若是video,填vid,若是文档,填link") 114 video_time = models.CharField(verbose_name="视频时长", blank=True, null=True, max_length=32) # 仅在前端展示使用 115 pub_date = models.DateTimeField(verbose_name="发布时间", auto_now_add=True) 116 free_trail = models.BooleanField("是否可试看", default=False) 117 is_flash = models.BooleanField(verbose_name="是否使用FLASH播放", default=False) 118 player_choices = ((0, "CC"), (1, "POLYV"), (2, "ALI")) 119 player = models.SmallIntegerField(choices=player_choices, default=1, help_text="视频播放器选择") 120 121 def course_chapter(self): 122 return self.chapter.chapter 123 124 def course_name(self): 125 return self.chapter.course.name 126 127 class Meta: 128 unique_together = ('chapter', 'section_link') 129 130 def __str__(self): 131 return "%s-%s" % (self.chapter, self.name) 132 133 134 class OftenAskedQuestion(models.Model): 135 """常见问题""" 136 content_type = models.ForeignKey(ContentType,limit_choices_to={'model__contains': 'course'},on_delete=models.CASCADE) # 关联course or degree_course 137 object_id = models.PositiveIntegerField() 138 content_object = GenericForeignKey('content_type', 'object_id') 139 140 question = models.CharField(max_length=255) 141 answer = models.TextField(max_length=1024) 142 143 def __str__(self): 144 return "%s-%s" % (self.content_object, self.question) 145 146 class Meta: 147 unique_together = ('content_type', 'object_id', 'question') 148 verbose_name_plural = "常见问题" 149 150 ######################################## 优惠券 ######################################## 151 152 class Coupon(models.Model): 153 """优惠券生成规则""" 154 name = models.CharField(max_length=64, verbose_name="活动名称") 155 brief = models.TextField(blank=True, null=True, verbose_name="优惠券介绍") 156 coupon_type_choices = ((0, '立减券'), (1, '满减券'), (2, '折扣券')) 157 coupon_type = models.SmallIntegerField(choices=coupon_type_choices, default=0, verbose_name="券类型") 158 money_equivalent_value = models.FloatField(verbose_name="等值货币") 159 off_percent = models.PositiveSmallIntegerField("折扣百分比", help_text="只针对折扣券,例7.9折,写79", blank=True, null=True) 160 minimum_consume = models.PositiveIntegerField("最低消费", default=0, help_text="仅在满减券时填写此字段") 161 content_type = models.ForeignKey(ContentType, blank=True, null=True,on_delete=models.CASCADE) 162 object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="可以把优惠券跟课程绑定") 163 content_object = GenericForeignKey('content_type', 'object_id') 164 quantity = models.PositiveIntegerField("数量(张)", default=1) 165 open_date = models.DateField("优惠券领取开始时间") 166 close_date = models.DateField("优惠券领取结束时间") 167 valid_begin_date = models.DateField(verbose_name="有效期开始时间", blank=True, null=True) 168 valid_end_date = models.DateField(verbose_name="有效结束时间", blank=True, null=True) 169 coupon_valid_days = models.PositiveIntegerField(verbose_name="优惠券有效期(天)", blank=True, null=True, 170 help_text="自券被领时开始算起") 171 status_choices = ((0, "上线"), (1, "下线")) 172 status = models.SmallIntegerField(choices=status_choices, default=0) 173 date = models.DateTimeField(auto_now_add=True) 174 175 def __str__(self): 176 return "%s(%s)" % (self.get_coupon_type_display(), self.name) 177 178 179 class CouponRecord(models.Model): 180 """优惠券发放、消费纪录""" 181 coupon = models.ForeignKey("Coupon",on_delete=models.CASCADE) 182 account = models.ForeignKey("UserInfo", blank=True, null=True, verbose_name="使用者",on_delete=models.CASCADE) 183 status_choices = ((0, '未使用'), (1, '已使用'), (2, '已过期'), (3, '未领取')) 184 status = models.SmallIntegerField(choices=status_choices, default=0) 185 get_time = models.DateTimeField(blank=True, null=True, verbose_name="领取时间", help_text="用户领取时间") 186 used_time = models.DateTimeField(blank=True, null=True, verbose_name="使用时间") 187 order = models.ForeignKey("Order", blank=True, null=True, verbose_name="关联订单",on_delete=models.CASCADE) # 一个订单可以有多个优惠券 188 date = models.DateTimeField(auto_now_add=True, verbose_name="生成时间") 189 #_coupon = GenericRelation("Coupon") 190 191 def __str__(self): 192 return self.coupon.name+"优惠券记录" 193 194 ######################################## 订单表 ######################################## 195 196 class Order(models.Model): 197 """订单""" 198 payment_type_choices = ((0, '微信'), (1, '支付宝'), (2, '优惠码'), (3, '贝里'), (4, '银联')) 199 payment_type = models.SmallIntegerField(choices=payment_type_choices) 200 payment_number = models.CharField(max_length=128, verbose_name="支付第3方订单号", null=True, blank=True) 201 order_number = models.CharField(max_length=128, verbose_name="订单号", unique=True) # 考虑到订单合并支付的问题 202 account = models.ForeignKey("UserInfo",on_delete=models.CASCADE) 203 actual_amount = models.FloatField(verbose_name="实付金额") 204 # coupon = models.OneToOneField("Coupon", blank=True, null=True, verbose_name="优惠码") #一个订单可以有多个优惠券 205 status_choices = ((0, '交易成功'), (1, '待支付'), (2, '退费申请中'), (3, '已退费'), (4, '主动取消'), (5, '超时取消')) 206 status = models.SmallIntegerField(choices=status_choices, verbose_name="状态") 207 order_type_choices = ((0, '用户下单'), (1, '线下班创建'),) 208 order_type = models.SmallIntegerField(choices=order_type_choices, default=0, verbose_name="订单类型") 209 date = models.DateTimeField(auto_now_add=True, verbose_name="订单生成时间") 210 pay_time = models.DateTimeField(blank=True, null=True, verbose_name="付款时间") 211 cancel_time = models.DateTimeField(blank=True, null=True, verbose_name="订单取消时间") 212 213 def __str__(self): 214 return "%s" % self.order_number 215 216 217 class OrderDetail(models.Model): 218 """订单详情""" 219 order = models.ForeignKey("Order",on_delete=models.CASCADE) 220 content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE) # 可关联普通课程或学位 221 object_id = models.PositiveIntegerField() 222 content_object = GenericForeignKey('content_type', 'object_id') 223 original_price = models.FloatField("课程原价") 224 price = models.FloatField("折后价格") 225 content = models.CharField(max_length=255, blank=True, null=True) # ? 226 valid_period_display = models.CharField("有效期显示", max_length=32) # 在订单页显示 227 valid_period = models.PositiveIntegerField("有效期(days)") # 课程有效期 228 memo = models.CharField(max_length=255, blank=True, null=True) 229 230 def __str__(self): 231 return "%s - %s - %s" % (self.order, self.content_type, self.price) 232 233 class Meta: 234 # unique_together = ("order", 'course') 235 unique_together = ("order", 'content_type', 'object_id') 236 237 238 ######################################## 用户表 ######################################## 239 240 from django.utils.safestring import mark_safe 241 242 from django.contrib.auth.models import AbstractUser 243 244 class UserInfo(AbstractUser): 245 username = models.CharField("用户名", max_length=64, unique=True) 246 email = models.EmailField( 247 verbose_name='email address', 248 max_length=255, 249 unique=True, 250 blank=True, 251 null=True 252 ) 253 uid = models.CharField(max_length=64, unique=True) # 与第3方交互用户信息时,用这个uid,以避免泄露敏感用户信息 254 mobile = models.BigIntegerField(verbose_name="手机", unique=True, help_text="用于手机验证码登录", null=True) 255 qq = models.CharField(verbose_name="QQ", max_length=64, blank=True, null=True, db_index=True) 256 weixin = models.CharField(max_length=128, blank=True, null=True, db_index=True, verbose_name="微信") 257 signature = models.CharField('个人签名', blank=True, null=True, max_length=255) 258 brief = models.TextField("个人介绍", blank=True, null=True) 259 openid = models.CharField(max_length=128, blank=True, null=True) 260 alipay_card = models.CharField(max_length=128, blank=True, null=True, verbose_name="支付宝账户") 261 gender_choices = ((0, '保密'), (1, '男'), (2, '女')) 262 gender = models.SmallIntegerField(choices=gender_choices, default=0, verbose_name="性别") 263 id_card = models.CharField(max_length=32, blank=True, null=True, verbose_name="身份证号或护照号") 264 password = models.CharField('password', max_length=128, 265 help_text=mark_safe('''<a class='btn-link' href='password'>重置密码</a>''')) 266 is_active = models.BooleanField(default=True, verbose_name="账户状态") 267 is_staff = models.BooleanField(verbose_name='staff status', default=False, help_text='决定着用户是否可登录管理后台') 268 name = models.CharField(max_length=32, default="", verbose_name="真实姓名") 269 head_img = models.CharField(max_length=256, default='/static/frontend/head_portrait/logo@2x.png', 270 verbose_name="个人头像") 271 role_choices = ((0, '学员'), (1, '导师'), (2, '讲师'), (3, '管理员'), (4, '班主任'), (5, '线下班主任')) 272 role = models.SmallIntegerField(choices=role_choices, default=0, verbose_name="角色") 273 # balance = models.PositiveIntegerField(default=0, verbose_name="可提现余额") 274 # #此处通过transaction_record表就可以查到,所以不用写在这了 275 memo = models.TextField('备注', blank=True, null=True, default=None, help_text="json格式存储") 276 date_joined = models.DateTimeField(auto_now_add=True, verbose_name="注册时间") 277 278 class Meta: 279 verbose_name = '账户信息' 280 verbose_name_plural = "账户信息" 281 282 283 def save(self, *args, **kwargs): 284 if not self.pk: 285 import hashlib 286 # This code only happens if the objects is not in the database yet. Otherwise it would have pk 287 m = hashlib.md5() 288 m.update(self.username.encode(encoding="utf-8")) 289 self.uid = m.hexdigest() 290 super(UserInfo, self).save(*args, **kwargs) 291 292 293 def __str__(self): 294 return "%s(%s)" % (self.username, self.get_role_display()) 295 296 297 class Token(models.Model): 298 """ 299 The default authorization token model. 300 """ 301 key = models.CharField(max_length=40) 302 user = models.OneToOneField( 303 UserInfo, related_name='auth_token', 304 on_delete=models.CASCADE, verbose_name="关联用户" 305 ) 306 created = models.DateTimeField(verbose_name="创建时间", auto_now_add=True) 307 308 309 def __str__(self): 310 return self.key 311 312 313 ############################################################## 314 315 316 class Student(models.Model): 317 name=models.CharField(max_length=32) 318 age=models.IntegerField() 319 gender=models.IntegerField()
在同步表的时候遇到一个问题,报错userinfo表,是因为Django本身会提供一张user表,我们写的userinfo是在user表的基础上扩展字段,所以要在settings中进行如下配置
AUTH_USER_MODEL="app01.UserInfo" #app01代表创建的app名
这样再同步就没有问题了