Пример #1
0
    def test_cached_as(self):
        counts = {'a': 0}
        def inc_a():
            counts['a'] += 1
            return ''

        qs = Post.objects.all()

        t = Template("""
            {% load cacheops %}
            {% cached_as qs 0 'a' %}.a{{ a }}{% endcached_as %}
            {% cached_as qs timeout=60 fragment_name='a' %}.a{{ a }}{% endcached_as %}
            {% cached_as qs fragment_name='a' timeout=60 %}.a{{ a }}{% endcached_as %}
        """)

        s = t.render(Context({'a': inc_a, 'qs': qs}))
        self.assertEqual(re.sub(r'\s+', '', s), '.a.a.a')
        self.assertEqual(counts['a'], 1)

        t.render(Context({'a': inc_a, 'qs': qs}))
        self.assertEqual(counts['a'], 1)

        invalidate_model(Post)
        t.render(Context({'a': inc_a, 'qs': qs}))
        self.assertEqual(counts['a'], 2)
Пример #2
0
    def test_cached_as(self):
        counts = {"a": 0}

        def inc_a():
            counts["a"] += 1
            return ""

        qs = Post.objects.all()

        t = Template(
            """
            {% load cacheops %}
            {% cached_as qs 0 'a' %}.a{{ a }}{% endcached_as %}
            {% cached_as qs timeout=60 fragment_name='a' %}.a{{ a }}{% endcached_as %}
            {% cached_as qs fragment_name='a' timeout=60 %}.a{{ a }}{% endcached_as %}
        """
        )

        s = t.render(Context({"a": inc_a, "qs": qs}))
        self.assertEqual(re.sub(r"\s+", "", s), ".a.a.a")
        self.assertEqual(counts["a"], 1)

        t.render(Context({"a": inc_a, "qs": qs}))
        self.assertEqual(counts["a"], 1)

        invalidate_model(Post)
        t.render(Context({"a": inc_a, "qs": qs}))
        self.assertEqual(counts["a"], 2)
def clear_cache(objects=None, models=None, purge=False):
    # this is required to refresh the templates content
    # otherwise after any update the page will not refresh properly
    try:
        cache.clear()
    except Exception as e:
        # ignore errors
        logger.error(str(e))

    if _is_cacheops_enabled():
        from cacheops import invalidate_all, invalidate_model, invalidate_obj

        if objects:
            for obj in objects:
                invalidate_obj(obj)

        if models:
            for model in models:
                get_content_type(model=model)  # add it to the models list
                invalidate_model(model)

        if purge:
            try:
                invalidate_all()
            except Exception as e:
                # Fixes: unknown command `FLUSHDB`
                #   In helm charts FLUSHDB and FLUSHALL commands are disabled
                logger.error(str(e))
                clear_cache(models=list(CONTENT_TYPE_CACHE.keys()))
Пример #4
0
    def test_cached_as(self):
        counts = {'a': 0}

        def inc_a():
            counts['a'] += 1
            return ''

        qs = Post.objects.all()

        t = Template("""
            {% load cacheops %}
            {% cached_as qs 0 'a' %}.a{{ a }}{% endcached_as %}
            {% cached_as qs timeout=60 fragment_name='a' %}.a{{ a }}{% endcached_as %}
            {% cached_as qs fragment_name='a' timeout=60 %}.a{{ a }}{% endcached_as %}
        """)

        s = t.render(Context({'a': inc_a, 'qs': qs}))
        self.assertEqual(re.sub(r'\s+', '', s), '.a.a.a')
        self.assertEqual(counts['a'], 1)

        t.render(Context({'a': inc_a, 'qs': qs}))
        self.assertEqual(counts['a'], 1)

        invalidate_model(Post)
        t.render(Context({'a': inc_a, 'qs': qs}))
        self.assertEqual(counts['a'], 2)
 def on_commit(items, init_flag):
     if init_flag:
         invalidate_model(BayesDictionary)
     else:
         # у запроса aggregate также сбросится кэш при сбрасывании кэша одной записи
         for instance in items:
             invalidate_obj(instance)
Пример #6
0
 def post(self,request,  *args, **kwargs):
     
     # check name is free
     
     if Node.objects.filter(parent=request.POST.get('parent'), name=request.POST.get('name')).count() > 0:
         return HttpResponse("This name already exists", status=400)
     
     node = Node(parent_id=request.POST.get('parent'), name=request.POST.get('name'))
     node.save()
     
     if use_cacheops:
         print 'invalidate'
         invalidate_model(Node)
         node = Node.objects.get(pk=node.pk)
         
     
     return HttpResponse(simplejson.dumps({
                 'name' : node.name,
                 'icon' : 'default',
                 'loaded' : True,
                 'pk' : node.pk,
                 'position' : list(node.parent.get_children()).index(node),
                 'children' : [],
                 'parent' : node.parent.pk if node.parent is not None else None
             }), content_type="application/json", status=201)
