Changeset - bdc4d207cf98
[Not reviewed]
default
0 2 0
Branko Majic (branko) - 11 years ago 2013-05-25 22:14:46
branko@majic.rs
Replaced the filtering of communications per project and location with a more robust/correct solution that applies filter on both source and destination field. Adjusted the template to use new GET parameters when creating 'add' link for the communications using filters.
2 files changed with 136 insertions and 7 deletions:
0 comments (0 inline, 0 general)
conntrackt/admin.py
Show inline comments
 
@@ -23,6 +23,136 @@ class InterfaceInline(admin.StackedInlin
 
    extra = 1
 

	
 

	
 
class CommunicationProjectListFilter(admin.SimpleListFilter):
 
    """
 
    This class implements a project-based filter for the communications list
 
    view. The filter is applied on both the source and destination field of a
 
    communication.
 

	
 
    The filter assumes that the communication belongs to a project by following
 
    the relationships through source and destination field towards interface,
 
    then entity, and then finally entity's project.
 

	
 
    Both source and destination must fullfil the requirement of belonging to the
 
    same project in order for the communication to be part of the resulting
 
    queryset.
 
    """
 

	
 
    # Set-up the filter title and parameter name that will be used for GET
 
    # request.
 
    title = "project"
 
    parameter_name = "project"
 

	
 
    def lookups(self, request, model_admin):
 
        """
 
        Returns a list of tuples that provide possible filter values that can be
 
        applied.
 

	
 
        Arguments:
 

	
 
          request - Request associated with the calling view.
 

	
 
          model_admin - Modem admin that can be used for accessing the model
 
          data.
 

	
 
        Returns:
 

	
 
          List of (project_id, project_object) tuples.
 
        """
 

	
 
        return [(p.id, p) for p in Project.objects.all()]
 

	
 
    def queryset(self, request, queryset):
 
        """
 
        Applies filtering by project ID on the provided communication queryset.
 

	
 
        Arguments:
 

	
 
          request - Request associated with the calling view.
 

	
 
          queryset - Current queryset used for displaying the information in the
 
          view.
 

	
 
        Returns:
 

	
 
          Queryset with applied filtering by object (if any). If no filtering
 
          needs to be done, returns original queryset.
 
        """
 

	
 
        # Apply the project filter on source and destination entity's project
 
        # ID, if it was specified.
 
        if self.value():
 
            return queryset.filter(source__entity__project=self.value(),
 
                                   destination__entity__project=self.value())
 

	
 
        return queryset
 

	
 

	
 
class CommunicationLocationListFilter(admin.SimpleListFilter):
 
    """
 
    This class implements a location-based filter for the communications list
 
    view. The filter is applied on both the source and destination field of a
 
    communication.
 

	
 
    The filter assumes that the communication belongs to a location by following
 
    the relationships through source and destination field towards interface,
 
    then entity, and then finally entity's location.
 

	
 
    Both source and destination must fullfil the requirement of belonging to the
 
    same location in order for the communication to be part of the resulting
 
    queryset.
 
    """
 

	
 
    # Set-up the filter title and parameter name that will be used for GET
 
    # request.
 
    title = "location"
 
    parameter_name = "location"
 

	
 
    def lookups(self, request, model_admin):
 
        """
 
        Returns a list of tuples that provide possible filter values that can be
 
        applied.
 

	
 
        Arguments:
 

	
 
          request - Request associated with the calling view.
 

	
 
          model_admin - Modem admin that can be used for accessing the model
 
          data.
 

	
 
        Returns:
 

	
 
          List of (project_id, project_object) tuples.
 
        """
 

	
 
        return [(p.id, p) for p in Location.objects.all()]
 

	
 
    def queryset(self, request, queryset):
 
        """
 
        Applies filtering by project ID on the provided communication queryset.
 

	
 
        Arguments:
 

	
 
          request - Request associated with the calling view.
 

	
 
          queryset - Current queryset used for displaying the information in the
 
          view.
 

	
 
        Returns:
 

	
 
          Queryset with applied filtering by object (if any). If no filtering
 
          needs to be done, returns original queryset.
 
        """
 

	
 
        # Apply the location filter on source and destination entity's project
 
        # ID, if it was specified.
 
        if self.value():
 
            return queryset.filter(source__entity__location=self.value(),
 
                                   destination__entity__location=self.value())
 

	
 
        return queryset
 

	
 

	
 
class CommunicationAdmin(admin.ModelAdmin):
 
    """
 
    Modifies the default admin class for the Communication class. The
 
@@ -41,7 +171,7 @@ class CommunicationAdmin(admin.ModelAdmi
 
    # All of the fields should be editable inline for ease-of-use purposes.
 
    list_editable = ('source', 'destination', 'protocol', 'port')
 
    # Add filters for project/location.
 
    list_filter = ['source__entity__project', 'source__entity__location']
 
    list_filter = (CommunicationProjectListFilter, CommunicationLocationListFilter)
 

	
 
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
 
        """
 
@@ -68,11 +198,11 @@ class CommunicationAdmin(admin.ModelAdmi
 
            interface_filter = {}
 

	
 
            # If project was specified in GET requests, add it as a filter.
 
            if 'source__entity__project__id__exact' in request.GET:
 
                interface_filter['entity__project'] = request.GET['source__entity__project__id__exact']
 
            if 'project' in request.GET:
 
                interface_filter['entity__project'] = request.GET['project']
 
            # If location was specified in GET request, add it as a filter.
 
            if 'source__entity__location__id__exact' in request.GET:
 
                interface_filter['entity__location'] = request.GET['source__entity__location__id__exact']
 
            if 'location' in request.GET:
 
                interface_filter['entity__location'] = request.GET['location']
 
            # If there are any filtering options for the show interfaces, apply them.
 
            if interface_filter:
 
                kwargs["queryset"] = Interface.objects.filter(**interface_filter)
 
@@ -120,4 +250,3 @@ admin.site.register(Location)
 
admin.site.register(Entity, EntityAdmin)
 
admin.site.register(Interface, InterfaceAdmin)
 
admin.site.register(Communication, CommunicationAdmin)
 

	
conntrackt/templates/admin/conntrackt/communication/change_list.html
Show inline comments
 
@@ -7,7 +7,7 @@
 
            <li>
 
              {# Add the GET parameters from the admin's filter to 'Add entity' button #}
 
              {# so we can perform some filtering on source/destination interfaces. #}
 
              <a href="{% url cl.opts|admin_urlname:'add' %}?{% if is_popup %}_popup=1{% endif %}{% if 'source__entity__location__id__exact' in cl.params %}&source__entity__location__id__exact={{ cl.params.source__entity__location__id__exact }}{% endif %}{% if 'source__entity__project__id__exact' in cl.params %}&source__entity__project__id__exact={{ cl.params.source__entity__project__id__exact }}{% endif %}" class="addlink">
 
              <a href="{% url cl.opts|admin_urlname:'add' %}?{% if is_popup %}_popup=1{% endif %}{% if 'location' in cl.params %}&location={{ cl.params.location }}{% endif %}{% if 'project' in cl.params %}&project={{ cl.params.project }}{% endif %}" class="addlink">
 
                {% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
 
              </a>
 
            </li>
0 comments (0 inline, 0 general)