Lookaway App Profile Views

Documented by kbruder tech✞ᵀᵀᴹ on Apr 05, 2021
Last updated on Jun 06, 2021


logo

Introduction

In this example, we are covering the Lookaway Posts app in order to learn how to use the AppPageMixin mixin to add context to your Lookaway CMS landing page views.


  1. App Profile View Imports

    Make sure to import the mixins along with the models and forms.

    posts/views.py
    from django.shortcuts import render, get_object_or_404
    from django.contrib import messages
    from django.contrib.auth.mixins import(
        LoginRequiredMixin,
        PermissionRequiredMixin,
        )
    from django.db.models import Q
    from django.http import HttpResponseRedirect
    from django.template import loader
    from django.urls import reverse_lazy, reverse
    from django.utils import timezone
    from django.views.generic.base import TemplateView
    from django.views.generic.edit import CreateView, FormView, UpdateView, DeleteView
    from django.views.generic.detail import DetailView
    from django.views.generic.list import ListView
    from lookaway.mixins import AppPageMixin
    from members.models import Member
    from members.mixins import MemberCreateMixin, MemberUpdateMixin, MemberDeleteMixin
    from art.models import Visual, Gallery
    from documentation.models import Article, Story, SupportDocument
    from music.models import Track, Album
    from objects.utils import Text
    from .forms import PostsAppProfileForm, PostsPageSectionForm, PostForm, ResponsePostForm, ReportPostForm
    from .models import PostsAppProfile, PostsPageSection, Post, ResponsePost, ReportPost
    

    Source: kbruder Tech

  2. App Profile Update View

    Normally class based UpdateViews are really simple. This is a special update view because the section queryset needs to be included in the context data so we can interact with them in the form. We are also sending contextual logic about when and how to render interactive buttons on the page.

    posts/views.py
    class PostsAppProfileUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    
        permission_required = 'posts.change_postsappprofile'
        model = PostsAppProfile
        form_class = PostsAppProfileForm
    
        def get_form_kwargs(self):
            kwargs = super(PostsAppProfileUpdateView, self).get_form_kwargs()
            kwargs['user'] = self.request.user
            return kwargs
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            # SEO stuff
            context['meta_title'] = profile.title
            context['meta_desc'] = "Update \"{}\" profile settings".format(profile.title)
            context['sections'] = PostsPageSection.objects.all().order_by(
                'order',
            )
            # Add posts page section button
            if self.request.user.has_perm('posts.add_postspagesection'):
                context['show_posts_page_section_add_button'] = True
                context['posts_page_section_add_button'] = { 
                    'url': reverse(
                        'posts:posts_page_section_create',
                    ),
                }
            # Edit posts page section button
            if self.request.user.has_perm('posts.change_postspagesection'):
                context['show_posts_page_section_edit_button'] = True
            # Delete posts page section button
            if self.request.user.has_perm('posts.delete_postspagesection'):
                context['show_posts_page_section_delete_button'] = True
    
            return context
    
        def get_success_url(self):
            next_url = self.request.GET.get('next')
            if next_url:
                return next_url
            else:
                return reverse('posts:posts_page')
    

    Source: kbruder Tech

  3. App Profile Landing Page View

    This is the landing page for the app. If it is the main app or the only app in your project then it can be used as the landing page for your site. Again, button logic is handled in the view. Notice we are using the "get_sets()" method to send lists of content to the page.

    posts/views.py
    # Posts app landing page
    class PostsPageView(TemplateView, AppPageMixin):
    
        template_name = 'posts/posts_page.html'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            # SEO stuff
            context['meta_title'] = profile.title
            context['meta_desc'] = profile.meta_description
            # Sections
            sections = PostsPageSection.objects.filter(
                is_enabled = True,
            ).order_by(
                'order',
            )
            if self.request.user.is_authenticated:
                context['sections'] = sections
            else:
                context['sections'] = sections.exclude(
                    members_only=True
                )
            # New and top Post instances
            context['new_posts'], context['top_posts'] = self.get_sets(
                Post,
                profile.n_posts,
                show_new=profile.show_new_posts,
                show_top=profile.show_top_posts,
            )
            # New and top Response instances
            context['new_responses'], context['top_responses'] = self.get_sets(
                ResponsePost,
                profile.n_responses,
                show_new=profile.show_new_responses,
                show_top=profile.show_top_responses,
            )
            # Create Post button
            if self.request.user.has_perm('posts.add_post'):
                context['show_post_add_button'] = True
                context['post_add_button'] = {
                    'url': reverse('posts:post_create'),
                    'text': "+Post",
                }
            # Update AppProfile button
            if self.request.user.has_perm('posts.change_postsappprofile'):
                context['show_profile_edit_button'] = True
                context['profile_edit_button'] = {
                    'url': reverse('posts:posts_app_profile_update',
                        kwargs={'pk': 1},
                    ),
                    'text': "Edit App"
                }
            # Add posts page section button
            if self.request.user.has_perm('posts.add_postspagesection'):
                context['show_posts_page_section_add_button'] = True
                context['posts_page_section_add_button'] = { 
                    'url': reverse(
                        'posts:posts_page_section_create',
                    ),
                }
            # Edit posts page section button
            if self.request.user.has_perm('posts.change_postspagesection'):
                context['show_posts_page_section_edit_button'] = True
            # Delete posts page section button
            if self.request.user.has_perm('posts.delete_postspagesection'):
                context['show_posts_page_section_delete_button'] = True
            return context
    

    Source: kbruder Tech

  4. App Page Section Create View

    This is the create view for AppPage sections. Extra keyword args are sent to the form to auto-increment the order field.

    posts/views.py
    class PostsPageSectionCreateView(LoginRequiredMixin, PermissionRequiredMixin, MemberCreateMixin, CreateView):
    
        permission_required = 'posts.add_postspagesection'
        model = PostsPageSection
        form_class = PostsPageSectionForm
    
        def get_form_kwargs(self):
            kwargs = super(PostsPageSectionCreateView, self).get_form_kwargs()
            kwargs['user'] = self.request.user
            kwargs['order'] = self.request.GET.get('order')
            return kwargs
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            context['meta_title'] = "New Page Section"
            context['meta_desc'] = "Add a section to the {} landing page.".format(profile.title)
            context['profile'] = profile
            return context
    
        def form_valid(self, form):
            member = Member.objects.get(pk=self.request.user.pk)
            form.instance.creation_date = timezone.now()
            form.instance.owner = member
            return super().form_valid(form)
    
        def get_success_url(self):
            next_url = self.request.GET.get('next')
            if next_url:
                return next_url
            else:
                return reverse(
                    'posts:posts_page_section_detail',
                    kwargs={'pk': self.object.pk},
                )
    

    Source: kbruder Tech

  5. App Page Section Detail View

    This is a detail page for viewing individual AppPage sections. When a section is successfully created or updated in a form, the requester will be redirected to this view.

    posts/views.py
    class PostsPageSectionDetailView(LoginRequiredMixin, DetailView):
    
        model = PostsPageSection
        context_object_name = 'section'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            context['meta_title'] = profile.title
            # Add posts page section button
            if self.request.user.has_perm('posts.add_postspagesection'):
                context['show_posts_page_section_add_button'] = True
                context['posts_page_section_add_button'] = {
                    'url': reverse(
                        'posts:posts_page_section_create',
                    ),
                }
            # Edit posts page section button
            if self.request.user.has_perm('posts.change_postspagesection'):
                context['show_posts_page_section_edit_button'] = True
            # Delete posts page section button
            if self.request.user.has_perm('posts.delete_postspagesection'):
                context['show_posts_page_section_delete_button'] = True
    
            return context
    

    Source: kbruder Tech

  6. App Page Section Update View

    A simple Update view for the AppPageSections. Nothing too crazy going on here. The requesting user is passed to the form in order to filter the choice selections.

    posts/views.py
    class PostsPageSectionUpdateView(LoginRequiredMixin, PermissionRequiredMixin, MemberUpdateMixin, UpdateView):
    
        permission_required = 'posts.change_postspagesection'
        model = PostsPageSection
        form_class = PostsPageSectionForm
    
        def get_form_kwargs(self):
            kwargs = super(PostsPageSectionUpdateView, self).get_form_kwargs()
            kwargs['user'] = self.request.user
            return kwargs
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            context['meta_title'] = "Update \"{}\"".format(self.object.title)
            context['meta_desc'] = "Make changes to this landing page section.".format(self.object.title)
            return context
    
        def form_valid(self, form):
            # Update last modified date for the Section
            form.instance.last_modified = timezone.now()
            return super().form_valid(form)
    
        def get_success_url(self):
            next_url = self.request.GET.get('next')
            if next_url:
                return next_url
            else:
                return reverse(
                    'posts:posts_page_section_detail',
                    kwargs={'pk': self.object.pk},
                )
    

    Source: kbruder Tech

  7. App Page Section Delete View

    The AppPageSection view for deleting sections.

    posts/views.py
    class PostsPageSectionDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
        
        permission_required = 'posts.delete_postspagesection'
        model = PostsPageSection
        context_object_name = "section"
        
        def get_success_url(self):
            return reverse(
                'posts:posts_page',
            )
    

    Source: kbruder Tech

  8. Generic Model Create View Example

    This is the create view for a Post in the Lookaway Posts App for your reference. Use this as a guide if you are need a starting point for your models' create views. The requesting user is passed as a kwarg to the form in order to filter the form choices on ManyToMany fields. Only model instances that are owned by the requesting user will appear as a choice on the form. There are other checks in place to ensure that one member cannot use this view to enumerate another member's model instances.

    posts/views.py
    class PostCreateView(LoginRequiredMixin, PermissionRequiredMixin, MemberCreateMixin, CreateView):
    
        permission_required = 'posts.add_post'
        model = Post
        form_class = PostForm
    
        def get_form_kwargs(self):
            kwargs = super(PostCreateView, self).get_form_kwargs()
            kwargs['user'] = self.request.user
            return kwargs
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            context['meta_title'] = "New Post"
            context['meta_desc'] = """Submit a Post you wish to publish. Posts \
                are open ended and can contain your contributed media."""
            return context
    
        def form_valid(self, form):
            member = self.request.user
            form.instance.creation_date = timezone.now()
            form.instance.owner = member
            form.instance.slug = Text.slugify_unique(self.model, form.instance.title)
            return super().form_valid(form)
    
        def get_success_url(self):
            next_url = self.request.GET.get('next')
            if next_url:
                return next_url
            else:
                return reverse(
                    'posts:post_detail',
                    kwargs={'slug': self.object.slug},
                )
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = FooAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            context['meta_title'] = "New Foo"
            context['meta_desc'] = "Enter the form instructions here"
            return context
    
        def form_valid(self, form):
            member = Member.objects.get(pk=self.request.user.pk)
            form.instance.creation_date = timezone.now()
            form.instance.owner = member
            form.instance.slug = Text.slugify_unique(
                    self.model,
                    form.instance.title,
            )
            return super().form_valid(form)
    
        def get_success_url(self):
            next_url = self.request.GET.get('next')
            if next_url:
                return next_url
            else:
                return reverse(
                    'foo:foo_detail',
                    kwargs={'slug': self.object.slug},
                )
    

    Source: kbruder Tech

  9. Generic Model List View Example

    This is the list view for Posts in the Lookaway Posts App for your reference. Use this as a guide if you are need a starting point for your models' list views.

    posts/views.py
    class PostListView(ListView):
    
        model = Post
        try:
            paginate_by = PostsAppProfile.objects.get_or_create(pk=1)[0].post_list_pagination
        except:
            paginate_by = 10
        context_object_name = 'posts'
    
        def get_queryset(self, *args, **kwargs):
            if self.request.user.is_authenticated:
                return Post.objects.filter(
                    Q(is_public=True),
                ).order_by(
                    'is_public',
                    '-publication_date',
                )
            else:
                return Post.objects.filter(
                    Q(is_public=True) & Q(members_only=False),
                ).order_by(
                    '-publication_date',
                )
    

    Source: kbruder Tech

  10. Generic Model Detail View Example

    This is the detail view for Posts in the Lookaway Posts App for your reference. Use this as a guide if you are need a starting point for your models' detail views. Detail views are very specific to your models so each one will be very different. In this example, Add, Edit, Delete, Response, and Marshmallow buttons are passed to the template.

    posts/views.py
    class PostDetailView(DetailView):
    
        model = Post
        context_object_name = 'post'
        
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            if self.request.user.is_authenticated:
                member = Member.objects.get(pk=self.request.user.pk)
                # Post Actions
                if self.object.owner.pk == member.pk:
                    if not self.object.is_public:
                        context['show_publish_button'] = True
                        context['publish_button'] = {
                            'url': reverse(
                                'posts:publish_post',
                                kwargs={
                                    'pk': self.object.pk,
                                },
                            )
                        }
                    context['show_edit_button'] = True
                    context['edit_button'] = {
                         'url': reverse(
                            'posts:post_update',
                            kwargs={
                                'slug': self.object.slug,
                            },
                        )
                    }
                    context['show_delete_button'] = True
                    context['delete_button'] = {
                         'url': reverse(
                            'posts:post_delete',
                            kwargs={
                                'pk': self.object.pk,
                            },
                        )
                    }
                # Marshmallow button
                if member.check_can_allocate() and not member.check_is_new():
                    context['can_add_marshmallow'] = True
                    context['marshmallow_button'] = {
                        'url': reverse(
                            'posts:post_marshmallow',
                            kwargs={
                                'pk': self.object.pk,
                            },
                        ),
                    }
                # Response button
                if self.request.user.has_perms('posts:add_response'):
                    context['can_respond'] = True
                    context['response_button'] = {
                        'url': reverse(
                            'posts:response_post_create',
                            kwargs={
                                'model': "post",
                                'pk': self.object.pk,
                                'members_only': self.object.members_only,
                            },
                        ),
                    }
                # Get the posts that are a response to this post
                context['responses'] = ResponsePost.objects.filter(
                    post=self.object,
                    is_public=True,
                ).order_by('weight', '-publication_date')[:5]
            else:
                context['responses'] = ResponsePost.objects.filter(
                    post=self.object,
                    is_public=True,
                    members_only=False,
                ).order_by('weight', '-publication_date')[:5]
            return context
    

    Source: kbruder Tech

  11. Generic Model Update View Example

    This is a pretty basic model update view. Again, the requesting user is passed as a kwarg to the form in order to filter the form choices on ManyToMany fields. Only model instances that are owned by the requesting user will appear as a choice on the form. There are other checks in place to ensure that one member cannot use this view to enumerate another member's model instances.

    posts/views.py
    class PostUpdateView(LoginRequiredMixin, PermissionRequiredMixin, MemberUpdateMixin, UpdateView):
    
        permission_required = 'posts.change_post'
        model = Post
        form_class = PostForm
    
        def get_form_kwargs(self):
            kwargs = super(PostUpdateView, self).get_form_kwargs()
            kwargs['user'] = self.request.user
            return kwargs
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            # App profile
            profile, created = PostsAppProfile.objects.get_or_create(pk=1)
            context['profile'] = profile
            context['meta_title'] = "Update \"{}\"".format(self.object.title)
            context['meta_desc'] = "Make changes to this Post."
            return context
    
        def form_valid(self, form):
            form.instance.last_modified = timezone.now()
            return super().form_valid(form)
    
        def get_success_url(self):
            next_url = self.request.GET.get('next')
            if next_url:
                return next_url
            else:
                return reverse(
                    'posts:post_detail',
                    kwargs={'slug': self.object.slug},
                )
    

    Source: kbruder Tech

  12. Model by Member List View

    This view shows only instances that belong to a given member. The member is specified in the URL.

    posts/views.py
    class MemberPostView(ListView):
    
        model = Post
        try:
            paginate_by = PostsAppProfile.objects.get_or_create(pk=1)[0].post_list_pagination
        except:
            paginate_by = 10
        context_object_name = 'posts'
    
        def get_queryset(self, *args, **kwargs):
            member = Member.objects.get(username=self.kwargs['member'])
            if self.request.user.is_authenticated:
                return Post.objects.filter(
                    owner=member
                ).order_by(
                    '-last_modified',
                )
            else: 
                return Post.objects.filter(
                    owner=member,
                    members_only=False,
                    is_public=True,
                ).order_by(
                    '-publication_date',
                )
    

    Source: kbruder Tech

Referenced by

App Profile Design Patterns - Lookaway CMS

Lookaway CMS comes with mixins, models, forms, and views that can be used when writing new Django apps.

bitcoin:3MnhNRKgrpTFQWstYicjF6GebY7u7dap4u
Bitcoin Accepted Here

3MnhNRKgrpTFQWstYicjF6GebY7u7dap4u

Please donate some Bitcoin to our site. We can use it to keep improving the site and open up to more members. Any amount will help. Thank you.


litecoin:MT61gm6pdp9rJoLyMWW5A1hnUpxAERnxqg
Litecoin Accepted Here

MT61gm6pdp9rJoLyMWW5A1hnUpxAERnxqg

Please donate some Lite to our site. We can use it to keep improving the site and open it up to more members. Any amount will help. Thank you.