Пример #7
0
def edit_block_view(request, block_id):
    try:
        block = EighthBlock.objects.get(id=block_id)
    except EighthBlock.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        form = BlockForm(request.POST, instance=block)
        if form.is_valid():
            form.save()
            invalidate_model(EighthBlock)
            messages.success(request, "Successfully edited block.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
    else:
        form = BlockForm(instance=block)

    context = {
        "form": form,
        "delete_url": reverse("eighth_admin_delete_block",
                              args=[block_id]),
        "admin_page_title": "Edit Block"
    }
    return render(request, "eighth/admin/edit_form.html", context)
Пример #8
0
def edit_block_view(request, block_id):
    try:
        block = EighthBlock.objects.get(id=block_id)
    except EighthBlock.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        form = BlockForm(request.POST, instance=block)
        if form.is_valid():
            form.save()
            invalidate_model(EighthBlock)
            messages.success(request, "Successfully edited block.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
    else:
        form = BlockForm(instance=block)

    context = {
        "form": form,
        "delete_url": reverse("eighth_admin_delete_block", args=[block_id]),
        "admin_page_title": "Edit Block",
        "block_id": block_id,
    }
    return render(request, "eighth/admin/edit_form.html", context)
Пример #9
0
def edit_block_view(request, block_id):
    try:
        block = EighthBlock.objects.get(id=block_id)
    except EighthBlock.DoesNotExist as e:
        raise http.Http404 from e

    if request.method == "POST":
        form = BlockForm(request.POST, instance=block)
        if form.is_valid():
            form.save()
            invalidate_model(EighthBlock)
            messages.success(request, "Successfully edited block.")
            #######
            if settings.ENABLE_HYBRID_EIGHTH:
                messages.warning(
                    request,
                    """Changing the block name here did not change the groups that were assigned to it.
                     If you need to do this, please delete this block and create the correct one.""",
                )
            #######
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
    else:
        form = BlockForm(instance=block)

    context = {
        "form": form,
        "delete_url": reverse("eighth_admin_delete_block", args=[block_id]),
        "admin_page_title": "Edit Block",
        "block_id": block_id,
    }
    return render(request, "eighth/admin/edit_form.html", context)
Пример #10
0
    def test_invalidation_signal(self):
        def set_signal(signal=None, **kwargs):
            signal_calls.append(kwargs)

        signal_calls = []
        cache_invalidated.connect(set_signal, dispatch_uid=1, weak=False)

        invalidate_all()
        invalidate_model(Post)
        c = Category.objects.create(title='Hey')
        self.assertEqual(signal_calls, [
            {
                'sender': None,
                'obj_dict': None
            },
            {
                'sender': Post,
                'obj_dict': None
            },
            {
                'sender': Category,
                'obj_dict': {
                    'id': c.pk,
                    'title': 'Hey'
                }
            },
        ])
Пример #11
0
    def handle(self, *args, **options):

        models = self._get_models(args)

        if options['verbosity']:
            self.stdout.write(f"Renaturalizing {len(models)} models.")

        for model, fields in models:
            for field in fields:
                target_field = field.target_field
                naturalize = field.naturalize_function
                count = 0

                # Print the model and field name
                if options['verbosity']:
                    self.stdout.write(
                        f"{model._meta.label}.{field.target_field} ({field.name})... ",
                        ending='\n' if options['verbosity'] >= 2 else '')
                    self.stdout.flush()

                # Find all unique values for the field
                queryset = model.objects.values_list(
                    target_field, flat=True).order_by(target_field).distinct()
                for value in queryset:
                    naturalized_value = naturalize(value,
                                                   max_length=field.max_length)

                    if options['verbosity'] >= 2:
                        self.stdout.write(f"  {value} -> {naturalized_value}",
                                          ending='')
                        self.stdout.flush()

                    # Update each unique field value in bulk
                    changed = model.objects.filter(name=value).update(
                        **{field.name: naturalized_value})

                    if options['verbosity'] >= 2:
                        self.stdout.write(f" ({changed})")
                    count += changed

                # Print the total count of alterations for the field
                if options['verbosity'] >= 2:
                    self.stdout.write(
                        self.style.SUCCESS(
                            f"{count} {model._meta.verbose_name_plural} updated ({queryset.count()} unique values)"
                        ))
                elif options['verbosity']:
                    self.stdout.write(self.style.SUCCESS(str(count)))

            # Invalidate cached queries
            invalidate_model(model)

        if options['verbosity']:
            self.stdout.write(self.style.SUCCESS("Done."))
Пример #12
0
 def update(self, **kwargs):
     # TODO: not sure whether should invalidate first or update first
     # from cacheops import invalidate_obj
     # for obj in self.iterator():
     #    invalidate_obj(obj)
     # update must behind invalidate obj
     n = super(CacheableQuerySet, self).update(**kwargs)
     if self.is_cacheable():
         from cacheops import invalidate_model
         invalidate_model(self.model)
     return n
Пример #13
0
 def set_read(self, user, filter):
     """
     Set messages as read.
     """
     qs = self.filter(
         filter,
         recipient=user,
         moderation_status=STATUS_ACCEPTED,
         read_at__isnull=True,
     ).update(read_at=now())
     invalidate_model(Message)
     return qs
Пример #14
0
 def set_read(self, user, filter):
     """
     Set messages as read.
     """
     qs = self.filter(
         filter,
         recipient=user,
         moderation_status=STATUS_ACCEPTED,
         read_at__isnull=True,
     ).update(read_at=now())
     invalidate_model(Message)
     return qs
Пример #15
0
 def put(self,request,  *args, **kwargs):
     
     node = self.get_object()
     
     if Node.objects.filter(name=request.PUT.get('name'), parent=node.parent).exclude(pk=node.pk).count() > 0:
         return HttpResponse("This name already exists", status=400)
     
     node.name = request.POST.get('name')
     node.save()
     
     if use_cacheops:
         invalidate_model(Node)
     
     return HttpResponse('')
Пример #16
0
 def trash(self, user, **kwargs):
     """
     Return messages belonging to a user and marked as deleted.
     """
     related = ('sender', 'recipient')
     filters = ({
         'recipient': user,
         'recipient_deleted_at__isnull': False,
         'moderation_status': STATUS_ACCEPTED,
     }, {
         'sender': user,
         'sender_deleted_at__isnull': False,
     })
     invalidate_model(Message)
     return self._folder(related, filters, **kwargs)
Пример #17
0
 def trash(self, user, **kwargs):
     """
     Return messages belonging to a user and marked as deleted.
     """
     related = ('sender', 'recipient')
     filters = ({
         'recipient': user,
         'recipient_deleted_at__isnull': False,
         'moderation_status': STATUS_ACCEPTED,
     }, {
         'sender': user,
         'sender_deleted_at__isnull': False,
     })
     invalidate_model(Message)
     return self._folder(related, filters, **kwargs)
Пример #18
0
    def test_invalidation_signal(self):
        def set_signal(signal=None, **kwargs):
            signal_calls.append(kwargs)

        signal_calls = []
        cache_invalidated.connect(set_signal, dispatch_uid=1, weak=False)

        invalidate_all()
        invalidate_model(Post)
        c = Category.objects.create(title='Hey')
        self.assertEqual(signal_calls, [
            {'sender': None, 'obj_dict': None},
            {'sender': Post, 'obj_dict': None},
            {'sender': Category, 'obj_dict': {'id': c.pk, 'title': 'Hey'}},
        ])
Пример #19
0
    def add_child(self, **kwargs):
        r"""
        Adds a child to the node

        :param \**kwargs: The supplied keyword arguments
        :type \**kwargs: dict

        :return: The new child
        :rtype: ~integreat_cms.cms.models.abstract_tree_node.AbstractTreeNode
        """
        # Adding a child can modify all other nodes via raw sql queries (which are not recognized by cachalot),
        # so we have to invalidate the whole model manually.
        invalidate_model(self.__class__)
        child = super().add_child(**kwargs)
        invalidate_model(self.__class__)
        return child
Пример #20
0
class Command(LabelCommand):
    help = 'Invalidates cache for entire app, model or particular instance'
    args = '(all | <app> | <app>.<model> | <app>.<model>.<pk>) +'
    label = 'app or model or object'

    def handle_label(self, label, pk=None, **options):
        if label == 'all':
            self.handle_all()
        else:
            app_n_model = label.split('.')
            if len(app_n_model) == 1:
                self.handle_app(app_n_model[0])
            elif len(app_n_model) == 2:
                self.handle_model(*app_n_model)
            elif len(app_n_model) == 3:
                self.handle_obj(*app_n_model)
            else:
                raise CommandError(
                    'Wrong model/app name syntax: %s\nType <app_name> or <app_name>.<model_name>'
                    % label)

    def handle_all(self):
        redis_conn.flushdb()

    def handle_app(self, app_name):
        try:
            app = get_app(app_name)
        except ImproperlyConfigured, e:
            raise CommandError(e)

        for model in get_models(app, include_auto_created=True):
            invalidate_model(model)
Пример #21
0
    def clear_local_database(self):
        """
        Deletes all data related to the local database. This can be used to get a
        fresh start.
        """
        # Unlink main objects from PeeringDB's before emptying the local database
        Connection.objects.filter(peeringdb_netixlan__isnull=False).update(
            peeringdb_netixlan=None)
        IXP.objects.filter(peeringdb_ixlan__isnull=False).update(
            peeringdb_ixlan=None)

        # The use of reversed is important to avoid fk issues
        for model in reversed(list(NAMESPACES.values())):
            model.objects.all()._raw_delete(using=DEFAULT_DB_ALIAS)
            invalidate_model(model)
        Synchronization.objects.all()._raw_delete(using=DEFAULT_DB_ALIAS)
        invalidate_model(Synchronization)
Пример #22
0
def delete_block_view(request, block_id):
    try:
        block = EighthBlock.objects.get(id=block_id)
    except EighthBlock.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        block.delete()
        invalidate_model(EighthBlock)
        messages.success(request, "Successfully deleted block.")
        return redirect("eighth_admin_dashboard")
    else:
        context = {"admin_page_title": "Delete Block",
                   "item_name": str(block),
                   "help_text": "Deleting this block will remove all records "
                                "of it related to eighth period."}

        return render(request, "eighth/admin/delete_form.html", context)
Пример #23
0
    def test_cached_as(self):
        inc = make_inc()
        qs = Post.objects.all()
        t = Template("""
            {% load cacheops %}
            {% cached_as qs None 'a' %}.{{ inc }}{% endcached_as %}
            {% cached_as qs timeout=60 fragment_name='a' %}.{{ inc }}{% endcached_as %}
            {% cached_as qs fragment_name='a' timeout=60 %}.{{ inc }}{% endcached_as %}
        """)

        # All the forms are equivalent
        self.assertRendersTo(t, {'inc': inc, 'qs': qs}, '.1.1.1')

        # Cache works across calls
        self.assertRendersTo(t, {'inc': inc, 'qs': qs}, '.1.1.1')

        # Post invalidation clears cache
        invalidate_model(Post)
        self.assertRendersTo(t, {'inc': inc, 'qs': qs}, '.2.2.2')
Пример #24
0
    def add_sibling(self, pos=None, **kwargs):
        r"""
        Adds a new node as a sibling to the current node object

        :param pos: The position of the new sibling
        :type pos: str

        :param \**kwargs: The supplied keyword arguments
        :type \**kwargs: dict

        :return: The new sibling
        :rtype: ~integreat_cms.cms.models.abstract_tree_node.AbstractTreeNode
        """
        # Adding a sibling can modify all other nodes via raw sql queries (which are not recognized by cachalot),
        # so we have to invalidate the whole model manually.
        invalidate_model(self.__class__)
        sibling = super().add_sibling(pos=pos, **kwargs)
        invalidate_model(self.__class__)
        return sibling
Пример #25
0
def delete_block_view(request, block_id):
    try:
        block = EighthBlock.objects.get(id=block_id)
    except EighthBlock.DoesNotExist as e:
        raise http.Http404 from e

    if request.method == "POST":
        block.delete()
        invalidate_model(EighthBlock)
        messages.success(request, "Successfully deleted block.")
        return redirect("eighth_admin_dashboard")
    else:
        context = {
            "admin_page_title": "Delete Block",
            "item_name": str(block),
            "help_text": "Deleting this block will remove all records " "of it related to eighth period.",
        }

        return render(request, "eighth/admin/delete_form.html", context)
Пример #26
0
    def test_cached_as(self):
        inc = _make_inc()
        qs = Post.objects.all()
        t = Template("""
            {% load cacheops %}
            {% cached_as qs 0 'a' %}.{{ inc }}{% endcached_as %}
            {% cached_as qs timeout=60 fragment_name='a' %}.{{ inc }}{% endcached_as %}
            {% cached_as qs fragment_name='a' timeout=60 %}.{{ inc }}{% endcached_as %}
        """)

        # All the forms are equivalent
        self.assertRendersTo(t, {'inc': inc, 'qs': qs}, '.1.1.1')

        # Cache works across calls
        self.assertRendersTo(t, {'inc': inc, 'qs': qs}, '.1.1.1')

        # Post invalidation clears cache
        invalidate_model(Post)
        self.assertRendersTo(t, {'inc': inc, 'qs': qs}, '.2.2.2')
Пример #27
0
    def add_items(self, item_model, items):
        """Adds items in bulk to the index. If we're adding stuff through the `update_index`
        management command, we'll receive these in chunks of 1000.

        We're then splitting those chunks into smaller chunks of 100, I think that helps
        not overload stuff, but it would be good TODO tests to verify this.

        Args:
            item_model (db.Model): The model class we're indexing
            items (list): A list containing a bunch of items to index.

        Returns:
            bool: True
        """
        prepared = []

        # Ensure we're not indexing something stale from the cache
        # This also stops redis from overloading during the indexing
        if USING_CACHEOPS is True:
            try:
                invalidate_model(item_model)
            except Exception:
                pass

        # split items into chunks of 100
        chunks = [items[x:x + 100] for x in range(0, len(items), 100)]

        for chunk in chunks:
            if self.update_strategy == 'delta':
                chunk = self._check_deltas(chunk)
            prepared = []
            for item in chunk:
                doc = self._create_document(self.model, item)
                prepared.append(doc)

            if self.update_strategy == 'soft' or self.update_strategy == 'delta':
                self.index.update_documents(prepared)
            else:
                self.index.add_documents(prepared)
            del (chunk)

        return True
Пример #28
0
def cisco_eox_populate_product_lc_state_sync_field():
    """
    Periodic job to populate the lc_state_sync field in the Products, which shows that the product lifecycle data are
    automatically synchronized against the Cisco EoX API in this case
    :return:
    """
    try:
        cis_vendor = Vendor.objects.get(name__istartswith="Cisco")

    except:
        # Vendor doesn't exist, no steps required
        logger.fatal("Vendor \"Cisco Systems\" not found in database, please check your installation")
        return {"error": "Vendor \"Cisco Systems\" not found in database"}

    cisco_products = Product.objects.filter(vendor=cis_vendor)

    if cisco_products.count() != 0:
        app_config = AppSettings()
        queries = app_config.get_cisco_eox_api_queries_as_list()

        # escape the query strings
        queries = [re.escape(e) for e in queries]

        # convert the wildcard values
        queries = [e.replace("\\*", ".*") for e in queries]
        queries = ["^" + e + "$" for e in queries]

        with transaction.atomic():
            # reset all entries for the vendor
            Product.objects.filter(vendor=cis_vendor).update(lc_state_sync=False)

            # only set the state sync to true if the periodic synchronization is enabled
            if app_config.is_periodic_sync_enabled():
                for query in queries:
                    Product.objects.filter(product_id__regex=query, vendor=cis_vendor).update(lc_state_sync=True)

        invalidate_model(Product)

        return {"status": "Database updated"}

    else:
        return {"error": "No Products associated to \"Cisco Systems\" found in database"}
Пример #29
0
    def move(self, target, pos=None):
        """
        Moves the current node and all it's descendants to a new position
        relative to another node.

        :param target: The target mode which determines the new position
        :type target: ~integreat_cms.cms.models.abstract_tree_node.AbstractTreeNode

        :param pos: The new position of the page relative to the target
                    (choices: :mod:`~integreat_cms.cms.constants.position`)
        :type pos: str

        :raises ~treebeard.exceptions.InvalidPosition: If the node is moved to another region
        """
        logger.debug("Moving %r to position %r of %r", self, pos, target)
        # Do not allow to move a node outside its region
        if self.region != target.region:
            # Allow moving as siblings of root nodes (because it's a separate tree)
            if not (target.is_root() and pos in [
                    position.LEFT,
                    position.RIGHT,
                    position.FIRST_SIBLING,
                    position.LAST_SIBLING,
            ]):
                raise InvalidPosition(
                    _('The node "{}" in region "{}" cannot be moved to "{}".').
                    format(self, self.region, target.region))
        # Moving a node can modify all other nodes via raw sql queries (which are not recognized by cachalot),
        # so we have to invalidate the whole model manually.
        invalidate_model(self.__class__)
        super().move(target=target, pos=pos)
        invalidate_model(self.__class__)

        # Reload 'self' because lft/rgt may have changed
        self.refresh_from_db()
        # Update parent to fix inconsistencies between tree fields
        new_parent = self.get_parent(update=True)
        logger.debug("Updating parent field from %r to %r", self.parent,
                     new_parent)
        self.parent = new_parent
        self.save()
Пример #30
0
 def post(self,request, *args, **kwargs):
     
     
     target = Node.objects.get(pk=request.DATA.get('target'));
     node = Node.objects.get(pk=request.DATA.get('node'))
     count = target.children.filter(models.Q(name=node.name) | models.Q(name__regex=r'^%s \([0-9]+\)$' % node.name)).count()
     if count > 0:
         
         q = target.children.filter(name__regex=r'^%s \([0-9]+\)$' % node.name)
         if q.count() > 0:
             name = q.order_by('-name')[0].name
             count = int(re.match('.* \(([0-9+])\)', name).group(1))
         
         node.name = node.name + " (%s)" % (count + 1)
         node.save() # mptt sucks
     
     node.parent = target
     node.save()
     
     if use_cacheops:
         invalidate_model(Node)
     
     return HttpResponse(simplejson.dumps({'name' : node.name, 'position' : list(Node.objects.get(pk=request.DATA.get('target')).get_children()).index(node)}), content_type="application/json")
Пример #31
0
 def handle_model(self, app_name, model_name):
     model = get_model(app_name, model_name)
     if model is None:
         raise CommandError('Unknown model: %s.%s' % (app_name, model_name))
     invalidate_model(model)
Пример #32
0
def repair_durations(limit_range, dump_to, load_from, tolerance, log_file):
    """
    Repair/reprocess master durations.
    """
    from base.audio.fileinfo import FileInfoProcessor

    items_to_reprocess = []
    affected_playlists = []
    affected_playlist_ids = []

    # invalidate cache for Media
    invalidate_model(Media)

    if load_from:

        if limit_range:
            raise NotImplementedError(
                '--limit-range option not allowed in combination with --load-from'
            )

        # using `set` to remove duplicate ids
        item_ids = set([
            int(l.strip().split(',')[0]) for l in load_from.readlines()
            if float(l.strip().split(',')[1]) > tolerance
        ])

        click.echo('loaded {} ids from dump file'.format(len(item_ids)))

        items_to_reprocess = Media.objects.filter(pk__in=item_ids)

    else:

        # mysql does not support remote/streaming cursors
        # to save memory items are loaded from db individually
        values = Media.objects.order_by('pk').values('id').nocache()

        if limit_range:
            _limits = limit_range.split(':')
            values = values[_limits[0]:_limits[1]]

        item_ids = [i['id'] for i in values]

        with click.progressbar(item_ids,
                               show_pos=True,
                               width=48,
                               label='Reprocessing {} tracks'.format(
                                   len(item_ids))) as bar:

            for item_pk in bar:

                close_old_connections()

                item = Media.objects.get(pk=item_pk)

                if item.master and item.master.path:

                    p = FileInfoProcessor(item.master.path)

                    current_duration = item.master_duration
                    new_duration = p.duration

                    try:
                        diff = abs(current_duration - new_duration)
                    except TypeError:
                        diff = 100.0

                    if diff > tolerance:
                        items_to_reprocess.append(item)

                    # add to csv log
                    if diff > tolerance and dump_to:
                        dump_to.write('{pk},{diff}\n'.format(pk=item.pk,
                                                             diff=diff))
                        dump_to.flush()

    click.echo('{} tracks have differences in duration'.format(
        len(items_to_reprocess)))

    if click.confirm(
            'Do you want to update/repair the durations on {} tracks?'.format(
                len(items_to_reprocess))):

        base_url = 'http://{}'.format(Site.objects.get_current().domain)

        tpl = u'''id: {id} - "{name}"
{url}
old: {current_duration} new: {new_duration} diff: {diff}
        '''

        tpl_log = u'{ct},{pk},{type},{current_duration},{new_duration},{diff},{url}\n'

        # write column header
        if log_file:
            log_file.write(
                tpl_log.format(
                    ct='content-type',
                    pk='id',
                    url='url',
                    type='type',
                    #
                    current_duration='old_duration',
                    new_duration='new_duration',
                    diff='diff',
                ))

        # loop affected media, fix durations, get playlist appearances & print/log info
        for item in items_to_reprocess:

            p = FileInfoProcessor(item.master.path)

            current_duration = item.master_duration
            new_duration = p.duration

            try:
                diff = current_duration - new_duration
            except TypeError:
                diff = '-'

            click.echo(
                tpl.format(
                    id=item.id,
                    name=item.name,
                    url=base_url + item.get_absolute_url(),
                    #
                    current_duration=current_duration,
                    new_duration=new_duration,
                    diff=diff))

            if log_file:
                log_file.write(
                    tpl_log.format(
                        ct='media',
                        pk=item.pk,
                        url=base_url + item.get_absolute_url(),
                        type=item.get_mediatype_display(),
                        #
                        current_duration=current_duration,
                        new_duration=new_duration,
                        diff=diff))
                log_file.flush()

            for p in item.get_appearances():
                if not p.pk in affected_playlist_ids:
                    affected_playlist_ids.append(p.pk)
                    # we need to store the 'current' value of the duration
                    affected_playlists.append({
                        'obj':
                        p,
                        'current_duration':
                        p.get_duration()
                    })

            # update media duration
            Media.objects.filter(pk=item.pk).update(
                master_duration=new_duration)
            invalidate_obj(item)

        # loop playlists & print/log info
        for item in affected_playlists:

            invalidate_obj(item['obj'])

            current_duration = float(item['current_duration']) / 1000
            new_duration = float(item['obj'].get_duration()) / 1000

            try:
                diff = current_duration - new_duration
            except TypeError:
                diff = '-'

            click.echo(
                tpl.format(
                    id=item['obj'].id,
                    name=item['obj'].name,
                    url=base_url + item['obj'].get_absolute_url(),
                    #
                    current_duration=current_duration,
                    new_duration=new_duration,
                    diff=diff))

            if log_file:
                log_file.write(
                    tpl_log.format(
                        ct='playlist',
                        pk=item['obj'].pk,
                        url=base_url + item['obj'].get_absolute_url(),
                        type=item['obj'].get_type_display(),
                        #
                        current_duration=current_duration,
                        new_duration=new_duration,
                        diff=diff))
                log_file.flush()

            # update playlist duration
            Playlist.objects.filter(pk=item['obj'].pk).update(
                duration=new_duration * 1000)
            invalidate_obj(item)
Пример #33
0
def add_block_view(request):
    if request.method == "POST" and "custom_block" in request.POST:
        form = QuickBlockForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Successfully added block.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
            request.session["add_block_form"] = pickle.dumps(form)

    date = None
    show_letters = None

    if "date" in request.GET:
        date = request.GET.get("date")
    if "date" in request.POST:
        date = request.POST.get("date")
    title_suffix = ""
    if date:
        date_format = re.compile(r"([0-9]{2})\/([0-9]{2})\/([0-9]{4})")
        fmtdate = date_format.sub(r"\3-\1-\2", date)
        title_suffix = " - {}".format(fmtdate)
        show_letters = True

        if "modify_blocks" in request.POST:
            letters = request.POST.getlist("blocks")
            current_letters = []
            blocks_day = EighthBlock.objects.filter(date=fmtdate)
            for day in blocks_day:
                current_letters.append(day.block_letter)
            for ltr in letters:
                if not ltr:
                    continue
                if ltr not in current_letters:
                    EighthBlock.objects.create(date=fmtdate, block_letter=ltr)
                    messages.success(
                        request, "Successfully added {} Block on {}".format(
                            ltr, fmtdate))
            for ltr in current_letters:
                if not ltr:
                    continue
                if ltr not in letters:
                    EighthBlock.objects.get(date=fmtdate,
                                            block_letter=ltr).delete()
                    messages.success(
                        request, "Successfully removed {} Block on {}".format(
                            ltr, fmtdate))

            invalidate_model(EighthBlock)

        if request.POST.get("assign_withdrawn", "off") == "on":
            try:
                grp = Group.objects.get(name="Withdrawn from TJ")
                act = EighthActivity.objects.get(name="Z - Withdrawn from TJ")
                for block in EighthBlock.objects.filter(date=fmtdate):
                    sch_act = EighthScheduledActivity.objects.update_or_create(
                        block=block,
                        activity=act,
                        defaults={
                            "attendance_taken": True,
                            "administrative": True,
                            "sticky": True,
                            "capacity": 100,
                            "restricted": True
                        },
                    )[0]
                    for u in grp.user_set.all():
                        sch_act.add_user(u, request=None, force=True)
                messages.success(
                    request,
                    "Successfully signed withdrawn students up for the withdrawn activity."
                )
            except (Group.DoesNotExist, EighthActivity.DoesNotExist):
                messages.error(
                    request,
                    'Unable to assign withdrawn students; either the "Withdrawn from TJ" group or "Z - Withdrawn from TJ" activity does not exist.',
                )

    #######
    if settings.ENABLE_HYBRID_EIGHTH:
        if request.POST.get("assign_hybrid", "off") == "on":
            blocks = EighthBlock.objects.filter(date=fmtdate)
            block_names = {
                b.block_letter[4:]
                for b in blocks if "P1" in b.block_letter
                or "P2" in b.block_letter or "Virt" in b.block_letter
            }
            if "Virt" in block_names and ("P1" in block_names
                                          or "P2" in block_names):
                eighth_admin_assign_hybrid_sticky_blocks.delay(fmtdate=fmtdate)
                messages.success(request, "Assigned groups successfully.")
            elif "Virt" in block_names and len(
                    block_names) == 1:  # everyone is virtual
                messages.warning(
                    request,
                    "Only virtual blocks have been created, so not assigning any groups."
                )
            else:  # something is wrong
                messages.error(
                    request,
                    "Created blocks successfully, but couldn't assign groups. Please do this manually."
                )
    #######

    letters = []
    visible_blocks = ["A", "B", "C", "D", "E", "F", "G", "H"]
    #######
    if settings.ENABLE_HYBRID_EIGHTH:
        visible_blocks = [
            "A - Virt", "A - P1", "A - P2", "B - Virt", "B - P1", "B - P2"
        ]
    #######
    if show_letters:
        onday = EighthBlock.objects.filter(date=fmtdate)
        for ltr in visible_blocks:
            exists = onday.filter(block_letter=ltr)
            letters.append({"name": ltr, "exists": exists})
        for blk in onday:
            if blk.block_letter not in visible_blocks:
                visible_blocks.append(blk.block_letter)
                letters.append({"name": blk.block_letter, "exists": True})

    context = {
        "admin_page_title": "Add or Remove Blocks{}".format(title_suffix),
        "date": date,
        "letters": letters,
        "show_letters": show_letters,
        "add_block_form": QuickBlockForm,
    }

    #######
    if settings.ENABLE_HYBRID_EIGHTH:
        context.update({"hybrid": True})
    #######

    return render(request, "eighth/admin/add_block.html", context)
Пример #34
0
def add_block_view(request):
    if request.method == "POST" and "custom_block" in request.POST:
        form = QuickBlockForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Successfully added block.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
            request.session["add_block_form"] = pickle.dumps(form)

    date = None
    show_letters = None

    if "date" in request.GET:
        date = request.GET.get("date")
    if "date" in request.POST:
        date = request.POST.get("date")
    title_suffix = ""
    if date:
        date_format = re.compile(r"([0-9]{2})\/([0-9]{2})\/([0-9]{4})")
        fmtdate = date_format.sub(r"\3-\1-\2", date)
        logger.debug(fmtdate)
        title_suffix = " - {}".format(fmtdate)
        show_letters = True

        if "modify_blocks" in request.POST:
            letters = request.POST.getlist("blocks")
            current_letters = []
            blocks_day = EighthBlock.objects.filter(date=fmtdate)
            for day in blocks_day:
                current_letters.append(day.block_letter)
            logger.debug(letters)
            logger.debug(current_letters)
            for l in letters:
                if not l:
                    continue
                if l not in current_letters:
                    EighthBlock.objects.create(date=fmtdate, block_letter=l)
                    messages.success(
                        request,
                        "Successfully added {} Block on {}".format(l, fmtdate))
            for l in current_letters:
                if not l:
                    continue
                if l not in letters:
                    EighthBlock.objects.get(date=fmtdate,
                                            block_letter=l).delete()
                    messages.success(
                        request, "Successfully removed {} Block on {}".format(
                            l, fmtdate))

            invalidate_model(EighthBlock)

    letters = []
    visible_blocks = ["A", "B", "C", "D", "E", "F", "G", "H"]
    if show_letters:
        onday = EighthBlock.objects.filter(date=fmtdate)
        for l in visible_blocks:
            exists = onday.filter(block_letter=l)
            letters.append({"name": l, "exists": exists})
        for blk in onday:
            if blk.block_letter not in visible_blocks:
                visible_blocks.append(blk.block_letter)
                letters.append({"name": blk.block_letter, "exists": True})

    context = {
        "admin_page_title": "Add or Remove Blocks{}".format(title_suffix),
        "date": date,
        "letters": letters,
        "show_letters": show_letters,
        "add_block_form": QuickBlockForm,
    }

    return render(request, "eighth/admin/add_block.html", context)
Пример #35
0
def edit_group_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        invalidate_model(Group)
        if group.name.lower().startswith("all students"):
            cache.delete("users:students")
        if "remove_all" in request.POST:
            users = group.user_set.all()
            num = users.count()
            for u in users:
                group.user_set.remove(u)
            group.save()
            invalidate_obj(group)
            messages.success(request, "Successfully deleted {} members of the group.".format(num))
            return redirect("eighth_admin_edit_group", group.id)
        form = GroupForm(request.POST, instance=group)
        if form.is_valid():
            if 'student_visible' in form.cleaned_data:
                props = group.properties
                props.student_visible = form.cleaned_data['student_visible']
                props.save()
                invalidate_obj(props)

            form.save()
            messages.success(request, "Successfully edited group.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error modifying group.")
    else:
        form = GroupForm(instance=group, initial={"student_visible": group.properties.student_visible})

    student_query = None
    if request.method == "GET":
        student_query = request.GET.get("q", None)

    if not student_query:
        users = group.user_set.all()  # Order not strictly alphabetical
    else:
        ion_ids = [sid.strip() for sid in student_query.split(",")]
        users = group.user_set.filter(username__in=ion_ids)
    users = users.order_by('username', 'first_name', 'last_name', 'student_id')
    p = Paginator(users, 100)  # Paginating to limit LDAP queries (slow)

    page_num = request.GET.get('p', 1)
    try:
        page = p.page(page_num)
    except PageNotAnInteger:
        page = p.page(1)
    except EmptyPage:
        page = p.page(p.num_pages)
    members = []
    for user in page:
        grade = user.grade
        emails = user.emails
        members.append({
            "id": user.id,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "student_id": user.student_id,
            "email": user.tj_email if user.tj_email else emails.first() if emails.count() > 0 else "",
            "grade": grade.number if user.grade and not user.grade.number == 13 else "Staff"
        })
    members = sorted(members, key=lambda m: (m["last_name"], m["first_name"]))
    linked_activities = EighthActivity.objects.filter(groups_allowed=group)

    def parse_int(value):
        return int(value) if value.isdigit() else None

    context = {
        "group": group,
        "members": members,
        "member_count": users.count(),
        "members_page": page,
        "edit_form": form,
        "added_ids": [parse_int(x) for x in request.GET.getlist("added")],
        "linked_activities": linked_activities,
        "admin_page_title": "Edit Group",
        "delete_url": reverse("eighth_admin_delete_group", args=[group_id])
    }

    if "possible_student" in request.GET:
        student_ids = request.GET.getlist("possible_student")
        possible_students = User.objects.get(id__in=student_ids)
        context["possible_students"] = possible_students

    return render(request, "eighth/admin/edit_group.html", context)
Пример #36
0
def edit_group_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        invalidate_model(Group)
        if group.name.lower().startswith("all students"):
            cache.delete("users:students")
        if "remove_all" in request.POST:
            users = group.user_set.all()
            num = users.count()
            for u in users:
                group.user_set.remove(u)
            group.save()
            invalidate_obj(group)
            messages.success(
                request,
                "Successfully deleted {} members of the group.".format(num))
            return redirect("eighth_admin_edit_group", group.id)
        form = GroupForm(request.POST, instance=group)
        if form.is_valid():
            if 'student_visible' in form.cleaned_data:
                props = group.properties
                props.student_visible = form.cleaned_data['student_visible']
                props.save()
                invalidate_obj(props)

            form.save()
            messages.success(request, "Successfully edited group.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error modifying group.")
    else:
        form = GroupForm(
            instance=group,
            initial={"student_visible": group.properties.student_visible})

    student_query = None
    if request.method == "GET":
        student_query = request.GET.get("q", None)

    if not student_query:
        users = group.user_set.all()  # Order not strictly alphabetical
    else:
        ion_ids = [sid.strip() for sid in student_query.split(",")]
        users = group.user_set.filter(username__in=ion_ids)

    p = Paginator(users, 100)  # Paginating to limit LDAP queries (slow)

    page_num = request.GET.get('p', 1)
    try:
        page = p.page(page_num)
    except PageNotAnInteger:
        page = p.page(1)
    except EmptyPage:
        page = p.page(p.num_pages)
    members = []
    for user in page:
        grade = user.grade
        emails = user.emails
        members.append({
            "id":
            user.id,
            "first_name":
            user.first_name,
            "last_name":
            user.last_name,
            "student_id":
            user.student_id,
            "email":
            user.tj_email if user.tj_email else emails[0] if emails else "",
            "grade":
            grade.number
            if user.grade and not user.grade.number == 13 else "Staff"
        })
    members = sorted(members, key=lambda m: (m["last_name"], m["first_name"]))
    linked_activities = EighthActivity.objects.filter(groups_allowed=group)

    def parse_int(value):
        return int(value) if value.isdigit() else None

    context = {
        "group": group,
        "members": members,
        "member_count": users.count(),
        "members_page": page,
        "edit_form": form,
        "added_ids": [parse_int(x) for x in request.GET.getlist("added")],
        "linked_activities": linked_activities,
        "admin_page_title": "Edit Group",
        "delete_url": reverse("eighth_admin_delete_group", args=[group_id])
    }

    if "possible_student" in request.GET:
        student_ids = request.GET.getlist("possible_student")
        possible_students = User.objects.get(id__in=student_ids)
        context["possible_students"] = possible_students

    return render(request, "eighth/admin/edit_group.html", context)
Пример #37
0
def do_invalidate_model(obj):
    invalidate_model(obj.__class__)
Пример #38
0
 def handle_model(self, app_name, model_name):
     model = get_model(app_name, model_name)
     if model is None:
         raise CommandError('Unknown model: %s.%s' % (app_name, model_name))
     invalidate_model(model)
Пример #39
0
def add_block_view(request):
    if request.method == "POST" and "custom_block" in request.POST:
        form = QuickBlockForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Successfully added block.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
            request.session["add_block_form"] = pickle.dumps(form)

    date = None
    show_letters = None

    if "date" in request.GET:
        date = request.GET.get("date")
    if "date" in request.POST:
        date = request.POST.get("date")
    title_suffix = ""
    if date:
        date_format = re.compile(r"([0-9]{2})\/([0-9]{2})\/([0-9]{4})")
        fmtdate = date_format.sub(r"\3-\1-\2", date)
        title_suffix = " - {}".format(fmtdate)
        show_letters = True

        if "modify_blocks" in request.POST:
            letters = request.POST.getlist("blocks")
            current_letters = []
            blocks_day = EighthBlock.objects.filter(date=fmtdate)
            for day in blocks_day:
                current_letters.append(day.block_letter)
            for ltr in letters:
                if not ltr:
                    continue
                if ltr not in current_letters:
                    EighthBlock.objects.create(date=fmtdate, block_letter=ltr)
                    messages.success(
                        request, "Successfully added {} Block on {}".format(
                            ltr, fmtdate))
            for ltr in current_letters:
                if not ltr:
                    continue
                if ltr not in letters:
                    EighthBlock.objects.get(date=fmtdate,
                                            block_letter=ltr).delete()
                    messages.success(
                        request, "Successfully removed {} Block on {}".format(
                            ltr, fmtdate))

            invalidate_model(EighthBlock)

    #######
    if settings.ENABLE_HYBRID_EIGHTH:
        if request.POST.get("assign_hybrid", "off") == "on":
            blocks = EighthBlock.objects.filter(date=fmtdate)
            block_names = {
                b.block_letter[4:]
                for b in blocks if "P1" in b.block_letter
                or "P2" in b.block_letter or "Virt" in b.block_letter
            }
            if "Virt" in block_names and ("P1" in block_names
                                          or "P2" in block_names):
                eighth_admin_assign_hybrid_sticky_blocks.delay(fmtdate=fmtdate)
                messages.success(request, "Assigned groups successfully.")
            elif "Virt" in block_names and len(
                    block_names) == 1:  # everyone is virtual
                messages.warning(
                    request,
                    "Only virtual blocks have been created, so not assigning any groups."
                )
            else:  # something is wrong
                messages.error(
                    request,
                    "Created blocks successfully, but couldn't assign groups. Please do this manually."
                )
    #######

    letters = []
    visible_blocks = ["A", "B", "C", "D", "E", "F", "G", "H"]
    #######
    if settings.ENABLE_HYBRID_EIGHTH:
        visible_blocks = [
            "A - Virt", "A - P1", "A - P2", "B - Virt", "B - P1", "B - P2"
        ]
    #######
    if show_letters:
        onday = EighthBlock.objects.filter(date=fmtdate)
        for ltr in visible_blocks:
            exists = onday.filter(block_letter=ltr)
            letters.append({"name": ltr, "exists": exists})
        for blk in onday:
            if blk.block_letter not in visible_blocks:
                visible_blocks.append(blk.block_letter)
                letters.append({"name": blk.block_letter, "exists": True})

    context = {
        "admin_page_title": "Add or Remove Blocks{}".format(title_suffix),
        "date": date,
        "letters": letters,
        "show_letters": show_letters,
        "add_block_form": QuickBlockForm,
    }

    #######
    if settings.ENABLE_HYBRID_EIGHTH:
        context.update({"hybrid": True})
    #######

    return render(request, "eighth/admin/add_block.html", context)
Пример #40
0
 def save(self, **kwargs):
     super().save(**kwargs)
     invalidate_model(ResultsTableEntry)
Пример #41
0
 def save(self, **kwargs):
     super().save(**kwargs)
     invalidate_model(BlockData)
Пример #42
0
def add_block_view(request):
    if request.method == "POST" and "custom_block" in request.POST:
        form = QuickBlockForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Successfully added block.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error adding block.")
            request.session["add_block_form"] = pickle.dumps(form)

    date = None
    show_letters = None

    if "date" in request.GET:
        date = request.GET.get("date")
    if "date" in request.POST:
        date = request.POST.get("date")
    title_suffix = ""
    if date:
        date_format = re.compile(r'([0-9]{2})\/([0-9]{2})\/([0-9]{4})')
        fmtdate = date_format.sub(r'\3-\1-\2', date)
        logger.debug(fmtdate)
        title_suffix = " - {}".format(fmtdate)
        show_letters = True

        if "modify_blocks" in request.POST:
            letters = request.POST.getlist("blocks")
            current_letters = []
            blocks_day = EighthBlock.objects.filter(date=fmtdate)
            for day in blocks_day:
                current_letters.append(day.block_letter)
            logger.debug(letters)
            logger.debug(current_letters)
            for l in letters:
                if len(l) == 0:
                    continue
                if l not in current_letters:
                    EighthBlock.objects.create(date=fmtdate, block_letter=l)
                    messages.success(request, "Successfully added {} Block on {}".format(l, fmtdate))
            for l in current_letters:
                if len(l) == 0:
                    continue
                if l not in letters:
                    EighthBlock.objects.get(date=fmtdate, block_letter=l).delete()
                    messages.success(request, "Successfully removed {} Block on {}".format(l, fmtdate))

            invalidate_model(EighthBlock)

    letters = []
    visible_blocks = ["A", "B", "C", "D", "E", "F", "G", "H"]
    if show_letters:
        onday = EighthBlock.objects.filter(date=fmtdate)
        for l in visible_blocks:
            exists = onday.filter(block_letter=l)
            letters.append({
                "name": l,
                "exists": exists
            })
        for blk in onday:
            if blk.block_letter not in visible_blocks:
                visible_blocks.append(blk.block_letter)
                letters.append({
                    "name": blk.block_letter,
                    "exists": True
                })

    context = {
        "admin_page_title": "Add or Remove Blocks{}".format(title_suffix),
        "date": date,
        "letters": letters,
        "show_letters": show_letters,
        "add_block_form": QuickBlockForm
    }

    return render(request, "eighth/admin/add_block.html", context)
Пример #43
0
def repair_durations(limit_range, dump_to, load_from, tolerance, log_file):
    """
    Repair/reprocess master durations.
    """
    from base.audio.fileinfo import FileInfoProcessor

    items_to_reprocess = []
    affected_playlists = []
    affected_playlist_ids = []

    # invalidate cache for Media
    invalidate_model(Media)

    if load_from:

        if limit_range:
            raise NotImplementedError('--limit-range option not allowed in combination with --load-from')

        # using `set` to remove duplicate ids
        item_ids = set([
            int(l.strip().split(',')[0]) for l in load_from.readlines() if float(l.strip().split(',')[1]) > tolerance
        ])


        click.echo('loaded {} ids from dump file'.format(len(item_ids)))

        items_to_reprocess = Media.objects.filter(pk__in=item_ids)

    else:

        # mysql does not support remote/streaming cursors
        # to save memory items are loaded from db individually
        values = Media.objects.order_by('pk').values('id').nocache()

        if limit_range:
            _limits = limit_range.split(':')
            values = values[_limits[0]:_limits[1]]

        item_ids = [i['id'] for i in values]

        with click.progressbar(item_ids, show_pos=True, width=48, label='Reprocessing {} tracks'.format(len(item_ids))) as bar:

            for item_pk in bar:

                close_old_connections()

                item = Media.objects.get(pk=item_pk)

                if item.master and item.master.path:

                    p = FileInfoProcessor(item.master.path)

                    current_duration = item.master_duration
                    new_duration = p.duration

                    try:
                        diff = abs(current_duration - new_duration)
                    except TypeError:
                        diff = 100.0

                    if diff > tolerance:
                        items_to_reprocess.append(item)

                    # add to csv log
                    if diff > tolerance and dump_to:
                        dump_to.write('{pk},{diff}\n'.format(pk=item.pk, diff=diff))
                        dump_to.flush()


    click.echo('{} tracks have differences in duration'.format(len(items_to_reprocess)))


    if click.confirm('Do you want to update/repair the durations on {} tracks?'.format(len(items_to_reprocess))):

        base_url = 'http://{}'.format(Site.objects.get_current().domain)


        tpl = u'''id: {id} - "{name}"
{url}
old: {current_duration} new: {new_duration} diff: {diff}
        '''


        tpl_log = u'{ct},{pk},{type},{current_duration},{new_duration},{diff},{url}\n'

        # write column header
        if log_file:
            log_file.write(tpl_log.format(
                ct='content-type',
                pk='id',
                url='url',
                type='type',
                #
                current_duration='old_duration',
                new_duration='new_duration',
                diff='diff',
            ))


        # loop affected media, fix durations, get playlist appearances & print/log info
        for item in items_to_reprocess:

            p = FileInfoProcessor(item.master.path)

            current_duration = item.master_duration
            new_duration = p.duration

            try:
                diff = current_duration - new_duration
            except TypeError:
                diff = '-'


            click.echo(tpl.format(
                id=item.id,
                name=item.name,
                url=base_url + item.get_absolute_url(),
                #
                current_duration=current_duration,
                new_duration=new_duration,
                diff=diff
            ))

            if log_file:
                log_file.write(tpl_log.format(
                    ct='media',
                    pk=item.pk,
                    url=base_url + item.get_absolute_url(),
                    type=item.get_mediatype_display(),
                    #
                    current_duration=current_duration,
                    new_duration=new_duration,
                    diff=diff
                ))
                log_file.flush()

            for p in item.get_appearances():
                if not p.pk in affected_playlist_ids:
                    affected_playlist_ids.append(p.pk)
                    # we need to store the 'current' value of the duration
                    affected_playlists.append({
                        'obj': p,
                        'current_duration': p.get_duration()
                    })

            # update media duration
            Media.objects.filter(pk=item.pk).update(master_duration=new_duration)
            invalidate_obj(item)


        # loop playlists & print/log info
        for item in affected_playlists:

            invalidate_obj(item['obj'])

            current_duration = float(item['current_duration']) / 1000
            new_duration = float(item['obj'].get_duration()) / 1000

            try:
                diff = current_duration - new_duration
            except TypeError:
                diff = '-'

            click.echo(tpl.format(
                id=item['obj'].id,
                name=item['obj'].name,
                url=base_url + item['obj'].get_absolute_url(),
                #
                current_duration=current_duration,
                new_duration=new_duration,
                diff=diff
            ))

            if log_file:
                log_file.write(tpl_log.format(
                    ct='playlist',
                    pk=item['obj'].pk,
                    url=base_url + item['obj'].get_absolute_url(),
                    type=item['obj'].get_type_display(),
                    #
                    current_duration=current_duration,
                    new_duration=new_duration,
                    diff=diff
                ))
                log_file.flush()

            # update playlist duration
            Playlist.objects.filter(pk=item['obj'].pk).update(duration=new_duration * 1000)
            invalidate_obj(item)
Пример #44
0
def do_invalidate_model(obj):
    invalidate_model(obj.__class__)
Пример #45
0
def edit_group_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        invalidate_model(Group)
        if group.name.lower().startswith("all students"):
            cache.delete("users:students")
        if "remove_all" in request.POST:
            users = group.user_set.all()
            num = users.count()
            for u in users:
                group.user_set.remove(u)
            group.save()
            invalidate_obj(group)
            messages.success(request, "Successfully deleted {} members of the group.".format(num))
            return redirect("eighth_admin_edit_group", group.id)
        form = GroupForm(request.POST, instance=group)
        if form.is_valid():
            if 'student_visible' in form.cleaned_data:
                props = group.properties
                props.student_visible = form.cleaned_data['student_visible']
                props.save()
                invalidate_obj(props)

            form.save()
            messages.success(request, "Successfully edited group.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error modifying group.")
    else:
        form = GroupForm(instance=group, initial={"student_visible": group.properties.student_visible})

    users = group.user_set.all()
    members = []
    for user in users:
        grade = user.grade
        emails = user.emails
        members.append({
            "id": user.id,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "student_id": user.student_id,
            "email": user.tj_email if user.tj_email else emails[0] if emails else "",
            "grade": grade.number if user.grade else "Staff"
        })
    members = sorted(members, key=lambda m: (m["last_name"], m["first_name"]))
    linked_activities = EighthActivity.objects.filter(groups_allowed=group)
    context = {
        "group": group,
        "members": members,
        "edit_form": form,
        "added_ids": request.GET.getlist("added"),
        "linked_activities": linked_activities,
        "admin_page_title": "Edit Group",
        "delete_url": reverse("eighth_admin_delete_group",
                              args=[group_id])
    }

    if "possible_student" in request.GET:
        student_ids = request.GET.getlist("possible_student")
        possible_students = User.objects.get(id__in=student_ids)
        context["possible_students"] = possible_students

    return render(request, "eighth/admin/edit_group.html", context)
Пример #46
0
def edit_group_view(request, group_id):
    try:
        group = Group.objects.get(id=group_id)
    except Group.DoesNotExist:
        raise http.Http404

    if request.method == "POST":
        invalidate_model(Group)
        if group.name.lower().startswith("all students"):
            cache.delete("users:students")
        if "remove_all" in request.POST:
            users = group.user_set.all()
            num = users.count()
            for u in users:
                group.user_set.remove(u)
            group.save()
            invalidate_obj(group)
            messages.success(
                request,
                "Successfully deleted {} members of the group.".format(num))
            return redirect("eighth_admin_edit_group", group.id)
        form = GroupForm(request.POST, instance=group)
        if form.is_valid():
            if 'student_visible' in form.cleaned_data:
                props = group.properties
                props.student_visible = form.cleaned_data['student_visible']
                props.save()
                invalidate_obj(props)

            form.save()
            messages.success(request, "Successfully edited group.")
            return redirect("eighth_admin_dashboard")
        else:
            messages.error(request, "Error modifying group.")
    else:
        form = GroupForm(
            instance=group,
            initial={"student_visible": group.properties.student_visible})

    users = group.user_set.all()
    members = []
    for user in users:
        grade = user.grade
        emails = user.emails
        members.append({
            "id":
            user.id,
            "first_name":
            user.first_name,
            "last_name":
            user.last_name,
            "student_id":
            user.student_id,
            "email":
            user.tj_email if user.tj_email else emails[0] if emails else "",
            "grade":
            grade.number if user.grade else "Staff"
        })
    members = sorted(members, key=lambda m: (m["last_name"], m["first_name"]))
    linked_activities = EighthActivity.objects.filter(groups_allowed=group)
    context = {
        "group": group,
        "members": members,
        "edit_form": form,
        "added_ids": request.GET.getlist("added"),
        "linked_activities": linked_activities,
        "admin_page_title": "Edit Group",
        "delete_url": reverse("eighth_admin_delete_group", args=[group_id])
    }

    if "possible_student" in request.GET:
        student_ids = request.GET.getlist("possible_student")
        possible_students = User.objects.get(id__in=student_ids)
        context["possible_students"] = possible_students

    return render(request, "eighth/admin/edit_group.html", context)
Пример #47
0
 def save(self, **kwargs):
     super().save(**kwargs)
     invalidate_model(Participant)
Пример #48
0
    def save(self, **kwargs):
        # if the object does not have the id, then we are
        # creating and not saving, thus we hash the token
        if not self.id:
            logger.info(f"creating {self.__repr__()}")
            raw_token, token = self.generate_token()
            self._token = raw_token
            self.token = token

        super().save(**kwargs)

        task_name = f'generating_results_for_raffle_{self.id}'
        task = PeriodicTask.objects.filter(name=task_name).first()
        if self.draw_datetime and not self.finalized:
            schedule, _ = IntervalSchedule.objects.get_or_create(every=3, period=IntervalSchedule.SECONDS)
            if not task:
                task = PeriodicTask(
                    name=task_name,
                    interval=schedule,
                    task="core.tasks.generate_raffle_results_task",
                    args=json.dumps([self.id]),
                )

            if self.draw_datetime > timezone.now():
                task.start_time = self.draw_datetime
            else:
                task.start_time = timezone.now()

            task.enabled = self.published
            task.save()

            # Notifications
            from notifications.models import NOTIFICATION_TYPE
            now = timezone.now()
            task, _ = PeriodicTask.objects.get_or_create(
                name=f'program_notification_on_raffle_{self.id}_type_{NOTIFICATION_TYPE.ONE_HOUR}',
                interval=schedule,
                one_off=True,
                task="notifications.tasks.send_one_hour_raffle_notifications",
                args=json.dumps([self.id]),
            )
            task.enabled = True
            task.start_time = self.draw_datetime - timedelta(hours=1)
            if task.start_time < now or not self.published:
                task.enabled = False
            task.save()

            task, _ = PeriodicTask.objects.get_or_create(
                name=f'program_notification_on_raffle_{self.id}_type_{NOTIFICATION_TYPE.ONE_MINUTE}',
                interval=schedule,
                one_off=True,
                task="notifications.tasks.send_one_minute_raffle_notifications",
                args=json.dumps([self.id]),
            )
            task.start_time = self.draw_datetime - timedelta(minutes=1)
            task.enabled = True
            if task.start_time < now or not self.published:
                task.enabled = False
            task.save()

            task, _ = PeriodicTask.objects.get_or_create(
                name=f'program_notification_on_raffle_{self.id}_type_{NOTIFICATION_TYPE.HAS_STARTED}',
                interval=schedule,
                one_off=True,
                task="notifications.tasks.send_has_started_raffle_notifications",
                args=json.dumps([self.id]),
            )
            if self.draw_datetime > timezone.now():
                task.start_time = self.draw_datetime
            else:
                task.start_time = timezone.now()

            task.enabled = self.published
            task.save()

        elif task:
            if task:
                task.enabled = False
                task.save()

        ResultsTable.objects.get_or_create(raffle=self)

        invalidate_model(Raffle)
Пример #49
0
def invalidated_update(qs, **kwargs):
    n = qs.update(**kwargs)
    invalidate_model(qs.model)
    return n