Repository: translate/pootle

Issue:
VFolders: Relate newly added units with existing vfolders
This might be achieved using the `postsave` signal for `Unit` despite it might put a lot of overhead if we are importing a project. A better method might be to push the actual job to a worker queue.

Please note that in the future this might be also necessary on unit change if we accept filtering rules including units statuses or similar.



Discussion:

Resolving patch:
diff --git a/pootle/apps/pootle_store/views.py b/pootle/apps/pootle_store/views.py
--- a/pootle/apps/pootle_store/views.py
+++ b/pootle/apps/pootle_store/views.py
@@ -727,10 +727,14 @@ def get_edit_unit(request, unit):
     alt_src_langs = get_alt_src_langs(request, user, translation_project)
     project = translation_project.project
 
+    # Retrieve the unit top priority, if any.
+    priority = unit.vfolders.aggregate(priority=Max('priority'))['priority']
+
     template_vars = {
         'unit': unit,
         'form': form,
         'comment_form': comment_form,
+        'priority': priority,
         'store': store,
         'directory': directory,
         'profile': user,
diff --git a/pootle/apps/virtualfolder/models.py b/pootle/apps/virtualfolder/models.py
--- a/pootle/apps/virtualfolder/models.py
+++ b/pootle/apps/virtualfolder/models.py
@@ -9,9 +9,12 @@
 
 from django.core.exceptions import ValidationError
 from django.db import models
+from django.db.models.signals import post_save
+from django.dispatch import receiver
 from django.utils.translation import ugettext_lazy as _
 
 from pootle.core.markup import get_markup_filter_name, MarkupField
+from pootle_app.models import Directory
 from pootle_language.models import Language
 from pootle_project.models import Project
 from pootle_store.models import Store, Unit
@@ -95,6 +98,15 @@ def save(self, *args, **kwargs):
 
                 if qs.exists():
                     self.units.add(*qs[0].units.all())
+                else:
+                    if not vf_file.endswith("/"):
+                        vf_file += "/"
+
+                    if Directory.objects.filter(pootle_path=vf_file).exists():
+                        qs = Unit.objects.filter(
+                            store__pootle_path__startswith=vf_file
+                        )
+                        self.units.add(*qs)
 
     def clean_fields(self):
         """Validate virtual folder fields."""
@@ -146,3 +158,28 @@ def get_all_pootle_paths(self):
                     for proj in projects]
 
         return [self.location]
+
+
+@receiver(post_save, sender=Unit)
+def relate_unit(sender, instance, created=False, **kwargs):
+    """Add newly created units to the virtual folders they belong, if any.
+
+    When a new store or translation project, or even a full project is added,
+    some of their units might be matched by the filters of any of the
+    previously existing virtual folders, so this signal handler relates those
+    new units to the virtual folders they belong to, if any.
+    """
+    if not created:
+        return
+
+    pootle_path = instance.store.pootle_path
+
+    for vf in VirtualFolder.objects.iterator():
+        for location in vf.get_all_pootle_paths():
+            if not pootle_path.startswith(location):
+                continue
+
+            for filename in vf.filter_rules.split(","):
+                if pootle_path == "".join([location, filename]):
+                    vf.units.add(instance)
+                    break


Test patch: