class Presentation(models.Model): title = models.CharField(max_length=100) name = models.SlugField(max_length=50, unique=True) owner = models.ForeignKey(User) hidden = models.BooleanField(default=False) source = models.CharField(max_length=1024, null=True) description = models.TextField(blank=True, null=True) password = models.CharField(max_length=32, blank=True, null=True) fieldset = models.ForeignKey(FieldSet, null=True) hide_default_data = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) ownedwrapper = generic.GenericRelation('util.OwnedWrapper') def save(self, **kwargs): unique_slug(self, slug_source='title', slug_field='name', check_current_slug=kwargs.get('force_insert')) super(Presentation, self).save(kwargs) def get_absolute_url(self, edit=False): return reverse(edit and 'presentation-edit' or 'presentation-view', kwargs={ 'id': self.id, 'name': self.name }) def override_dates(self, created=None, modified=None): cursor = connection.cursor() if created and self.id: cursor.execute( "UPDATE %s SET created=%%s WHERE id=%%s" % self._meta.db_table, [created, self.id]) if modified and self.id: cursor.execute( "UPDATE %s SET modified=%%s WHERE id=%%s" % self._meta.db_table, [modified, self.id]) def cached_items(self): if not hasattr(self, '_cached_items'): self._cached_items = tuple(self.items.all()) return self._cached_items def records(self): return [i.record for i in self.items.all()] def visible_item_count(self): return len(filter(lambda i: not i.hidden, self.cached_items())) def hidden_item_count(self): return len(filter(lambda i: i.hidden, self.cached_items())) def duplicate(self): dup = Presentation() dup.title = self.title dup.owner = self.owner dup.hidden = self.hidden dup.description = self.description dup.password = self.password dup.fieldset = self.fieldset dup.hide_default_data = self.hide_default_data return dup @staticmethod def check_passwords(passwords): if passwords: q = reduce(lambda a, b: a | b, (Q(id=id, password=password) for id, password in passwords.iteritems())) return Presentation.objects.filter(q).values_list('id', flat=True) else: return [] def verify_password(self, request): self.unlocked = (self.owner == request.user) or ( not self.password) or (request.session.get( 'passwords', dict()).get(self.id) == self.password) return self.unlocked @staticmethod def published_Q(owner=None): publish_permission = Permission.objects.get( codename='publish_presentations') valid_publishers = User.objects.filter( Q(id__in=publish_permission.user_set.all()) | Q(groups__id__in=publish_permission.group_set.all()) | Q(is_superuser=True)) q = Q(owner__in=valid_publishers) & Q(hidden=False) if owner and not owner.is_anonymous(): return q | Q( id__in=filter_by_access(owner, Presentation, manage=True)) else: return q @staticmethod def get_by_id_for_request(id, request): p = (filter_by_access(request.user, Presentation).filter( Presentation.published_Q(request.user), id=id)) return p[0] if p and p[0].verify_password(request) else None class Meta: permissions = (("publish_presentations", "Can publish presentations"), )
class View(Entity): """ :class:`View` is an abstract model that represents an item which can be "rendered", generally in response to an :class:`HttpRequest`. """ #: A generic relation back to nodes. nodes = generic.GenericRelation(Node, content_type_field='view_content_type', object_id_field='view_object_id') #: An attribute on the class which defines whether this :class:`View` can handle subpaths. Default: ``False`` accepts_subpath = False @classmethod def handles_subpath(cls, subpath): """Returns True if the :class:`View` handles the given subpath, and False otherwise.""" if not cls.accepts_subpath and subpath != "/": return False return True def reverse(self, view_name=None, args=None, kwargs=None, node=None, obj=None): """ If :attr:`accepts_subpath` is True, try to reverse a URL using the given parameters using ``self`` as the urlconf. If ``obj`` is provided, :meth:`get_reverse_params` will be called and the results will be combined with any ``view_name``, ``args``, and ``kwargs`` that may have been passed in. :param view_name: The name of the view to be reversed. :param args: Extra args for reversing the view. :param kwargs: A dictionary of arguments for reversing the view. :param node: The node whose subpath this is. :param obj: An object to be passed to :meth:`get_reverse_params` to generate a view_name, args, and kwargs for reversal. :returns: A subpath beyond the node that reverses the view, or an absolute url that reverses the view if a node was passed in. :except philo.exceptions.ViewDoesNotProvideSubpaths: if :attr:`accepts_subpath` is False :except philo.exceptions.ViewCanNotProvideSubpath: if a reversal is not possible. """ if not self.accepts_subpath: raise ViewDoesNotProvideSubpaths if obj is not None: # Perhaps just override instead of combining? obj_view_name, obj_args, obj_kwargs = self.get_reverse_params(obj) if view_name is None: view_name = obj_view_name args = list(obj_args) + list(args or []) obj_kwargs.update(kwargs or {}) kwargs = obj_kwargs try: subpath = reverse(view_name, urlconf=self, args=args or [], kwargs=kwargs or {}) except NoReverseMatch, e: raise ViewCanNotProvideSubpath(e.message) if node is not None: return node.construct_url(subpath) return subpath
class BaseContent(models.Model): """Parent class for every content model. """ name = models.CharField(_('name'), max_length=250, db_index=True, blank=False) slug = AutoSlugField(populate_from='name', unique=True, db_index=True, always_update=False, editable=True, blank=True) published = models.BooleanField(_('published'), default=True) # user that uploads the content user = models.ForeignKey(User, editable=False, blank=True, null=True) related_contents = generic.GenericRelation(RelatedContent, object_id_field='self_id', content_type_field='self_type') creation_date = models.DateTimeField(_('creation date'), editable=True, default=datetime.now) modification_date = models.DateTimeField(_('modification date'), auto_now=True, editable=False, default=datetime.now) allow_comments = models.CharField(_('allow comments'), max_length=4, choices = ( ('SITE',_('default')), ('YES',_('enabled')), ('NO',_('disabled')) ), default='SITE') comments = generic.GenericRelation(Comment, object_id_field="object_pk") show_author = models.CharField(_('show author'), max_length=6, default='SITE', choices = ( ('AUTHOR', _('author')), ('USER', _('user if author is empty')), ('SITE', _('default')) ), help_text=_('Select which field to use to show as author of this content.')) def get_absolute_url(self): return '/%s/%s/' % (self.get_object_name(), self.slug) @classmethod def get_app_label(cls): return get_app_label(cls) @classmethod def get_object_name(cls): return get_object_name(cls) @classmethod def get_verbose_name(cls): return cls._meta.verbose_name @property def get_last_change_date(self): return self.modification_date def translations(self): trans_links = [] for lang in settings.LANGUAGES: # we look for the number rosetta uses to identity an app # which can be different for each language lang_code = lang[0] app_idx = None for i, path in enumerate(find_pos(lang_code)): project_path = cyclope.settings.CYCLOPE_PROJECT_PATH common_prefix = os.path.commonprefix([path, project_path]) if common_prefix == project_path: # we found the position for our app app_idx = i break if app_idx is not None: signature = "%s/%s/%s/" % (self._meta.app_label, self._meta.module_name, self.slug) trans_links.append( u'<a href="/rosetta/select/%s/%s/?query=%s">%s</a> ' % (lang[0], app_idx, signature, _(lang[1]))) trans_links = ''.join(trans_links) return trans_links def pictures(self): if getattr(self, "_pictures", False) is not False: return self._pictures self._pictures = None if self.related_contents: pic_model = models.get_model('medialibrary', 'picture') ctype = ContentType.objects.get_for_model(pic_model) rel_contents = self.related_contents.filter(other_type__pk=ctype.pk) self._pictures = [ r.other_object for r in rel_contents ] return self._pictures def get_author_or_user(self): """ Returns the author or the user that created the content as stated on self.show_author and/or SiteSettings.show_author. """ ret = None author = getattr(self, "author", None) site_settings = get_singleton(SiteSettings) if self.show_author == "AUTHOR" or (self.show_author == "SITE" and site_settings.show_author == "AUTHOR"): ret = author elif self.show_author == "USER" or (self.show_author == "SITE" and site_settings.show_author == "USER"): ret = author or self.user # If the ir no author it defaults to user return ret translations.allow_tags = True translations.short_description = _('translations') def __unicode__(self): return self.name class Meta: abstract = True
class ShippingMethodCriterion(models.Model, Criterion): """A criterion for the shipping method. """ operator = models.PositiveIntegerField(_(u"Operator"), blank=True, null=True, choices=SELECT_OPERATORS) shipping_methods = models.ManyToManyField(ShippingMethod, verbose_name=_(u"Shipping methods")) criteria_objects = generic.GenericRelation(CriteriaObjects, object_id_field="criterion_id", content_type_field="criterion_type") def __unicode__(self): values = [] for value in self.value.all(): values.append(value.name) return "%s %s %s" % ("Shipping", self.get_operator_display(), ", ".join(values)) @property def content_type(self): """Returns the content_type of the criterion as lower string. This is for instance used to select the appropriate form for the criterion. """ return u"shipping_method" @property def name(self): """Returns the descriptive name of the criterion. """ return _(u"Shipping method") def is_valid(self, request, product=None): """Returns True if the criterion is valid. """ # Check whether the criteria is part of a shipping method if so the # operator IS and IS_NOT are not allowed. This will later exluded by the # UID. # The reason why we have to check this is that the get_selected_shipping_method # checks for valid shipping methods and call this method again, so that # we get an infinte recursion. import lfs.shipping.utils content_object = self.criteria_objects.filter()[0].content if isinstance(content_object, ShippingMethod): is_shipping_method = True else: is_shipping_method = False if not is_shipping_method and self.operator == IS: shipping_method = lfs.shipping.utils.get_selected_shipping_method(request) return shipping_method in self.shipping_methods.all() elif not is_shipping_method and self.operator == IS_NOT: shipping_method = lfs.shipping.utils.get_selected_shipping_method(request) return shipping_method not in self.shipping_methods.all() elif self.operator == IS_VALID: for sm in self.shipping_methods.all(): if not lfs.criteria.utils.is_valid(request, sm, product): return False return True elif self.operator == IS_NOT_VALID: for sm in self.shipping_methods.all(): if lfs.criteria.utils.is_valid(request, sm, product): return False return True else: return False @property def value(self): """Returns the value of the criterion. """ return self.shipping_methods def as_html(self, request, position): """Renders the criterion as html in order to be displayed within several forms. """ selected_shipping_methods = self.shipping_methods.all() shipping_methods = [] for sm in ShippingMethod.objects.filter(active=True): if sm in selected_shipping_methods: selected = True else: selected = False shipping_methods.append({ "id": sm.id, "name": sm.name, "selected": selected, }) return render_to_string("manage/criteria/shipping_method_criterion.html", RequestContext(request, { "id": "ex%s" % self.id, "operator": self.operator, "value": self.value, "position": position, "shipping_methods": shipping_methods, }))
class Document2(models.Model): owner = models.ForeignKey(auth_models.User, db_index=True, verbose_name=_t('Owner'), help_text=_t('Creator.'), related_name='doc2_owner') name = models.CharField(default='', max_length=255) description = models.TextField(default='') uuid = models.CharField(default=uuid_default, max_length=36, db_index=True) type = models.CharField( default='', max_length=32, db_index=True, help_text=_t( 'Type of document, e.g. Hive query, Oozie workflow, Search Dashboard...' )) data = models.TextField(default='{}') extra = models.TextField(default='') last_modified = models.DateTimeField(auto_now=True, db_index=True, verbose_name=_t('Time last modified')) version = models.SmallIntegerField(default=1, verbose_name=_t('Document version'), db_index=True) is_history = models.BooleanField(default=False, db_index=True) tags = models.ManyToManyField('self', db_index=True) dependencies = models.ManyToManyField('self', db_index=True) doc = generic.GenericRelation( Document, related_name='doc_doc') # Compatibility with Hue 3 objects = Document2Manager() unique_together = ('uuid', 'version', 'is_history') def natural_key(self): return (self.uuid, self.version, self.is_history) @property def data_dict(self): if not self.data: self.data = json.dumps({}) data_python = json.loads(self.data) return data_python def update_data(self, post_data): data_dict = self.data_dict data_dict.update(post_data) self.data = json.dumps(data_dict) def get_absolute_url(self): if self.type == 'oozie-coordinator2': return reverse('oozie:edit_coordinator') + '?coordinator=' + str( self.id) elif self.type == 'oozie-bundle2': return reverse('oozie:edit_bundle') + '?bundle=' + str(self.id) elif self.type == 'notebook': return reverse('spark:editor') + '?notebook=' + str(self.id) elif self.type == 'search-dashboard': return reverse('search:index') + '?collection=' + str(self.id) else: return reverse('oozie:edit_workflow') + '?workflow=' + str(self.id) def to_dict(self): return { 'owner': self.owner.username, 'name': self.name, 'description': self.description, 'uuid': self.uuid, 'id': self.id, 'doc1_id': self.doc.get().id if self.doc.exists() else -1, 'type': self.type, 'last_modified': self.last_modified.strftime(UTC_TIME_FORMAT), 'last_modified_ts': calendar.timegm(self.last_modified.utctimetuple()), 'isSelected': False, 'absoluteUrl': self.get_absolute_url() } def can_read_or_exception(self, user): self.doc.get().can_read_or_exception(user)
class OddRelation2(models.Model): name = models.CharField(max_length=100) tlinks = generic.GenericRelation(TextLink)
class UserProfile(models.Model, ExtendedAttributesManager): user = models.ForeignKey(User, unique=True, related_name='profile') hidden_status = models.BooleanField(default=False) hidden_email = models.BooleanField(default=False) rating_total = models.IntegerField(default=0) signature = models.TextField(blank=True) secret_question = models.TextField(blank=True) secret_answer = models.TextField(blank=True) short_desc = models.CharField(max_length=255, blank=True) long_desc = models.TextField(blank=True) custom_nick_display = models.TextField(blank=True) auto_login = models.BooleanField(blank=True) back_to_topic = models.BooleanField(blank=True) auto_quote = models.BooleanField(blank=True) link_source_post = models.BooleanField(blank=True) always_preview = models.BooleanField(blank=True) # mod_denied = models.BooleanField(blank = True) # can_modify_profile_own = models.BooleanField(blank = True) # can_change_custom_nick_display = models.BooleanField(blank = True) # can_change_short_desc = models.BooleanField(blank = True) show_ruler = models.BooleanField(blank=True) save_password = models.BooleanField(blank=True) contributor = models.BooleanField(blank=True) is_alias = models.BooleanField(blank=True) post_per_page = models.SmallIntegerField(blank=True, default=30) min_rating = models.SmallIntegerField(blank=True, default=2) mana = models.IntegerField(default=0) last_post = models.ForeignKey("Post", blank=True, null=True, related_name="posted_by", editable=False) posts_count = models.IntegerField(blank=True, default=0, editable=False) _extended_attributes = generic.GenericRelation("ExtendedAttributeValue") ignores = generic.GenericRelation(Ignore) _replies = generic.GenericRelation("Post", editable=False) _last_reply_id = models.PositiveIntegerField(default=0, blank=True, editable=False) # reverse_timestamp = models.PositiveIntegerField(default = 0) timestamp = models.PositiveIntegerField(blank=True, default=0, db_index=True, editable=False) replies_count = models.IntegerField( default=0, editable=False) #This should be a denorm. last_page_url = models.CharField(max_length=255, blank=True, default='', editable=False) last_page_time = models.DateTimeField(default=datetime.datetime.now(), db_index=True, editable=False) def __unicode__(self): return self.user.username @models.permalink def get_absolute_url(self): # name=name+'\x01' if name.endswith('.') else name return ('profiles_profile_detail', (), { 'username': iri_to_uri(self.user.username) }) @models.permalink def get_replies_url(self): return ('board_profile_view_replies', (), { 'username': iri_to_uri(self.user.username) }) @property def replies(self): return self._replies.filter(is_active=True).select_related('postdata') @property def last_reply( self ): #TODO: Check if we want to have this return the actual object? return self._last_reply_id @property def posts(self): return self.user._posts.select_related('user', 'postdata').order_by( '-pk') #IGNORE:W0212 @property def interactions(self): return Interaction.objects.filter(user=self) @property def favorites(self): faves = Fave.objects.get_for_user(self.user) post_ct = ContentType.objects.get_for_model(Post).pk tag_ct = ContentType.objects.get_for_model(Tag).pk # userprofile_ct = ContentType.objects.get_for_model(UserProfile).pk userpost_ct = ContentType.objects.get_for_model(User).pk favorites_list = { post_ct: [], tag_ct: [], # userprofile_ct:[], userpost_ct: [], } itypes = InteractionType.objects.filter( name='read', content_type__in=favorites_list).values('content_type_id', 'pk') ctypes = dict((i["pk"], i["content_type_id"]) for i in itypes) for f in faves: favorites_list[f.content_type_id].append(f.object_id) fave_list = dict( (i["pk"], favorites_list[i["content_type_id"]]) for i in itypes) q = Q() for itype, f in fave_list.iteritems(): q = q | (Q(interaction_type=itype) & Q(object_id__in=f)) last_interactions = {} for li in self.interactions.filter(q): try: ct = ctypes[li.interaction_type_id] if not last_interactions.has_key(ct): last_interactions[ct] = {} last_interactions[ct][li.object_id] = li except KeyError: pass faved_objects = {} faved_objects[post_ct] = dict((o.pk, { 'last': o.last_reply, 'obj': o, 'type': 'post' }) for o in Post.objects.filter(pk__in=favorites_list[post_ct])) faved_objects[tag_ct] = dict((o.pk, { 'last': o.timestamp, 'obj': o, 'type': 'tag' }) for o in Tag.objects.filter(pk__in=favorites_list[tag_ct])) # faved_objects[userprofile_ct] = dict((o.pk, {'last':o.last_reply, 'obj':o, 'type':'userprofile'}) for o in UserProfile.objects.filter(pk__in = favorites_list[userprofile_ct])) faved_objects[userpost_ct] = dict((o.pk, { 'last': o.get_profile().last_post_id, 'obj': o.get_profile(), 'type': 'user' }) for o in User.objects.filter(pk__in=favorites_list[userpost_ct])) link_prefix = { post_ct: '¶', tag_ct: '.', userpost_ct: '@', # userpost_ct:'by: ', } for f in faves: ct = f.content_type_id oid = f.object_id fo = faved_objects[ct][oid] obj = fo['obj'] try: #TODO: Should we link to the last interaction or to the starting point? f.link_start = int( last_interactions[ct][oid].value.split(';')[0]) except KeyError: #This shouldn't actually ever happen, because there _should_ be an interaction of sorts. f.link_start = 0 f.link_href = obj.get_absolute_url() f.link_title = link_prefix[ct] + getattr(obj, 'title', obj.__unicode__()) f.current = fo['last'] f.fresh = fo.get('op', operator.lt)(f.link_start, f.current) f.remove = reverse('unfave_object', kwargs={ 'fave_type_slug': 'star', 'content_type_id': ct, 'object_id': oid }) return faves def save(self, *args, **kwargs): #IGNORE:W0221 if not bool(self._last_reply_id): self._last_reply_id = self.pk super(UserProfile, self).save(*args, **kwargs) # Call the "real" save() method. class Meta: #IGNORE:W0232 app_label = 'board' permissions = ( ("set_nick_display", "Can change nick display"), ("change_short_desc", "Can change short desc"), ("edit_profile_own", "Can edit own profile"), ("become_mod", "Can become mod"), )
class Document2(models.Model): HOME_DIR = '' TRASH_DIR = '.Trash' EXAMPLES_DIR = 'examples' owner = models.ForeignKey(auth_models.User, db_index=True, verbose_name=_t('Owner'), help_text=_t('Creator.'), related_name='doc2_owner') name = models.CharField(default='', max_length=255) description = models.TextField(default='') uuid = models.CharField(default=uuid_default, max_length=36, db_index=True) type = models.CharField(default='', max_length=32, db_index=True, help_text=_t('Type of document, e.g. Hive query, Oozie workflow, Search Dashboard...')) data = models.TextField(default='{}') extra = models.TextField(default='') search = models.TextField(blank=True, null=True, help_text=_t('Searchable text for the document.')) # settings = models.TextField(default='{}') # Owner settings like, can other reshare, can change access last_modified = models.DateTimeField(auto_now=True, db_index=True, verbose_name=_t('Time last modified')) version = models.SmallIntegerField(default=1, verbose_name=_t('Document version'), db_index=True) is_history = models.BooleanField(default=False, db_index=True) dependencies = models.ManyToManyField('self', symmetrical=False, related_name='dependents', db_index=True) parent_directory = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.CASCADE) doc = generic.GenericRelation(Document, related_name='doc_doc') # Compatibility with Hue 3 objects = Document2Manager() class Meta: unique_together = ('uuid', 'version', 'is_history') ordering = ["-last_modified", "name"] def __str__(self): res = '%s - %s - %s' % (force_unicode(self.name), self.owner, self.uuid) return force_unicode(res) @property def data_dict(self): if not self.data: self.data = json.dumps({}) data_python = json.loads(self.data) return data_python @property def path(self): if self.parent_directory: return '%s/%s' % (self.parent_directory.path, self.name) else: return self.name @property def dirname(self): return os.path.dirname(self.path) or '/' @property def is_directory(self): return self.type == 'directory' @property def is_home_directory(self): return self.is_directory and self.parent_directory == None and self.name == self.HOME_DIR @property def is_trash_directory(self): return self.is_directory and self.name == self.TRASH_DIR def natural_key(self): return (self.uuid, self.version, self.is_history) def copy(self, name, owner, description=None): copy_doc = self copy_doc.pk = None copy_doc.id = None copy_doc.uuid = uuid_default() copy_doc.name = name copy_doc.owner = owner if description: copy_doc.description = description copy_doc.save() return copy_doc def update_data(self, post_data): data_dict = self.data_dict data_dict.update(post_data) self.data = json.dumps(data_dict) def get_absolute_url(self): url = None try: if self.type == 'oozie-coordinator2': url = reverse('oozie:edit_coordinator') + '?coordinator=' + str(self.id) elif self.type == 'oozie-bundle2': url = reverse('oozie:edit_bundle') + '?bundle=' + str(self.id) elif self.type.startswith('query'): url = reverse('notebook:editor') + '?editor=' + str(self.id) elif self.type == 'directory': url = '/home2' + '?uuid=' + self.uuid elif self.type == 'notebook': url = reverse('notebook:notebook') + '?notebook=' + str(self.id) elif self.type == 'search-dashboard': url = reverse('search:index') + '?collection=' + str(self.id) elif self.type == 'link-pigscript': url = reverse('pig:index') + '#edit/%s' % self.data_dict.get('object_id', '') elif self.type == 'link-workflow': url = '/jobsub/#edit-design/%s' % self.data_dict.get('object_id', '') else: url = reverse('oozie:edit_workflow') + '?workflow=' + str(self.id) except NoReverseMatch, e: LOG.warn('Could not perform reverse lookup for type %s, app may be blacklisted.' % self.type) return url
class ShippingMethod(models.Model): """Decides how bought products are delivered to the customer. Instance variables: - name The name of the shipping method. This is displayed to the customer to choose the shipping method. - description A longer description of the shipping method. This could be displayed to the customer to describe the shipping method in detail. - note This is displayed to the customer within the checkout process and should contain a short note about the shipping method. - priority The order in which the shipping methods are displayed to the customer. - image An image of the shipping method, which is displayed to customer within the checkout process. - active A flag which decides whether a shipping method is displayed to the customer or not. - tax The tax of the shipping method. - price The default price of the shipping method. This is taken if the shipping method either has no additional prices or if none of he additional prices is valid. - criteria_objects A shipping method may have several criteria which decide whether the shipping method is valid. It is valid if all criteria are true. Only active and valid shipping methods are provided to the shop customer. - delivery_time Reference to a delivery_time """ name = models.CharField(_(u"Name"), max_length=50) description = models.TextField(_(u"Description"), blank=True) note = models.TextField(_(u"Note"), blank=True) priority = models.IntegerField(_(u"Priority"), default=0) image = models.ImageField(_(u"Image"), upload_to="images", blank=True, null=True) active = models.BooleanField(_(u"Active"), default=False) tax = models.ForeignKey(Tax, verbose_name=_(u"Tax"), blank=True, null=True) price = models.FloatField(_(u"Price"), default=0.0) delivery_time = models.ForeignKey(DeliveryTime, verbose_name=_(u"Delivery time"), blank=True, null=True) criteria_objects = generic.GenericRelation( CriteriaObjects, object_id_field="content_id", content_type_field="content_type") objects = ActiveShippingMethodManager() class Meta: ordering = ("priority", ) def __unicode__(self): return self.name def is_valid(self, request, product=None): """The shipping method is valid if it has no criteria or if all assigned criteria are true. If product is given the product is tested otherwise the whole cart. """ from lfs.criteria import utils as criteria_utils return criteria_utils.is_valid(self, request, product)
class UserProfile(caching.base.CachingMixin, models.Model): """Definition of UserProfile Model.""" user = models.OneToOneField(User) registration_complete = models.BooleanField(default=False) date_joined_program = models.DateField(blank=True) date_left_program = models.DateField(blank=True, null=True) local_name = models.CharField(max_length=100, blank=True, default='') birth_date = models.DateField(validators=[_validate_birth_date], blank=True, null=True) city = models.CharField(max_length=50, blank=False, default='') region = models.CharField(max_length=50, blank=False, default='') country = models.CharField(max_length=50, blank=False, default='') lon = models.FloatField(blank=False, null=True) lat = models.FloatField(blank=False, null=True) display_name = models.CharField( max_length=DISPLAY_NAME_MAX_LENGTH, blank=True, default='', unique=True, validators=[ RegexValidator(regex=r'("")|(^[A-Za-z0-9_]+$)', message='Please only A-Z characters, numbers and ' 'underscores.') ]) private_email = models.EmailField(blank=False, null=True, default='') mozillians_profile_url = models.URLField(validators=[ RegexValidator(regex=r'^http(s)?://(www\.)?mozillians.org/', message='Please provide a valid Mozillians url.') ]) twitter_account = models.CharField( max_length=16, default='', blank=True, validators=[ RegexValidator(regex=r'("^$")|(^[A-Za-z0-9_]+$)', message='Please provide a valid Twitter handle.') ]) jabber_id = models.CharField(max_length=50, blank=True, default='') irc_name = models.CharField(max_length=50, blank=False, default='') irc_channels = models.TextField(blank=True, default='') linkedin_url = models.URLField( blank=True, null=False, default='', validators=[ RegexValidator(regex=r'("^$")|(^http(s)?://(.*?)linkedin.com/)', message='Please provide a valid LinkedIn url.') ]) facebook_url = models.URLField( blank=True, null=False, default='', validators=[ RegexValidator(regex=r'("^$")|(^http(s)?://(.*?)facebook.com/)', message='Please provide a valid Facebook url.') ]) diaspora_url = models.URLField(blank=True, null=False, default='') personal_website_url = models.URLField(blank=True, null=False, default='') personal_blog_feed = models.URLField(blank=True, null=False, default='') wiki_profile_url = models.URLField( blank=True, null=False, default='', validators=[ RegexValidator(regex=r'^http(s)?://wiki.mozilla.org/User:'******'Please provide a valid wiki url.') ]) added_by = models.ForeignKey(User, null=True, blank=True, related_name='users_added') bio = models.TextField(blank=True, default='') gender = models.NullBooleanField(choices=((None, 'Gender'), (True, 'Female'), (False, 'Male')), default=None) mentor = models.ForeignKey(User, null=True, blank=True, related_name='mentees', validators=[_validate_mentor], on_delete=models.SET_NULL) functional_areas = models.ManyToManyField(FunctionalArea, related_name='users_matching') tracked_functional_areas = models.ManyToManyField( FunctionalArea, related_name='users_tracking') receive_email_on_add_comment = models.BooleanField(null=False, blank=True, default=True) receive_email_on_add_event_comment = models.BooleanField(null=False, blank=True, default=True) receive_email_on_add_voting_comment = models.BooleanField(null=False, blank=True, default=True) mozillian_username = models.CharField(blank=True, default='', max_length=40) current_streak_start = models.DateField(null=True, blank=True) longest_streak_start = models.DateField(null=True, blank=True) longest_streak_end = models.DateField(null=True, blank=True) first_report_notification = models.DateField(null=True, blank=True) second_report_notification = models.DateField(null=True, blank=True) timezone = models.CharField(max_length=100, blank=True, default='') unavailability_task_id = models.CharField(max_length=256, blank=True, null=True, editable=False, default='') is_rotm_nominee = models.BooleanField(default=False) rotm_nominated_by = models.ForeignKey(User, null=True, blank=True, related_name='rotm_nominations', validators=[_validate_mentor], on_delete=models.SET_NULL) action_items = generic.GenericRelation('dashboard.ActionItem') objects = caching.base.CachingManager() class Meta: permissions = (('create_user', 'Can create new user'), ('can_edit_profiles', 'Can edit profiles'), ('can_delete_profiles', 'Can delete profiles')) def get_absolute_url(self): return reverse('remo.profiles.views.view_profile', kwargs={'display_name': self.display_name}) @property def get_age(self): """Return the age of the user as an integer. Age gets calculated from birth_date variable. Snippet from http://djangosnippets.org/snippets/557/ """ d = timezone.now().date() age = ((d.year - self.birth_date.year) - int( (d.month, d.day) < (self.birth_date.month, self.birth_date.day))) return age def clean(self, *args, **kwargs): """Ensure that added_by variable does not have the same value as user variable. """ if self.added_by == self.user: raise ValidationError('Field added_by cannot be the same as user.') return super(UserProfile, self).clean(*args, **kwargs) def get_action_items(self): """Return a list of Action Items relevant to this model.""" today = timezone.now().date() due_date = datetime.date(today.year, today.month, NOMINATION_END_DAY) name = u'{0} {1}'.format(NOMINATION_ACTION_ITEM, today.strftime('%B')) priority = ActionItem.NORMAL action_item = Item(name, self.user, priority, due_date) return [action_item]
class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model): ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None, verbose_name=_("ref")) milestone = models.ForeignKey("milestones.Milestone", null=True, blank=True, default=None, related_name="user_stories", on_delete=models.SET_NULL, verbose_name=_("milestone")) project = models.ForeignKey("projects.Project", null=False, blank=False, related_name="user_stories", verbose_name=_("project")) owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name="owned_user_stories", verbose_name=_("owner"), on_delete=models.SET_NULL) status = models.ForeignKey("projects.UserStoryStatus", null=True, blank=True, related_name="user_stories", verbose_name=_("status"), on_delete=models.SET_NULL) is_closed = models.BooleanField(default=False) points = models.ManyToManyField("projects.Points", null=False, blank=False, related_name="userstories", through="RolePoints", verbose_name=_("points")) order = models.PositiveSmallIntegerField(null=False, blank=False, default=100, verbose_name=_("order")) created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False, verbose_name=_("created date")) modified_date = models.DateTimeField(auto_now=True, null=False, blank=False, verbose_name=_("modified date")) finish_date = models.DateTimeField(null=True, blank=True, verbose_name=_("finish date")) subject = models.CharField(max_length=500, null=False, blank=False, verbose_name=_("subject")) description = models.TextField(null=False, blank=True, verbose_name=_("description")) assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, default=None, related_name="userstories_assigned_to_me", verbose_name=_("assigned to")) watchers = models.ManyToManyField(settings.AUTH_USER_MODEL, null=True, blank=True, related_name="watched_user_stories", verbose_name=_("watchers")) client_requirement = models.BooleanField( default=False, null=False, blank=True, verbose_name=_("is client requirement")) team_requirement = models.BooleanField( default=False, null=False, blank=True, verbose_name=_("is team requirement")) tags = PickledObjectField(null=False, blank=True, verbose_name=_("tags")) attachments = generic.GenericRelation("attachments.Attachment") generated_from_issue = models.ForeignKey( "issues.Issue", null=True, blank=True, related_name="generated_user_stories", verbose_name=_("generated from issue")) notifiable_fields = [ "subject", "milestone", "owner", "assigned_to", "finish_date", "client_requirement", "team_requirement", "status", "points", "tags", "description", "is_blocked", "blocked_comment", "generated_from_isssue" ] class Meta: verbose_name = "user story" verbose_name_plural = "user stories" ordering = ["project", "order", "ref"] unique_together = ("ref", "project") permissions = (("view_userstory", "Can view user story"), ) def __str__(self): return "({1}) {0}".format(self.ref, self.subject) def __repr__(self): return "<UserStory %s>" % (self.id) def _get_prev_neighbor_filters(self, queryset): conds = [{ "order__lt": "{obj.order}" }, { "order__lte": "{obj.order}", "ref__lt": "{obj.ref}" }] return conds def _get_next_neighbor_filters(self, queryset): conds = [{ "order__gt": "{obj.order}" }, { "order__gte": "{obj.order}", "ref__gt": "{obj.ref}" }] return conds def get_role_points(self): return self.role_points def get_total_points(self): total = 0.0 for rp in self.role_points.select_related("points"): if rp.points.value: total += rp.points.value return total def get_notifiable_assigned_to_display(self, value): if not value: return _("Unassigned") return value.get_full_name() def get_notifiable_tags_display(self, value): if type(value) is list: return ", ".join(value) return value def get_notifiable_points_display(self, value): if isinstance(value, models.manager.Manager): return ", ".join([ "{}: {}".format(rp.role.name, rp.points.name) for rp in self.role_points.all().order_by("role") ]) return None def _get_watchers_by_role(self): return { "owner": self.owner, "assigned_to": self.assigned_to, "suscribed_watchers": self.watchers.all(), "project": self.project, }
class RelayDomain(AdminObject): """Relay domain. A relay domain differs from a usual domaine because its final destination is not reached yet. It must be accepted by the MTA but it will then be transfered to another one. """ name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True, help_text=ugettext_lazy('The domain name')) target_host = models.CharField( ugettext_lazy('target host'), max_length=255, help_text=ugettext_lazy('Remote destination of this domain')) service = models.ForeignKey(Service, default='relay') enabled = models.BooleanField( ugettext_lazy('enabled'), help_text=ugettext_lazy('Check to activate this domain')) verify_recipients = models.BooleanField( ugettext_lazy('verify recipients'), help_text=ugettext_lazy('Check for valid recipients')) owners = generic.GenericRelation(ObjectAccess) objects = RelayDomainManager() class Meta: ordering = ['name'] @property def tags(self): return [{ "name": "relaydomain", "label": _("Relay Domain"), "type": "dom" }, { "name": self.service.name, "label": "%s:" % self.service.name, "type": "srv", "color": "info" }] @property def aliases(self): return self.relaydomainalias_set def __str__(self): return self.name def to_csv(self, csvwriter): """Export this relay domain to CSV. :param csvwriter: """ csvwriter.writerow([ "relaydomain", self.name, self.target_host, self.service.name, self.enabled, self.verify_recipients ]) for rdalias in self.relaydomainalias_set.all(): rdalias.to_csv(csvwriter) def from_csv(self, user, row): """Import a relay domain from CSV. :param user: user importing the relay domain :param str row: relay domain definition """ if len(row) != 6: raise BadRequest(_("Invalid line")) self.name = row[1].strip() self.target_host = row[2].strip() self.service, created = Service.objects.get_or_create( name=row[3].strip()) self.enabled = (row[4].strip() == 'True') self.verify_recipients = (row[5].strip() == 'True') self.save(creator=user) def post_create(self, creator): """Post creation actions. :param ``User`` creator: user whos created this relay domain """ super(RelayDomain, self).post_create(creator) for rdomalias in self.relaydomainalias_set.all(): rdomalias.post_create(creator)
class SavedQuery(models.Model): """ Stores the query that people have save or submitted. Note that this used to be called QueryDesign. Any references to 'design' probably mean a SavedQuery. """ DEFAULT_NEW_DESIGN_NAME = _('My saved query') AUTO_DESIGN_SUFFIX = _(' (new)') TYPES = QUERY_TYPES TYPES_MAPPING = { 'beeswax': HQL, 'hql': HQL, 'impala': IMPALA, 'rdbms': RDBMS, 'spark': SPARK } type = models.IntegerField(null=False) owner = models.ForeignKey(User, db_index=True) # Data is a json of dictionary. See the beeswax.design module. data = models.TextField(max_length=65536) name = models.CharField(max_length=80) desc = models.TextField(max_length=1024) mtime = models.DateTimeField(auto_now=True) # An auto design is a place-holder for things users submit but not saved. # We still want to store it as a design to allow users to save them later. is_auto = models.BooleanField(default=False, db_index=True) is_trashed = models.BooleanField(default=False, db_index=True, verbose_name=_t('Is trashed'), help_text=_t('If this query is trashed.')) is_redacted = models.BooleanField(default=False) doc = generic.GenericRelation(Document, related_name='hql_doc') class Meta: ordering = ['-mtime'] def get_design(self): try: return HQLdesign.loads(self.data) except ValueError: # data is empty pass def clone(self, new_owner=None): if new_owner is None: new_owner = self.owner design = SavedQuery(type=self.type, owner=new_owner) design.data = self.data design.name = self.name design.desc = self.desc design.is_auto = self.is_auto return design @classmethod def create_empty(cls, app_name, owner, data): query_type = SavedQuery.TYPES_MAPPING[app_name] design = SavedQuery(owner=owner, type=query_type) design.name = SavedQuery.DEFAULT_NEW_DESIGN_NAME design.desc = '' if global_redaction_engine.is_enabled(): design.data = global_redaction_engine.redact(data) else: design.data = data design.is_auto = True design.save() Document.objects.link(design, owner=design.owner, extra=design.type, name=design.name, description=design.desc) design.doc.get().add_to_history() return design @staticmethod def get(id, owner=None, type=None): """ get(id, owner=None, type=None) -> SavedQuery object Checks that the owner and type match (when given). May raise PopupException (type/owner mismatch). May raise SavedQuery.DoesNotExist. """ try: design = SavedQuery.objects.get(id=id) except SavedQuery.DoesNotExist, err: msg = _('Cannot retrieve query id %(id)s.') % {'id': id} raise err if owner is not None and design.owner != owner: msg = _('Query id %(id)s does not belong to user %(user)s.') % { 'id': id, 'user': owner } LOG.error(msg) raise PopupException(msg) if type is not None and design.type != type: msg = _('Type mismatch for design id %(id)s (owner %(owner)s) - Expected %(expected_type)s, got %(real_type)s.') % \ {'id': id, 'owner': owner, 'expected_type': design.type, 'real_type': type} LOG.error(msg) raise PopupException(msg) return design
class URLPath(MPTTModel): """ Strategy: Very few fields go here, as most has to be managed through an article's revision. As a side-effect, the URL resolution remains slim and swift. """ # Tells django-wiki that permissions from a this object's article # should be inherited to children's articles. In this case, it's a static # property.. but you can also use a BooleanField. INHERIT_PERMISSIONS = True objects = managers.URLPathManager() _default_manager = objects articles = generic.GenericRelation(ArticleForObject) # Do NOT modify this field - it is updated with signals whenever ArticleForObject is changed. article = models.ForeignKey( Article, on_delete=models.CASCADE, editable=False, verbose_name=_(u'Cache lookup value for articles')) SLUG_MAX_LENGTH = 50 slug = models.SlugField(verbose_name=_(u'slug'), null=True, blank=True, max_length=SLUG_MAX_LENGTH) site = models.ForeignKey(Site) parent = TreeForeignKey('self', null=True, blank=True, related_name='children') def __init__(self, *args, **kwargs): pass # Fixed in django-mptt 0.5.3 #self._tree_manager = URLPath.objects return super(URLPath, self).__init__(*args, **kwargs) def __cached_ancestors(self): """ This returns the ancestors of this urlpath. These ancestors are hopefully cached from the article path lookup. Accessing a foreign key included in add_selecte_related on one of these ancestors will not occur an additional sql query, as they were retrieved with a select_related. If the cached ancestors were not set explicitly, they will be retrieved from the database. """ if not self.get_ancestors().exists(): self._cached_ancestors = [] if not hasattr(self, "_cached_ancestors"): self._cached_ancestors = list( self.get_ancestors().select_related_common()) return self._cached_ancestors def __cached_ancestors_setter(self, ancestors): self._cached_ancestors = ancestors # Python 2.5 compatible property constructor cached_ancestors = property(__cached_ancestors, __cached_ancestors_setter) def set_cached_ancestors_from_parent(self, parent): self.cached_ancestors = parent.cached_ancestors + [parent] @property def path(self): if not self.parent: return "" ancestors = filter(lambda ancestor: ancestor.parent is not None, self.cached_ancestors) slugs = [obj.slug if obj.slug else "" for obj in ancestors + [self]] return "/".join(slugs) + "/" def is_deleted(self): """ Returns True if this article or any of its ancestors have been deleted """ return self.first_deleted_ancestor() is not None def first_deleted_ancestor(self): for ancestor in self.cached_ancestors + [self]: if ancestor.article.current_revision.deleted == True: return ancestor return None @transaction.commit_manually def delete_subtree(self): """ NB! This deletes this urlpath, its children, and ALL of the related articles. This is a purged delete and CANNOT be undone. """ try: for descendant in self.get_descendants( include_self=True).order_by("-level"): print "deleting ", descendant descendant.article.delete() transaction.commit() except: transaction.rollback() log.exception("Exception deleting article subtree.") @classmethod def root(cls): site = Site.objects.get_current() root_nodes = list( cls.objects.root_nodes().filter(site=site).select_related_common()) # We fetch the nodes as a list and use len(), not count() because we need # to get the result out anyway. This only takes one sql query no_paths = len(root_nodes) if no_paths == 0: raise NoRootURL("You need to create a root article on site '%s'" % site) if no_paths > 1: raise MultipleRootURLs("Somehow you have multiple roots on %s" % site) return root_nodes[0] class MPTTMeta: pass def __unicode__(self): path = self.path return path if path else ugettext(u"(root)") def save(self, *args, **kwargs): super(URLPath, self).save(*args, **kwargs) def delete(self, *args, **kwargs): assert not (self.parent and self.get_children() ), "You cannot delete a root article with children." super(URLPath, self).delete(*args, **kwargs) class Meta: verbose_name = _(u'URL path') verbose_name_plural = _(u'URL paths') unique_together = ('site', 'parent', 'slug') app_label = settings.APP_LABEL def clean(self, *args, **kwargs): if self.slug and not self.parent: raise ValidationError( _(u'Sorry but you cannot have a root article with a slug.')) if not self.slug and self.parent: raise ValidationError( _(u'A non-root note must always have a slug.')) if not self.parent: if URLPath.objects.root_nodes().filter(site=self.site).exclude( id=self.id): raise ValidationError( _(u'There is already a root node on %s') % self.site) super(URLPath, self).clean(*args, **kwargs) @classmethod def get_by_path(cls, path, select_related=False): """ Strategy: Don't handle all kinds of weird cases. Be strict. Accepts paths both starting with and without '/' """ # TODO: Save paths directly in the model for constant time lookups? # Or: Save the parents in a lazy property because the parents are # always fetched anyways so it's fine to fetch them here. path = path.lstrip("/") path = path.rstrip("/") # Root page requested if not path: return cls.root() slugs = path.split('/') level = 1 parent = cls.root() for slug in slugs: if settings.URL_CASE_SENSITIVE: child = parent.get_children().select_related_common().get( slug=slug) child.cached_ancestors = parent.cached_ancestors + [parent] parent = child else: child = parent.get_children().select_related_common().get( slug__iexact=slug) child.cached_ancestors = parent.cached_ancestors + [parent] parent = child level += 1 return parent def get_absolute_url(self): return reverse('wiki:get', kwargs={'path': self.path}) @classmethod def create_root(cls, site=None, title="Root", request=None, **kwargs): if not site: site = Site.objects.get_current() root_nodes = cls.objects.root_nodes().filter(site=site) if not root_nodes: # (get_or_create does not work for MPTT models??) article = Article() revision = ArticleRevision(title=title, **kwargs) if request: revision.set_from_request(request) article.add_revision(revision, save=True) article.save() root = cls.objects.create(site=site, article=article) article.add_object_relation(root) else: root = root_nodes[0] return root @classmethod def create_article(cls, parent, slug, site=None, title="Root", article_kwargs={}, **kwargs): """Utility function: Create a new urlpath with an article and a new revision for the article""" if not site: site = Site.objects.get_current() article = Article(**article_kwargs) article.add_revision(ArticleRevision(title=title, **kwargs), save=True) article.save() newpath = cls.objects.create(site=site, parent=parent, slug=slug, article=article) article.add_object_relation(newpath) return newpath
class Place(models.Model): name = models.CharField(max_length=100) links = generic.GenericRelation(Link) def __str__(self): return "Place: %s" % self.name
class Article(TendenciBaseModel): CONTRIBUTOR_AUTHOR = 1 CONTRIBUTOR_PUBLISHER = 2 CONTRIBUTOR_CHOICES = ((CONTRIBUTOR_AUTHOR, 'Author'), (CONTRIBUTOR_PUBLISHER, 'Publisher')) guid = models.CharField(max_length=40) slug = SlugField(_('URL Path'), unique=True) timezone = TimeZoneField(_('Time Zone')) headline = models.CharField(max_length=200, blank=True) summary = models.TextField(blank=True) body = tinymce_models.HTMLField() source = models.CharField(max_length=300, blank=True) first_name = models.CharField(_('First Name'), max_length=100, blank=True) last_name = models.CharField(_('Last Name'), max_length=100, blank=True) contributor_type = models.IntegerField(choices=CONTRIBUTOR_CHOICES, default=CONTRIBUTOR_AUTHOR) google_profile = models.URLField(_('Google+ URL'), blank=True) phone = models.CharField(max_length=50, blank=True) fax = models.CharField(max_length=50, blank=True) email = models.CharField(max_length=120, blank=True) website = models.CharField(max_length=300, blank=True) release_dt = models.DateTimeField(_('Release Date/Time'), null=True, blank=True) # used for better performance when retrieving a list of released articles release_dt_local = models.DateTimeField(null=True, blank=True) syndicate = models.BooleanField(_('Include in RSS feed'), default=True) featured = models.BooleanField() design_notes = models.TextField(_('Design Notes'), blank=True) group = models.ForeignKey(Group, null=True, default=get_default_group, on_delete=models.SET_NULL) tags = TagField(blank=True) # for podcast feeds enclosure_url = models.CharField(_('Enclosure URL'), max_length=500, blank=True) enclosure_type = models.CharField(_('Enclosure Type'), max_length=120, blank=True) enclosure_length = models.IntegerField(_('Enclosure Length'), default=0) not_official_content = models.BooleanField(_('Official Content'), blank=True) # html-meta tags meta = models.OneToOneField(MetaTags, null=True) categories = generic.GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = generic.GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = ArticleManager() class Meta: permissions = (("view_article", "Can view article"), ) verbose_name = "Article" verbose_name_plural = "Articles" def get_meta(self, name): """ This method is standard across all models that are related to the Meta model. Used to generate dynamic methods coupled to this instance. """ return ArticleMeta().get_meta(self, name) @models.permalink def get_absolute_url(self): return ("article", [self.slug]) @models.permalink def get_version_url(self, hash): return ("article.version", [hash]) def __unicode__(self): return self.headline def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) self.assign_release_dt_local() super(Article, self).save(*args, **kwargs) def assign_release_dt_local(self): """ convert release_dt to the corresponding local time example: if release_dt: 2014-05-09 03:30:00 timezone: US/Pacific settings.TIME_ZONE: US/Central then the corresponding release_dt_local will be: 2014-05-09 05:30:00 """ now = datetime.now() now_with_tz = adjust_datetime_to_timezone(now, settings.TIME_ZONE) if self.timezone and self.release_dt and self.timezone.zone != settings.TIME_ZONE: time_diff = adjust_datetime_to_timezone( now, self.timezone) - now_with_tz self.release_dt_local = self.release_dt + time_diff else: self.release_dt_local = self.release_dt def age(self): return datetime.now() - self.create_dt @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items @property def has_google_author(self): return self.contributor_type == self.CONTRIBUTOR_AUTHOR @property def has_google_publisher(self): return self.contributor_type == self.CONTRIBUTOR_PUBLISHER
class OddRelation1(models.Model): name = models.CharField(max_length=100) clinks = generic.GenericRelation(CharLink)
class Lot(models.Model): # spatial fields coord = models.PointField(srid=4326, blank=True) bounds = models.MultiPolygonField(srid=4326, blank=True) #area = models.FloatField(db_index=True, blank=True) address = models.CharField(db_index=True, max_length=255, blank=True) city = models.CharField(max_length=255) state = models.CharField(max_length=2) country = models.CharField(max_length=255) code = models.CharField(max_length=10, blank=True) # meta fields is_visible = models.BooleanField(db_index=True, default=True) is_vacant = models.BooleanField(db_index=True, default=False) is_public = models.BooleanField(db_index=True, default=False) #auto-generated fields slug = models.SlugField(max_length=255, editable=False) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) comments = generic.GenericRelation(Comment) objects = PassThroughGeoManager.for_queryset_class(LotQuerySet)() class Meta: pass @property def activity_count(self): activity = self.comments.count() + self.ideas.count() return activity @property def has_project(self): if self.ideas: return True else: return False @property def has_comment(self): if self.comments: return True else: return False def get_sqft(self): """ Returns the area in sq ft. """ # Convert our geographic polygons (in WGS84) # into a local projection for New York (here EPSG:32118) try: return self.bounds.transform(102729, clone=True).area except Exception: return None def get_acres(self): """ Returns the area in sq ft. """ # Convert our geographic polygons (in WGS84) # into a local projection for New York (here EPSG:32118) try: return self.bounds.transform(102729, clone=True).area * 0.00002295684 except Exception: return None def __unicode__(self): if self.address: return u'%s' % (self.address) elif self.coord: return u'(%s,%s)' % (self.coord.x, self.coord.y) else: return u'No Address %s' % (self.pk) def get_absolute_url(self): return reverse('lotxlot_lot_detail', args=[str(self.id)]) def save(self, *args, **kwargs): if not self.pk: if self.address: slug = '%s %s, %s' % (self.address, self.city, self.state) elif self.coord: slug = '(%s,%s) %s, %s' % (self.coord.x, self.coord.y, self.city, self.state) else: slug = 'No Address %s %s, %s' % (self.pk, self.city, self.state) self.slug = slugify(slug) super(Lot, self).save(*args, **kwargs)
class Contact(models.Model): notes = generic.GenericRelation(Note)
class File(TendenciBaseModel): file = models.FileField("", max_length=260, upload_to=file_directory) guid = models.CharField(max_length=40) name = models.CharField(max_length=200, blank=True) description = models.TextField(blank=True) content_type = models.ForeignKey(ContentType, blank=True, null=True) object_id = models.IntegerField(blank=True, null=True) is_public = models.BooleanField(default=True) group = models.ForeignKey(Group, null=True, default=get_default_group, on_delete=models.SET_NULL) tags = TagField(null=True, blank=True) categories = generic.GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = generic.GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = FileManager() class Meta: permissions = (("view_file", "Can view file"), ) @models.permalink def get_absolute_url(self): return ("file", [self.pk]) @models.permalink def get_absolute_download_url(self): return ("file", [self.pk, 'download']) def __unicode__(self): return self.get_name() @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items def save(self, *args, **kwargs): if not self.id: self.guid = unicode(uuid.uuid1()) super(File, self).save(*args, **kwargs) if self.is_public_file(): set_s3_file_permission(self.file, public=True) else: set_s3_file_permission(self.file, public=False) cache_set = cache.get("files_cache_set.%s" % self.pk) if cache_set is not None: # TODO remove cached images cache.delete_many(cache.get("files_cache_set.%s" % self.pk)) cache.delete("files_cache_set.%s" % self.pk) def delete(self, *args, **kwargs): # Related objects # Import related objects here to prevent circular references from tendenci.apps.pages.models import Page from tendenci.addons.events.models import Event from tendenci.apps.stories.models import Story pages = Page.objects.filter(header_image=self.pk) events = Event.objects.filter(image=self.pk) stories = Story.objects.filter(image=self.pk) # Set foreign key of related objects to None for page in pages: page.header_image = None page.save() for event in events: event.image = None event.save() for story in stories: story.image = None story.save() # roll back the transaction to fix the error for postgresql #"current transaction is aborted, commands ignored until # end of transaction block" connection._rollback() # delete actual file; do not save() self.instance self.file.delete(save=False) # delete database record super(File, self).delete(*args, **kwargs) def basename(self): return os.path.basename(unicode(self.file.name)) def ext(self): return os.path.splitext(self.basename())[-1] def get_name(self): return self.name or os.path.splitext(self.basename())[0] def get_name_ext(self): return "%s%s" % (self.get_name(), self.ext()) def type(self): ext = self.ext().lower() # map file-type to extension types = { 'image': ('.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff', '.bmp'), 'text': ('.txt', '.doc', '.docx'), 'spreadsheet': ('.csv', '.xls', '.xlsx'), 'powerpoint': ('.ppt', '.pptx'), 'pdf': ('.pdf'), 'video': ('.wmv', '.mov', '.mpg', '.mp4', '.m4v'), 'zip': ('.zip'), } # if file ext. is recognized # return icon for type in types: if ext in types[type]: return type return None def mime_type(self): types = { # list of uncommon mimetypes 'application/msword': ('.doc', '.docx'), 'application/ms-powerpoint': ('.ppt', '.pptx'), 'application/ms-excel': ('.xls', '.xlsx'), 'video/x-ms-wmv': ('.wmv'), } # add mimetypes for type in types: for ext in types[type]: mimetypes.add_type(type, ext) # guess mimetype mimetype = mimetypes.guess_type(self.file.name)[0] return mimetype def icon(self): # if we don't know the type # we can't find an icon [to represent the file] if not self.type(): return None # assign icons directory icons_dir = os.path.join(settings.LOCAL_STATIC_URL, 'images/icons') # map file-type to image file icons = { 'text': 'icon-ms-word-2007.gif', 'spreadsheet': 'icon-ms-excel-2007.gif', 'powerpoint': 'icon-ms-powerpoint-2007.gif', 'image': 'icon-ms-image-2007.png', 'pdf': 'icon-pdf.png', 'video': 'icon-wmv.png', 'zip': 'icon-zip.gif', } # return image path return icons_dir + '/' + icons[self.type()] def get_file_from_remote_storage(self): return cStringIO.StringIO(default_storage.open(self.file.name).read()) def image_dimensions(self): try: if hasattr(settings, 'USE_S3_STORAGE') and settings.USE_S3_STORAGE: im = Image.open(self.get_file_from_remote_storage()) else: im = Image.open(self.file.path) return im.size except Exception: return (0, 0) def read(self): """Returns a file's text data For now this only considers pdf files. if the file cannot be read this will return an empty string. """ if not settings.USE_S3_STORAGE: if not os.path.exists(self.file.path): return unicode() if self.type() == 'pdf': try: doc = PDF(self.file.file) except: return unicode() return doc.text() return unicode() def is_public_file(self): return all([ self.is_public, self.allow_anonymous_view, self.status, self.status_detail.lower() == "active" ]) def get_file_public_url(self): if self.is_public_file(): if hasattr(settings, 'USE_S3_STORAGE') and settings.USE_S3_STORAGE: return self.file.url else: return "%s%s" % (settings.MEDIA_URL, self.file) return None
class PaymentMethodCriterion(models.Model, Criterion): """A criterion for the payment method. """ operator = models.PositiveIntegerField(_(u"Operator"), blank=True, null=True, choices=SELECT_OPERATORS) payment_methods = models.ManyToManyField(PaymentMethod, verbose_name=_(u"Payment methods")) criteria_objects = generic.GenericRelation(CriteriaObjects, object_id_field="criterion_id", content_type_field="criterion_type") def __unicode__(self): values = [] for value in self.value.all(): values.append(value.name) return "%s %s %s" % ("Payment", self.get_operator_display(), ", ".join(values)) @property def content_type(self): """Returns the content_type of the criterion as lower string. This is for instance used to select the appropriate form for the criterion. """ return u"payment_method" @property def name(self): """Returns the descriptive name of the criterion. """ return _(u"Payment method") def is_valid(self, request, product=None): """Returns True if the criterion is valid. """ # see ShippingMethodCriterion for what's going on here import lfs.shipping.utils content_object = self.criteria_objects.filter()[0].content if isinstance(content_object, PaymentMethod): is_payment_method = True else: is_payment_method = False if not is_payment_method and self.operator == IS: payment_method = lfs.payment.utils.get_selected_payment_method(request) return payment_method in self.payment_methods.all() elif not is_payment_method and self.operator == IS_NOT: payment_method = lfs.payment.utils.get_selected_payment_method(request) return payment_method not in self.payment_methods.all() elif self.operator == IS_VALID: for pm in self.payment_methods.all(): if not lfs.criteria.utils.is_valid(request, pm, product): return False return True elif self.operator == IS_NOT_VALID: for pm in self.payment_methods.all(): if lfs.criteria.utils.is_valid(request, pm, product): return False return True else: return False @property def value(self): """Returns the value of the criterion. """ return self.payment_methods def as_html(self, request, position): """Renders the criterion as html in order to be displayed within several forms. """ selected_payment_methods = self.payment_methods.all() payment_methods = [] for pm in PaymentMethod.objects.filter(active=True): if pm in selected_payment_methods: selected = True else: selected = False payment_methods.append({ "id": pm.id, "name": pm.name, "selected": selected, }) return render_to_string("manage/criteria/payment_method_criterion.html", RequestContext(request, { "id": "ex%s" % self.id, "operator": self.operator, "value": self.value, "position": position, "payment_methods": payment_methods, }))
class ForumSection(models.Model): link = models.CharField('Link', max_length=250) title = models.CharField('Title', max_length=250) threads = generic.GenericRelation(KongThread)
class Issue(models.Model): class Meta: app_label = 'gcd' ordering = ['series', 'sort_code'] unique_together = ('series', 'sort_code') # Issue identification number = models.CharField(max_length=50, db_index=True) title = models.CharField(max_length=255, db_index=True) no_title = models.BooleanField(default=False, db_index=True) volume = models.CharField(max_length=50, db_index=True) no_volume = models.BooleanField(default=False, db_index=True) display_volume_with_number = models.BooleanField(default=False, db_index=True) isbn = models.CharField(max_length=32, db_index=True) no_isbn = models.BooleanField(default=False, db_index=True) valid_isbn = models.CharField(max_length=13, db_index=True) variant_of = models.ForeignKey('self', null=True, related_name='variant_set') variant_name = models.CharField(max_length=255) barcode = models.CharField(max_length=38, db_index=True) no_barcode = models.BooleanField(default=False) # Dates and sorting publication_date = models.CharField(max_length=255) key_date = models.CharField(max_length=10, db_index=True) on_sale_date = models.CharField(max_length=10, db_index=True) on_sale_date_uncertain = models.BooleanField(blank=True) sort_code = models.IntegerField(db_index=True) indicia_frequency = models.CharField(max_length=255) no_indicia_frequency = models.BooleanField(default=False, db_index=True) # Price, page count and format fields price = models.CharField(max_length=255) page_count = models.DecimalField(max_digits=10, decimal_places=3, null=True) page_count_uncertain = models.BooleanField(default=False) editing = models.TextField() no_editing = models.BooleanField(default=False, db_index=True) notes = models.TextField() keywords = TaggableManager() # Series and publisher links series = models.ForeignKey(Series) indicia_publisher = models.ForeignKey(IndiciaPublisher, null=True) indicia_pub_not_printed = models.BooleanField(default=False) image_resources = generic.GenericRelation(Image) def _indicia_image(self): img = Image.objects.filter( object_id=self.id, deleted=False, content_type=ContentType.objects.get_for_model(self), type__id=1) if img: return img.get() else: return None indicia_image = property(_indicia_image) brand = models.ForeignKey(Brand, null=True) no_brand = models.BooleanField(default=False, db_index=True) def _soo_image(self): img = Image.objects.filter( object_id=self.id, deleted=False, content_type=ContentType.objects.get_for_model(self), type__id=2) if img: return img.get() else: return None soo_image = property(_soo_image) # In production, this is a tinyint(1) because the set of numbers # is very small. But syncdb produces an int(11). is_indexed = models.IntegerField(default=0, db_index=True) # Fields related to change management. reserved = models.BooleanField(default=False, db_index=True) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True, db_index=True) deleted = models.BooleanField(default=False, db_index=True) def active_stories(self): return self.story_set.exclude(deleted=True) def shown_stories(self): """ returns cover sequence and story sequences """ if self.variant_of: stories_from = self.variant_of else: stories_from = self stories = list(stories_from.active_stories().order_by( 'sequence_number').select_related('type', 'migration_status')) if self.series.is_comics_publication: if (len(stories) > 0): cover_story = stories.pop(0) if self.variant_of: # can have only one sequence, the variant cover if self.active_stories().count(): cover_story = self.active_stories()[0] elif self.variant_of and len(list(self.active_stories())): cover_story = self.active_stories()[0] else: cover_story = None else: cover_story = None return cover_story, stories def active_covers(self): return self.cover_set.exclude(deleted=True) def variant_covers(self): """ returns the images from the variant issues """ from cover import Cover if self.variant_of: variant_issues = list(self.variant_of.variant_set\ .exclude(id=self.id)\ .exclude(deleted=True)\ .values_list('id', flat=True)) else: variant_issues = list(self.variant_set.exclude(deleted=True)\ .values_list('id', flat=True)) variant_covers = Cover.objects.filter(issue__id__in=variant_issues)\ .exclude(deleted=True) if self.variant_of: variant_covers |= self.variant_of.active_covers() return variant_covers def shown_covers(self): return self.active_covers(), self.variant_covers() def has_covers(self): return self.series.is_comics_publication and \ self.active_covers().count() > 0 def other_variants(self): if self.variant_of: variants = self.variant_of.variant_set.exclude(id=self.id) else: variants = self.variant_set.all() return list(variants.exclude(deleted=True)) def _display_number(self): if self.title and self.series.has_issue_title: title = " - " + self.title else: title = "" if self.display_volume_with_number: return u'v%s#%s%s' % (self.volume, self.number, title) return self.number + title display_number = property(_display_number) # determine and set whether something has been indexed at all or not def set_indexed_status(self): from story import StoryType is_indexed = INDEXED['skeleton'] if self.page_count > 0: total_count = self.active_stories()\ .aggregate(Sum('page_count'))['page_count__sum'] if total_count > 0 and total_count >= Decimal( '0.4') * self.page_count: is_indexed = INDEXED['full'] if is_indexed != INDEXED['full'] and self.active_stories()\ .filter(type=StoryType.objects.get(name='comic story')).count() > 0: is_indexed = INDEXED['partial'] if self.is_indexed != is_indexed: self.is_indexed = is_indexed self.save() return self.is_indexed def index_status_name(self): """ Text form of status. If clauses arranged in order of most likely case to least. """ if self.reserved: active = self.revisions.get(changeset__state__in=states.ACTIVE) return states.CSS_NAME[active.changeset.state] elif self.is_indexed == INDEXED['full']: return 'approved' elif self.is_indexed == INDEXED['partial']: return 'partial' else: return 'available' def get_prev_next_issue(self): """ Find the issues immediately before and after the given issue. """ prev_issue = None next_issue = None earlier_issues = self.series.active_base_issues()\ .filter(sort_code__lt=self.sort_code) earlier_issues = earlier_issues.order_by('-sort_code') if earlier_issues: prev_issue = earlier_issues[0] later_issues = self.series.active_base_issues()\ .filter(sort_code__gt=self.sort_code) later_issues = later_issues.order_by('sort_code') if later_issues: next_issue = later_issues[0] return [prev_issue, next_issue] def delete(self): self.deleted = True self.reserved = False self.save() def has_reprints(self): from story import STORY_TYPES """Simplifies UI checks for conditionals. notes and reprint fields""" return self.from_reprints.count() or \ self.to_reprints.exclude(target__type__id=STORY_TYPES['promo']).count() or \ self.from_issue_reprints.count() or \ self.to_issue_reprints.count() def deletable(self): if self.cover_revisions.filter(changeset__state__in=states.ACTIVE)\ .count() > 0: return False if self.variant_set.filter(deleted=False).count() > 0: return False if self.has_reprints(): return False for story in self.active_stories(): if story.has_reprints(notes=False): return False return True def can_upload_variants(self): if self.has_covers(): return self.revisions.filter(changeset__state__in=states.ACTIVE, deleted=True).count() == 0 else: return False def get_absolute_url(self): return urlresolvers.reverse('show_issue', kwargs={'issue_id': self.id}) def full_name(self, variant_name=True): if variant_name and self.variant_name: return u'%s #%s [%s]' % (self.series.full_name(), self.display_number, self.variant_name) else: return u'%s #%s' % (self.series.full_name(), self.display_number) def short_name(self): if self.variant_name: return u'%s #%s [%s]' % (self.series.name, self.display_number, self.variant_name) else: return u'%s #%s' % (self.series.name, self.display_number) def __unicode__(self): if self.variant_name: return u'%s #%s [%s]' % (self.series, self.display_number, self.variant_name) else: return u'%s #%s' % (self.series, self.display_number)
class ForumSubSection(models.Model): forum_section = models.ForeignKey(ForumSection) link = models.CharField('Link', max_length=250) title = models.CharField('Title', max_length=250) threads = generic.GenericRelation(KongThread)
class Discount(models.Model): """A discount which is given to the customer if several criteria fullfilled. **Attributes:** name The name of the discount. This can be displayed to the customer. value The value of the discount, can be absolute or percentage dependend on the type of the discount. type The type of the discount. Absolute or percentage. tax The included tax within the discount. sku The SKU of the discount. criteria_objects Criteria which must all valid to make the discount happen. """ name = models.CharField(_(u"Name"), max_length=100) value = models.FloatField(_(u"Value")) type = models.PositiveSmallIntegerField(_(u"Type"), choices=DISCOUNT_TYPE_CHOICES, default=DISCOUNT_TYPE_ABSOLUTE) tax = models.ForeignKey(Tax, verbose_name=_(u"Tax"), blank=True, null=True) sku = models.CharField(_(u"SKU"), blank=True, max_length=50) criteria_objects = generic.GenericRelation(CriteriaObjects, object_id_field="content_id", content_type_field="content_type") def __unicode__(self): return self.name def is_valid(self, request, product=None): """The shipping method is valid if it has no criteria or if all assigned criteria are true. If product is given the product is tested otherwise the whole cart. """ return lfs.criteria.utils.is_valid(request, self, product) def get_tax(self, request, product=None): """Returns the absolute tax of the voucher. """ price_gross = self.get_price_gross(request, product) if self.tax: return price_gross * (self.tax.rate / (100 + self.tax.rate)) else: if self.type == DISCOUNT_TYPE_ABSOLUTE: return 0.0 else: cart = lfs.cart.utils.get_cart(request) return cart.get_tax(request) * (self.value / 100) def get_price_net(self, request, product=None): """Returns the net price of the discount. """ return self.get_price_gross(request, product) - self.get_tax(request, product) def get_price_gross(self, request, product=None): """Returns the gross price of the discount. """ if self.type == DISCOUNT_TYPE_ABSOLUTE: return self.value cart = lfs.cart.utils.get_cart(request) if cart is not None: return cart.get_price_gross(request) * (self.value / 100) elif product is not None: return product.get_price_gross(request) * (self.value / 100) return 0.0
class HasLinks(models.Model): links = generic.GenericRelation(Link) class Meta: abstract = True
site_id=settings.SITE_ID) c.save() return c class TestCaseEmailSettings(models.Model): case = models.OneToOneField(TestCase, related_name='email_settings') notify_on_case_update = models.BooleanField(default=False) notify_on_case_delete = models.BooleanField(default=False) auto_to_case_author = models.BooleanField(default=False) auto_to_case_tester = models.BooleanField(default=False) auto_to_run_manager = models.BooleanField(default=False) auto_to_run_tester = models.BooleanField(default=False) auto_to_case_run_assignee = models.BooleanField(default=False) cc_list = generic.GenericRelation(Contact, object_id_field='object_pk') class Meta: pass def add_cc(self, email_addrs): '''Add email addresses to CC list Arguments: - email_addrs: str or list, holding one or more email addresses ''' emailaddr_list = [] if not isinstance(email_addrs, list): emailaddr_list.append(email_addrs) else:
class B(models.Model): a = generic.GenericRelation(A) class Meta: ordering = ('id', )
class Page(ModelBase): """Placeholder model for pages.""" object_type = object_types['article'] title = models.CharField(max_length=100) slug = models.SlugField(max_length=110) sub_header = models.CharField(max_length=150, blank=True, null=True) content = RichTextField(config_name='rich', blank='False') author = models.ForeignKey('users.UserProfile', related_name='pages') last_update = models.DateTimeField(auto_now_add=True, default=datetime.datetime.now) project = models.ForeignKey('projects.Project', related_name='pages') listed = models.BooleanField(default=True) minor_update = models.BooleanField(default=True) collaborative = models.BooleanField(default=True) index = models.IntegerField() deleted = models.BooleanField(default=False) comments = generic.GenericRelation(PageComment, content_type_field='page_content_type', object_id_field='page_id') # Badges to which the user can submit their work to. # Used to facilitate both posting a comment to the task with # a link to the work they did on the task and apply for skills badges badges_to_apply = models.ManyToManyField( 'badges.Badge', null=True, blank=False, related_name='tasks_accepting_submissions') def __unicode__(self): return self.title @models.permalink def get_absolute_url(self): return ('page_show', (), { 'slug': self.project.slug, 'page_slug': self.slug, }) def friendly_verb(self, verb): if verbs['post'] == verb: return _('added') def save(self): """Make sure each page has a unique url.""" count = 1 if not self.slug: slug = slugify(self.title) self.slug = slug while True: existing = Page.objects.filter(project__slug=self.project.slug, slug=self.slug) if len(existing) == 0: break self.slug = "%s-%s" % (slug, count + 1) count += 1 if not self.index: if self.listed: max_index = Page.objects.filter(project=self.project, listed=True).aggregate( Max('index'))['index__max'] self.index = max_index + 1 if max_index else 1 else: self.index = 0 super(Page, self).save() def get_next_page(self): if self.listed and not self.deleted: try: return self.project.pages.filter(deleted=False, index__gt=self.index, listed=True)[0] except IndexError: pass return None def get_next_badge_can_apply(self, profile): next_badges = self.badges_to_apply.order_by('id') next_badges_can_apply = [] for badge in next_badges: awarded = Award.objects.filter(user=profile, badge=badge).exists() applied = Submission.objects.filter(author=profile, badge=badge).exists() elegible = badge.is_eligible(profile.user) if not awarded and not applied and elegible: next_badges_can_apply.append(badge) if len(next_badges_can_apply) > 1: break next_badge = next_badges_can_apply[0] if next_badges_can_apply else None is_last_badge = not next_badges_can_apply[1:] return next_badge, is_last_badge def can_edit(self, user): if self.project.is_organizing(user): return True if self.collaborative: return self.project.is_participating(user) return False def first_level_comments(self): return self.comments.filter( reply_to__isnull=True).order_by('-created_on') def can_comment(self, user, reply_to=None): return self.project.is_participating(user) def get_comment_url(self, comment, user): comment_index = 0 abs_reply_to = comment.abs_reply_to or comment for first_level_comment in self.first_level_comments(): if abs_reply_to.id == first_level_comment.id: break comment_index += 1 items_per_page = settings.PAGINATION_DEFAULT_ITEMS_PER_PAGE page = (comment_index / items_per_page) + 1 url = self.get_absolute_url() return url + '?pagination_page_number=%s#%s' % (page, comment.id) def comments_fire_activity(self): return True def comment_notification_recipients(self, comment): from users.models import UserProfile participants = self.project.participants() from_organizer = self.project.organizers().filter( user=comment.author).exists() if from_organizer: participants = participants.filter( no_organizers_content_updates=False) else: participants = participants.filter( no_participants_content_updates=False) return UserProfile.objects.filter( id__in=participants.values('user__id')) def recent_activity(self, min_count=2): comments = self.comments.filter(deleted=False) today = datetime.date.today() day = today.day month = today.month year = today.year # get today's commments count today_comments_count = comments.filter(created_on__day=day, created_on__month=month, created_on__year=year).count() if today_comments_count >= min_count: return today_comments_count, _('today') # get this week comments count week = today.isocalendar()[1] first_day = datetime.date(year, 1, 1) delta_days = first_day.isoweekday() - 1 delta_weeks = week if year == first_day.isocalendar()[0]: delta_weeks -= 1 week_start_delta = datetime.timedelta(days=-delta_days, weeks=delta_weeks) week_start = first_day + week_start_delta week_end_delta = datetime.timedelta(days=7 - delta_days, weeks=delta_weeks) week_end = first_day + week_end_delta this_week_comments_count = comments.filter( created_on__gte=week_start, created_on__lt=week_end).count() if this_week_comments_count >= min_count: return this_week_comments_count, _('this week') # get this month comments count this_month_comments_count = comments.filter( created_on__month=month, created_on__year=year).count() return this_month_comments_count, _('this month')
class UserProfile(models.Model): ''' ''' user = models.OneToOneField(User) username = models.CharField(max_length=30) columns = generic.GenericRelation(Column) username_change_time = models.DateTimeField(blank=True, null=True) avatar = models.ForeignKey(Avatar, blank=True, null=True) avatar_change_time = models.DateTimeField(blank=True, null=True) name = models.CharField(max_length=NAME_MAX_LEN, blank=True) name_change_time = models.DateTimeField(blank=True, null=True) website = models.URLField(blank=True) signature = models.CharField(max_length=SIGNATURE_MAX_LEN, blank=True) detail = models.TextField(blank=True) def get_name(self): if self.name: return self.name else: return self.username def __unicode__(self): return self.get_name() def is_can_change_name(self): if not self.name_change_time: return True can_change_days = timedelta(days=PROFILE_NAME_CHANGE_DAYS) can_change_time = self.name_change_time + can_change_days if now() > can_change_time: return True else: return False def change_name(self, name): if self.is_can_change_name() and name: self.name = name self.name_change_time = now() self.save() return True else: return False def detail_change(self, data): if self.signature != data['signature']: self.signature = data['signature'] if self.detail != data['detail']: self.detail = data['detail'] self.save() return True def get_absolute_url(self): return '/people/' + self.username + '/' def get_column(self): try: return self.columns.all()[0] except: return create_column(self)