Raf Rasenberg
Raf Rasenberg

Reputation: 674

Remove individual ManyToManyRelationship instances through a Django view

So I have this Assignment model:

class Assignment(models.Model):
    has_applied = models.ManyToManyField('driver.Driver', blank=True, verbose_name=_(
        "Driver applications"), related_name="driver_applications")

Which features a has_applied field with a ManyToMany relationship to the Driver model. I want the front-end user to be able to remove these relationships.

I have a normal DetailView from the Assignment model and use it to display a list of candidates per Assignment instance:

class AssignmentCandidateDetailView(generic.DetailView):
    model = Assignment
    context_object_name = 'assignment_candidate_detail'
    template_name = 'pages/candidate/c.html'

With this url:

path('assignment/<int:pk>/candidates', views.AssignmentCandidateDetailView.as_view(), name='assignment-candidate-detail'),

And in the template I use this to get a list of the candidates that have applied and their information:

{% for entry in assignment_candidate_detail.has_applied.all %}
..... stuff
{% endfor %}

In the template list of candidates I would like to add a "Delete" button per candidate. This button will remove the ManyToMany field relationship of that particular candidate. But I am not sure how to approach this. Can someone help?

I supposse it should be something like (pseudo code):

def assignment_candidate_delete(request, pk):
    assignment = get_object_or_404(Assignment, pk=pk)
    assignment.has_applied.remove(candidate)

But how can I pass the correct information so that it removes only the relationship of a particular candidate?

EDIT:

So based on the anwser of I tried this:

URL:

path('assignment/<int:pk>/candidates/delete/<int:id>', views.assignment_candidate_delete, name='assignment-candidate-delete'),

Views:

def assignment_candidate_delete(request, pk, id):
    assignment = get_object_or_404(Assignment, pk=pk)
    assignment.has_applied.remove(id)

Template:

{% for entry in candidates %}
    <a href="{% url 'assignment-candidate-delete' request.resolver_match.kwargs.pk entry.id %}">Delete</a>
{% endfor %}

For me this seems to be a very ugly and hacky way to get the pk of the current page. Is there another way to get the desired pk?

Upvotes: 1

Views: 38

Answers (1)

Radwan Abu-Odeh
Radwan Abu-Odeh

Reputation: 2045

Inside the body of your DELETE request, you should have something like

{
    "candidate_id": "<<<<ID>>>"
}

and inside your view

def assignment_candidate_delete(request, pk, id):
    assignment = get_object_or_404(Assignment, pk=pk)
    candidate = get_object_or_404(Driver, pk=id)
    # Check for permissions if user is authorized to do such operation.
    assignment.has_applied.filter(has_applied_id=id).delete()
    # I am not sure if 'has_applied_id' is the correct field name for the driver's
    # id on the join table, if not just use the equivalent one. 

Answer Update:

for the template url generation

{% url 'assignment-candidate-delete' pk="<<<ASSIGNMENT_PK>>>>>" id="<<<<Driver ID>>>>" %}
# Just replace these with the respective data needed.

Upvotes: 1

Related Questions