Using multiple models in for loop on template

28 views
Skip to first unread message

Keegen Knapp

unread,
Jul 29, 2019, 1:17:38 PM7/29/19
to Django users
I'm trying to create a detail view for the model PROJECT. In the detail view, I want to also include a model TASK and all the related objects in ATTACHMENTS to each task.
I'd like to do something like this -
{for task in task list}
{task}
{for attachments in task}
{attachment}
{end for}
{end for}


Here are snippets of the working files. Thanks in advance for any help!!

Models.py - Project
class Project(NamedModel):
    """An Asana project in a workspace having a collection of tasks."""
    layout_choices = (
        ('board', _('board')),
        ('list', _('list')),
    )

    archived = models.BooleanField(default=False)
    color = models.CharField(choices=COLOR_CHOICES, max_length=16, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    current_status = models.ForeignKey(
        'ProjectStatus', null=True, on_delete=models.SET_NULL, related_name='current_status')
    custom_field_settings = models.ManyToManyField(
        'CustomField', through='CustomFieldSetting', related_name='custom_field_settings')
    due_date = models.DateField(null=True, blank=True)
    due_on = models.DateField(null=True, blank=True)
    followers = models.ManyToManyField('User', related_name='projects_following', blank=True)
    html_notes = models.TextField(null=True, blank=True)
    layout = models.CharField(choices=layout_choices, max_length=16)
    members = models.ManyToManyField('User', blank=True)
    modified_at = models.DateTimeField(auto_now=True)
    notes = models.TextField(null=True, blank=True)
    owner = models.ForeignKey(
        'User', to_field='remote_id', related_name='projects_owned',
        null=True, on_delete=models.SET_NULL)
    public = models.BooleanField(default=False)
    resource_type = models.CharField(max_length=24, null=True, blank=True, default='project')
    start_on = models.DateField(null=True, blank=True)
    team = models.ForeignKey('Team', to_field='remote_id', null=True, on_delete=models.SET_NULL)
    workspace = models.ForeignKey('Workspace', to_field='remote_id', on_delete=models.CASCADE)

    def asana_url(self, **kwargs):
        """Returns the absolute url for this project at Asana."""
        return '{}{}/list'.format(ASANA_BASE_URL, self.remote_id)


Models.py - Task
class Task(Hearted, NamedModel):
    """An Asana task; something that needs doing."""
    status_choices = (
        ('inbox', _('inbox')),
        ('upcoming', _('upcoming')),
        ('later', _('later')),
    )
    subtype_choices = (
        ('default_task', _('default task')),
        ('section', _('section')),
    )

    assignee = models.ForeignKey(
        'User', to_field='remote_id', related_name='assigned_tasks', null=True, blank=True,
        on_delete=models.SET_NULL)
    assignee_status = models.CharField(choices=status_choices, max_length=16)
    completed = models.BooleanField(default=False)
    completed_at = models.DateTimeField(null=True, blank=True)
    custom_fields = models.TextField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    dependencies = models.ManyToManyField('self', symmetrical=False, related_name='dependents')
    due_at = models.DateTimeField(null=True, blank=True)
    due_on = models.DateField(null=True, blank=True)
    followers = models.ManyToManyField('User', related_name='tasks_following')
    html_notes = models.TextField(null=True, blank=True)
    modified_at = models.DateTimeField(auto_now=True)
    notes = models.TextField(null=True, blank=True)
    parent = models.ForeignKey(
        'self', to_field='remote_id', null=True, blank=True, on_delete=models.SET_NULL)
    projects = models.ManyToManyField('Project')
    resource_subtype = models.CharField(
        choices=subtype_choices, max_length=24, default='default_task')
    resource_type = models.CharField(max_length=24, null=True, blank=True, default='task')
    start_on = models.DateField(null=True, blank=True)
    tags = models.ManyToManyField('Tag')

    def _asana_project_url(self, project):
        return '{}{}/{}/list'.format(ASANA_BASE_URL, project.workspace.remote_id, self.remote_id)

    def asana_url(self, **kwargs):
        """Returns the absolute url for this task at Asana."""
        if 'project' in kwargs:
            return self._asana_project_url(kwargs['project'])
        projects = self.projects.all()
        if len(projects) == 1:
            project = projects[0]
            return self._asana_project_url(project)
        return super(Task, self).asana_url()

    def delete_from_asana(self, *args, **kwargs):
        """Deletes this task from Asana and then deletes this model instance."""
        client = client_connect()
        client.tasks.delete(self.remote_id)
        logger.debug('Deleted asana task %s', self.name)
        return self.delete(*args, **kwargs)

    def due(self):
        return self.due_at or self.due_on
    due.admin_order_field = 'due_on'

    def refresh_from_asana(self):
        """Updates this task from Asana."""
        client = client_connect()
        task_dict = client.tasks.find_by_id(self.remote_id)
        if task_dict['assignee']:
            user = User.objects.get_or_create(
                remote_id=task_dict['assignee']['id'],
                defaults={'name': task_dict['assignee']['name']})[0]
            task_dict['assignee'] = user
        task_dict.pop('id')
        task_dict.pop('dependents', None)
        dependencies = task_dict.pop('dependencies', None)
        task_dict.pop('hearts', None)
        task_dict.pop('memberships')
        task_dict.pop('num_hearts', None)
        task_dict.pop('projects')
        task_dict.pop('workspace')
        followers_dict = task_dict.pop('followers')
        tags_dict = task_dict.pop('tags')
        for field, value in task_dict.items():
            setattr(self, field, value)
        self.save()
        follower_ids = [follower['id'] for follower in followers_dict]
        followers = User.objects.filter(id__in=follower_ids)
        self.followers.set(followers)
        for tag_ in tags_dict:
            tag = Tag.objects.get_or_create(
                remote_id=tag_['id'],
                defaults={'name': tag_['name']})[0]
            self.tags.add(tag)
        if dependencies:
            self.dependencies.set([dep['id'] for dep in dependencies])

    def sync_to_asana(self, fields=None):
        """Updates Asana to match values from this task."""
        fields = fields or ['completed']
        data = {}
        for field in fields:
            data[field] = getattr(self, field)
        client = client_connect()
        client.tasks.update(self.remote_id, data)
        logger.debug('Updated asana for task %s', self.name)

    def add_comment(self, text):
        """Adds a comment in Asana for this task."""
        client = client_connect()
        response = client.tasks.add_comment(self.remote_id, {'text': text})
        logger.debug('Added comment for task %s: %s', self.name, text)
        return response

    def get_custom_fields(self):
        """Returns custom_fields as a dict"""
        response = json.loads(self.custom_fields)
        custom_field_values = {}
        for custom_field in response:
            if custom_field['resource_subtype'] == 'enum':
                custom_field_values[custom_field['name']] = custom_field['enum_value']['name']
            elif custom_field['resource_subtype'] == 'number':
                if custom_field.get('precision', 0):
                    custom_field_values[custom_field['name']] = float(custom_field['number_value'])
                else:
                    custom_field_values[custom_field['name']] = int(custom_field['number_value'])
            else:
                custom_field_values[custom_field['name']] = custom_field['text_value']
        return custom_field_values



Models.py - Attachment
class Attachment(NamedModel):
    """A remote file."""
    host_choices = (
        ('asana', 'asana'),
    )
    type_choices = (
        ('image', 'image'),
        ('other', 'other'),
    )
    created_at = models.DateTimeField(auto_now_add=True)
    download_url = models.URLField(max_length=1024)
    host = models.CharField(choices=host_choices, max_length=24)
    parent = models.ForeignKey('Task', to_field='remote_id', on_delete=models.CASCADE)
    permanent_url = models.URLField(max_length=1024)
    resource_type = models.CharField(max_length=24, null=True, blank=True, default='attachment')
    type = models.CharField(choices=type_choices, max_length=24, null=True, blank=True)
    view_url = models.URLField(max_length=1024)

    def asana_url(self, **kwargs):
        return self.permanent_url


Views.py - Project Detail
class ProjectDetail(SingleObjectMixin, ListView):
    queryset = Project.objects.all()
    template_name = 'dash1/project_detail.html'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object(queryset=Project.objects.all())
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['Project'] = self.object
        context['task_list'] = Task.objects.filter(projects=8).order_by('-completed_at', 'name')[:5]
        context['attachment_list'] = Attachment.objects.all()[:5]
        return context

Template - 
{% block main %}
<h1>{{ object }}</h1>
{% for object in task_list.all %}
<div class="row">
    <div class="col-xl-4">
        <div class="card-box project-box">
            <div class="dropdown float-right">
                <a href="#" class="dropdown-toggle card-drop arrow-none" data-toggle="dropdown" aria-expanded="false">
                    <h3 class="m-0 text-muted"><i class="mdi mdi-dots-horizontal"></i></h3>
                </a>
                <div class="dropdown-menu dropdown-menu-right" aria-labelledby="btnGroupDrop1">
                    <a class="dropdown-item" href="#">Edit</a>
                    <a class="dropdown-item" href="#">Delete</a>
                    <a class="dropdown-item" href="#">Add Members</a>
                    <a class="dropdown-item" href="#">Add Due Date</a>
                </div>
            </div>
            <p class="text-muted text-uppercase mb-0 font-13">DUE: {{ object.due_on }}</p>
            <h4 class="mt-0 mb-3"><a href="" class="text-dark">{{ object.name }}</a></h4>
            <p class="text-muted font-13">{{ object.notes }}<a href="#" class="font-600 text-muted">view more</a>
            </p>

            <ul class="list-inline">
                {% for object in attachment_list.all %}
                <li class="list-inline-item">
                    <img src="{{ object.permanent_url }}" height="30px">
                </li>
                {% endfor %}
            </ul>

            
            <label class="">Task completed: <span class="text-custom">{{ object.completed_at }}</span></label>
            
            </div><!-- /.progress .no-rounded -->
        </div>
    </div>
</div>
        {% empty %}
            <p class="lead">
                No Tasks Loaded
            </p>
        {% endfor %}


{% endblock %}




Reply all
Reply to author
Forward
0 new messages