Home > OS >  Is it possible to convert these FBVs that return HttpResponse() into CBVs? (Django)
Is it possible to convert these FBVs that return HttpResponse() into CBVs? (Django)

Time:07-11

I currently have the following function-based views, their purpose is to take a specific action based on what the user selected:

@login_required()
@csrf_exempt
def remove_member(request, pk, project_id):
    if request.method == 'POST':
        user = get_object_or_404(User, id=pk)
        project = get_object_or_404(Project, id=project_id)
        project.members.remove(user)

        html = '<div  role="alert" id="message-response">' \
               'Update successful! '   user.first_name   ' is no longer part of your team. </div>'

        return HttpResponse(html)

@login_required()
@csrf_exempt
def demote_admin(request, pk, project_id):
    if request.method == 'POST':
        user = get_object_or_404(User, id=pk)
        project = get_object_or_404(Project, id=project_id)
        project.admin.remove(user)

        html = '<div  role="alert" id="message-response">' \
               'Update successful! '   user.first_name   ' is no longer an admin. </div>'

        return HttpResponse(html)

I'm using htmx on the template to populate a div with the returned html.

There are several similar functions to the examples above. So I would like to convert these into a single CBV in order to reduce redundancy. The new CBV would also require some sort of check, in order to take the appropriate action. However, I'm not sure which class would be best suited for this, and which method would be best to override in this scenario.

(admin and members are M2M fields assigned to the Project model)

CodePudding user response:

There is no reason to combine those two different actions into a single class based view.

However, you can convert them into their own class based views and extend from a basic class based view. But this will only reduce some lines and adding some extra lines.

from django.views.generic.base import View
from django.contrib.auth.mixins import LoginRequiredMixin


@csrf_exempt
class AbstractUserProjectView(LoginRequiredMixin, View):
    def post(request, pk, project_id):
        user = get_object_or_404(User, id=pk)
        project = get_object_or_404(Project, id=project_id)
        
        message = self.perform_action(user, project)

        return HttpResponse(
            '<div  role="alert" id="message-response">'   message   '</div>'
        )


@csrf_exempt
class RemoveMemberView(LoginRequiredMixin, View):
    def perform_action(user, project):
        project.members.remove(user)
        return 'Update successful! '   user.first_name   ' is no longer part of your team.'


@csrf_exempt
class DemoteAdminView(LoginRequiredMixin, View):
    def perform_action(user, project):
        project.admin.remove(user)
        return 'Update successful! '   user.first_name   ' is no longer an admin.'

But i would suggest to write them as their own views like:

from django.views.generic.base import View
from django.contrib.auth.mixins import LoginRequiredMixin

@csrf_exempt
class RemoveMemberView(LoginRequiredMixin, View):
    def post(request, pk, project_id):
        user = get_object_or_404(User, id=pk)
        project = get_object_or_404(Project, id=project_id)
        project.members.remove(user)
        return HttpResponse(
            '<div  role="alert" id="message-response">' \
               'Update successful! '   user.first_name   ' is no longer part of your team. </div>'
        )


@csrf_exempt
class DemoteAdminView(LoginRequiredMixin, View):
    def post(request, pk, project_id):
        user = get_object_or_404(User, id=pk)
        project = get_object_or_404(Project, id=project_id)
        project.admin.remove(user)
        return HttpResponse(
            '<div  role="alert" id="message-response">' \
               'Update successful! '   user.first_name   ' is no longer an admin. </div>'
        )

CodePudding user response:

Thank you for all the advice regarding csrf and redirects. I came up with the following to solve those issues:

View:

class TeamUpdateView(ProjectAuthMixin, View):
    @staticmethod
    def post(request, *args, **kwargs):
        member = kwargs['pk']
        project = Project.objects.get(slug=kwargs['slug'])
        action = kwargs['edit']

        if action == 'remove-member':
            project.members.remove(member)
            messages.success(request, "Successfully removed user.")

        elif action == 'remove-admin':
            project.admin.remove(member)
            messages.success(request, "Successfully removed user from admin group.")

        elif action == 'promote-admin':
            project.admin.add(member)
            messages.success(request, "Successfully promoted user to admin.")

        return HttpResponseRedirect(reverse('customerportal:team', args=(project.slug,)))

Template:

<div >
    <form action="{% url 'customerportal:team-edit' slug 'remove-member' member.id %}" method="post">
        {% csrf_token %}
        <button type="submit" value="Submit" >Remove Member</button>
    </form>
</div>
  • Related