class Section(mptt_models.MPTTModel): """ Model for sectioning the curriculum. """ name = models.CharField(max_length=255, verbose_name=ugettext_lazy('Name')) parent = mptt_models.TreeForeignKey( 'self', related_name='children', null=True, blank=True, verbose_name=ugettext_lazy('Parent section')) weight = models.IntegerField( default=0, verbose_name=ugettext_lazy('Weight'), help_text=ugettext_lazy('Use this for ordering elements.')) scores = models.IntegerField( default=1, validators=[MinValueValidator(1), MaxValueValidator(100)], verbose_name=ugettext_lazy('Learning scores'), help_text=ugettext_lazy( 'Choose a value from 1 to 100. Only relevant for elements without children.' )) notes = models.TextField(blank=True, verbose_name=ugettext_lazy('Notes')) users = models.ManyToManyField(User, through='UserSectionRelation') class Meta: verbose_name = ugettext_lazy('Section') verbose_name_plural = ugettext_lazy('Sections') class MPTTMeta: order_insertion_by = ['weight', 'name'] def __str__(self): return self.name
class Category(mptt_models.MPTTModel, backend_models.AbstractNameModel, backend_models.AbstractCreatedUpdatedModel): parent = mptt_models.TreeForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children")
class Subject(mptt.MPTTModel): name = djm.CharField(max_length=32, verbose_name=_('name')) # Default english name parent = mptt.TreeForeignKey('self', on_delete=djm.CASCADE, null=True, blank=True, related_name='children') @property def localized(self): return self.localizations.filter( language__alpha2=t.get_language()).first() @property def languages(self): return location.Language.objects.filter(localizedsubject__subject=self) def __str__(self): return self.name class Meta: verbose_name = _('subject') verbose_name_plural = _('subjects') unique_together = (('name', 'parent'), )
class Node(mpttmodels.MPTTModel, TimestampableMixin): """ Node model """ ENC_VERSION = 1 name = models.CharField(max_length=255) meta = models.TextField(null=True, blank=True) type = models.IntegerField() data = models.TextField(null=True, blank=True) blob_data = models.FileField(upload_to='', null=True, blank=True) color = models.CharField(max_length=7, blank=True, null=True) parent = mpttmodels.TreeForeignKey('self', null=True, blank=True, related_name='children') enc_version = models.IntegerField(default=ENC_VERSION) created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="nodes") objects = NodeManager() # class Meta: # db_table = u'vaultier_node' def get_user_member(self, user): model = get_model("accounts.Member") return model.objects.get(user=user, node=self.get_root()) def save(self, *args, **kwargs): self.acl_propagation_stopped = True super(Node, self).save(*args, **kwargs) if kwargs.get('force_insert') and not self.parent: self.acl_principal = get_model('accounts', 'Member')( node=self, user=self.created_by, status=MemberStatusField.STATUS_MEMBER, created_by=self.created_by) self.acl_principal.save() else: try: member = get_model('accounts', 'Member').objects.get(node=self.get_root(), user=self.created_by) self.acl_principal = member except: pass self.acl.insert(created=kwargs.get('force_insert')) def delete(self, *args, **kwargs): self.acl_principal = get_model('accounts', 'Member').objects.get( node=self.get_root(), user=self.created_by) super(Node, self).delete(*args, **kwargs)
class Category(mptt_models.MPTTModel): category_name = models.CharField(max_length=255) parent = mptt_models.TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') slug = models.SlugField(max_length=500, unique=True) class MPTTMeta: order_insertion_by = ['category_name'] def __str__(self): return self.category_name
class MPTTComment(mptt_models.MPTTModel): author_name = models.CharField(max_length=32) author_email = models.EmailField() text = models.CharField(max_length=2000) created_at = models.DateTimeField(auto_now_add=True) parent = mptt_models.TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
class Account(mptt_models.MPTTModel): ASSET = 'AS' LIABILITY = 'LI' INCOME = 'IN' EXPENSE = 'EX' EQUITY = 'EQ' ACCOUNT_KIND_CHOICES = ( (ASSET, 'Asset'), (LIABILITY, 'Liability'), (INCOME, 'Income'), (EXPENSE, 'Expense'), (EQUITY, 'Equity') ) name = models.CharField(_('account name'), max_length=255) parent = mptt_models.TreeForeignKey( 'self', null=True, blank=True, related_name='children', db_index=True, on_delete=models.CASCADE ) code = models.CharField(_('account code'), max_length=5) full_code = models.CharField(_('full account code'), max_length=255, db_index=True, unique=True) kind = models.CharField(_('account kind'), max_length=2, choices=ACCOUNT_KIND_CHOICES, blank=True) @property def computed_full_code(self): """ The full code of this account, computed from the database. This is triggered on an account and all descendents when its code changes, and therefore full_code == computed_full_code should always be True. """ # Normally, we would use values_list for this, but here we assume that # this method has been called after get_cached_trees, so we can skip the db. # In the worst case, this results in a lot of queries (like it would anyways). ancestor_codes = map(attrgetter('code'), self.get_ancestors(include_self=True)) return "-".join(ancestor_codes) def __str__(self): return f"{self.full_code} – {self.name}" class MPTTMeta: order_insertion_by = ["code"] class Meta: unique_together = (("parent", "code"),)
class Department(mptt_models.MPTTModel): name = models.CharField(max_length=100) parent = mptt_models.TreeForeignKey('self', null=True, blank=True, related_name='children') created_time = models.DateTimeField(auto_now_add=True) updated_time = models.DateTimeField(auto_now=True) def __str__(self): return u"%s" % self.name
class Category(mptt_models.MPTTModel): name = models.CharField(max_length=255, unique=False) slug = models.SlugField(max_length=255) parent = mptt_models.TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') def __str__(self): return str(self.name)
class Section(mptt_models.MPTTModel): """ Model for sectioning the curriculum. """ name = models.CharField(max_length=255, verbose_name=ugettext_lazy('Name')) parent = mptt_models.TreeForeignKey( 'self', related_name='children', null=True, blank=True, verbose_name=ugettext_lazy('Parent section')) weight = models.IntegerField( default=0, verbose_name=ugettext_lazy('Weight'), help_text=ugettext_lazy('Use this for ordering elements.')) scores = models.IntegerField( default=1, validators=[MinValueValidator(1), MaxValueValidator(100)], verbose_name=ugettext_lazy('Learning scores'), help_text=ugettext_lazy( 'Choose a value from 1 to 100. Only relevant for elements without children.' )) notes = models.TextField(blank=True, verbose_name=ugettext_lazy('Notes')) users = models.ManyToManyField(User, through='UserSectionRelation') class Meta: verbose_name = ugettext_lazy('Section') verbose_name_plural = ugettext_lazy('Sections') class MPTTMeta: order_insertion_by = ['weight', 'name'] def __str__(self): return self.name def serialize(self, user): """ Serializes the progress data of a user for the section. Returns a dictionary. """ data = dict(name=self.name, scores=self.scores, notes=self.notes) try: usersectionrelation = self.usersectionrelation.get(user=user) except UserSectionRelation.DoesNotExist: data.update(dict(progress=0, comment='')) else: data.update( dict(progress=usersectionrelation.progress, comment=usersectionrelation.comment)) return data
class BugzillaComponent(mptt_models.MPTTModel): name = models.CharField(max_length=100, validators=[validate_bc_name]) parent_component = mptt_models.TreeForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.CASCADE) class Meta: unique_together = [ ("name", "parent_component"), ] class MPTTMeta: parent_attr = 'parent_component' order_insertion_by = ['name'] def __unicode__(self): return self.name def get_path_name(self): bugzilla_subcomponents = [] for node in self.get_ancestors(include_self=True): bugzilla_subcomponents.append(node.name) return u"%s" % "/".join(bugzilla_subcomponents) def get_subcomponents(self): path_name = self.get_path_name() result = [] for descendant in self.get_descendants(): descendant_path_name = descendant.get_path_name().replace( path_name + '/', "", 1) result.append(descendant_path_name) return result def export(self, fields=None): _fields = ['name', 'parent_component', 'subcomponents' ] if fields is None else fields result = dict() if 'name' in _fields: result['name'] = self.name if 'parent_component' in _fields: result[ 'parent_component'] = self.parent_component.name if self.parent_component else None if 'subcomponents' in _fields: result['subcomponents'] = self.get_subcomponents() return result
class Comment(comment_models.AbstractComment): role_id = models.IntegerField(blank=True, null=True) edit_role_id = models.IntegerField(blank=True, null=True) parent: thread_models.Thread = mptt_models.TreeForeignKey( thread_models.Thread, models.PROTECT, null=False, blank=False, related_name='comments', verbose_name=_('thread')) def get_absolute_url(self): return urls.reverse('game_forum_api:comment', kwargs={ 'pk': self.pk, 'variation_id': self.parent.variation_id, })
class BusinessModuleTree(mptt_models.MPTTModel): name = models.CharField(max_length=50, verbose_name="业务模块名称") description = models.CharField(max_length=256, verbose_name="业务模块描述", null=True, blank=True) parent = mptt_models.TreeForeignKey('self', null=True, blank=True, related_name='children') disabled = models.BooleanField(default=False, verbose_name="业务模块是否下架") class Meta: ordering = ("level", "disabled", "-id") unique_together = (('name', 'parent'), ) def __str__(self): return self.name
class Region(mptt.MPTTModel, AbstractGroup): """A geographical region modelled as a group.""" users = models.ManyToManyField( settings.AUTH_USER_MODEL, verbose_name=_("Users"), related_name='regions', help_text=_("Users who can access this region")) parent = mptt.TreeForeignKey('self', null=True, blank=True, related_name="children", db_index=True) boundary = models.ForeignKey('groups.Boundary', null=True, verbose_name=_('boundary'), related_name='regions', on_delete=models.SET_NULL) class MPTTMeta: order_insertion_by = ['name'] @transaction.atomic def deactivate(self): # Make this region's parent the parent of all of its children. with Region.objects.disable_mptt_updates(): for child in self.get_children(): child.parent = self.parent child.save() Region.objects.rebuild() # Move this node out of the tree. # If this region is re-activated, it will appear at the top level. self.parent = None super(Region, self).deactivate() def get_users(self): return self.users.filter(is_active=True).select_related('profile') @classmethod def sync_with_temba(cls, org, uuids): """Rebuild the tree hierarchy after new nodes are added.""" super(Region, cls).sync_with_temba(org, uuids) Region.objects.rebuild()
class Product(models.Model): name = models.CharField(max_length=255) price = models.DecimalField(decimal_places=2, max_digits=10) image = models.ImageField(upload_to='product/%Y/%m/', blank=True, null=True) category = mptt_models.TreeForeignKey('Category', null=True, blank=True, on_delete=models.ForeignKey) description = RichTextField() rating = models.PositiveSmallIntegerField(default=0) quantity = models.PositiveIntegerField(null=True, blank=True) slug = models.SlugField(max_length=255) is_sale = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ('name',) db_table = 'products' def __str__(self): return self.name
class Comment(MPTTModel): name = models.CharField(max_length=100) text = RichTextField() # 上一个人名称 previous = models.CharField(blank=True, null=True, max_length=100) # 头像地址 avatar_url = models.CharField(max_length=4000, blank=True, default="") # parent为该评论的父评论,所以第一个参数为'self',当为空时表示为第一层级的评论 # 指定related_name='children',这样可以父评论通过comment.children获取子评论,默认是通过comment.comment_set获取 # parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.SET_NULL) parent = mpttModels.TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True, on_delete=models.SET_NULL) created_time = models.DateTimeField(auto_now_add=True) # parent = post = models.ForeignKey('blog.Article', on_delete=models.CASCADE) # 访问者ip地址 ip = models.CharField(max_length=100, blank=True) # 访问者所在城市 city = models.CharField(max_length=100, blank=True) email = models.EmailField(max_length=255, blank=True) url = models.URLField(blank=True) visible = models.BooleanField(default=True) def __str__(self): return self.text[:20] class MPTTMeta: order_insertion_by = ['-created_time']
class ProcessNode(mptt.MPTTModel, UUIDMixin, TimestampMixin): """ Model representing the nodes in a tree of various processes done to a sample. """ prefix = 'n' comment = fields.RichTextField(blank=True) parent = mptt.TreeForeignKey('self', null=True, related_name='children') process = models.ForeignKey(Process, null=True) piece = models.CharField(max_length=5) number = models.IntegerField(default=1) objects = mptt.TreeManager() def get_sample(self): return self.get_root().sample def swap_processes(self, other): tmp = self.process_id self.process_id = other.process_id other.process_id = tmp self.save() other.save()
class AbstractComment(models.Model): """ Forum comment """ class Meta: verbose_name = _('comment') verbose_name_plural = _('comments') ordering = ['id'] abstract = True objects = models.Manager() # linters don't worry, be happy parent = mptt_models.TreeForeignKey(thread_models.Thread, models.PROTECT, null=False, blank=False, related_name='comments', verbose_name=_('thread')) title = models.CharField(max_length=255, unique=False, verbose_name=_('title')) body = models.TextField(verbose_name=_('body')) user = models.ForeignKey(User, models.PROTECT, null=False, blank=False, related_name='%(app_label)s', verbose_name=_('author')) editor = models.ForeignKey(User, models.PROTECT, null=True, blank=True, related_name='%(app_label)s_edited', verbose_name=_('edited by')) create_time = models.DateTimeField( auto_now_add=True, verbose_name=_('created at'), ) edit_time = models.DateTimeField( null=True, blank=True, verbose_name=_('edited at'), ) reply = models.ForeignKey('self', models.PROTECT, null=True, blank=True, related_name='answers', verbose_name=_('reply to')) deleted = models.BooleanField(default=False, verbose_name=_(u'deleted')) order = models.IntegerField( null=False, blank=False, verbose_name=_(u'order'), ) data = jsonfield.JSONField(default=default_json) media = jsonfield.JSONField(default=default_json) def __str__(self): return self.title[:40] if self.title else self.body[:40] def is_thread(self): return not self.order def get_absolute_url(self): return urls.reverse('forum_api:comment', kwargs={'pk': self.pk})
class Department(mptt_models.MPTTModel): title = models.CharField(max_length=255) parent = mptt_models.TreeForeignKey('self', null=True, blank=True) def __str__(self): return self.title
class AbstractThread(mptt_models.MPTTModel): """ Forum thread """ class Meta: verbose_name = _('thread') verbose_name_plural = _('threads') ordering = ['id'] abstract = True objects = ThreadManager() title = models.CharField(max_length=255, unique=False, verbose_name=_('title')) body = models.TextField(verbose_name=_('body')) parent = mptt_models.TreeForeignKey('self', models.PROTECT, null=True, blank=True, related_name='children', verbose_name=_('parent thread')) room = models.BooleanField(default=False, verbose_name=_(u'room')) user = models.ForeignKey(User, models.PROTECT, related_name='%(app_label)s', verbose_name=_('author')) default_rights = models.SmallIntegerField( default=None, blank=True, null=True, verbose_name=_(u'access type'), choices=DEFAULT_RIGHTS_CHOICES, ) create_time = models.DateTimeField( auto_now_add=True, verbose_name=_('created at'), ) closed = models.BooleanField(default=False, verbose_name=_(u'closed')) important = models.BooleanField(default=False, verbose_name=_(u'important')) deleted = models.BooleanField(default=False, verbose_name=_(u'deleted')) data = jsonfield.JSONField(default=default_json) media = jsonfield.JSONField(default=default_json) def __str__(self): return (self.title or self.body)[:40] def descendant_count(self): return (self.rght - self.lft - 1) / 2 def get_absolute_url(self): return urls.reverse('forum_api:thread', kwargs={'pk': self.pk}) def rights(self, user_id): rights = self.data['rights'] result = rights['all'] if user_id: result |= rights['users'].get(str(user_id), 0) return result def read_right(self, user): return bool(user.is_superuser or (self.rights(user.pk) & ACCESS_READ)) def write_right(self, user): return bool( (not self.closed) and (user.is_superuser or (self.rights(user.pk) & ACCESS_WRITE))) def moderate_right(self, user): return bool(user.is_superuser or (self.rights(user.pk) & ACCESS_MODERATE)) def edit_right(self, user): return bool(user.is_superuser or (self.rights(user.pk) & ACCESS_EDIT)) @property def moderators(self): return User.objects.filter(pk__in=[ pk for pk, right in self.data.get('rights', {}).get( 'users', {}).items() if right & ACCESS_MODERATE ]) @property def accessed_users(self): if self.default_rights != NO_ACCESS: return None return User.objects.filter(pk__in=[ pk for pk, right in self.data.get('rights', {}).get( 'users', {}).items() if right & ACCESS_READ ]) def rights_to_json(self, user): return { 'write': self.write_right(user), 'moderate': self.moderate_right(user), 'edit': self.edit_right(user), 'move': self.edit_right(user), }