I have two models: a Project model and ProjectNotes. ProjectNotes are notes that are related to Projects. The ProjectNotes model has a project field that is a foreign key of the related Project.
The problem I have is that when I delete a note on a project, the entire project is deleted. Only the note should be deleted. I think I have on_delete=models.cascade set up correctly on the ProjectNotes model. So I think the issue is with the view.
The models:
class ProjectManager(models.Manager):
def search(self, query=None):
qs = self.get_queryset()
if query is not None:
or_lookup = (
Q(title__icontains=query) |
Q(description__icontains=query)
# Q(slug__icontains=query)
)
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups
return qs
def get_with_counted_notes_documents_todos(self):
queryset = self.get_queryset().annotate(
num_notes=Count('notes'),
num_documents=Count('project_documents'),
num_todos=Count('todo_group')
)
return queryset
class Project(models.Model):
title = models.CharField(max_length= 200)
description = tinymce_models.HTMLField()
status = models.CharField(max_length=20, choices=PROJECT_CHOICES, default="active")
date = models.DateTimeField(auto_now_add=True, null=True)
created_by = models.ForeignKey(CustomUser, editable=False, null=True, blank=True, on_delete=models.RESTRICT)
tags = tagulous.models.TagField(to=SiteWideTags, blank=True, related_name='projects_tags')
objects = ProjectManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('company_project:project_detail', args=[str(self.id)])
class ProjectNotesManager(models.Manager):
def search(self, query=None):
qs = self.get_queryset()
if query is not None:
or_lookup = (
Q(title__icontains=query) |
Q(body__icontains=query)
# Q(slug__icontains=query)
)
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups
return qs
class ProjectNotes(models.Model):
title = models.CharField(max_length=200)
body = tinymce_models.HTMLField()
project = models.ForeignKey(Project, default=0, blank=True, on_delete=models.CASCADE, related_name='notes')
date = models.DateTimeField(auto_now_add=True, null=True)
created_by = models.ForeignKey(CustomUser, editable=False, null=True, blank=True, on_delete=models.RESTRICT)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('company_project:project_note_detail', args=[self.project_id, str(self.id)])
objects = ProjectNotesManager()
The view:
class ProjectNoteDeleteView(DeleteBreadcrumbMixin, DeleteView):
model = ProjectNotes
template_name = 'company_accounts/delete_project_note.html'
@cached_property
def crumbs(self):
project = self.get_object()
relate_notes = self.get_note()
bread_crumbs = [
("projects", reverse(
"company_project:" CompanyProjects.list_view_name, )
),
(f"{project.title}",
reverse(
"company_project:" CompanyProjectsDetailView.detail_view_name,
kwargs={'pk': project.id})
),
("notes", reverse(
"company_project:projectnotes_list",
kwargs={'pk': project.id})
),
(f"{relate_notes.title}",
reverse(
"company_project:project_note_detail",
kwargs={'project_pk': project.id, 'pk': self.kwargs.get('pk')})
),
(f"Delete: {relate_notes.title}",
reverse(
"company_project:project_note_detail",
kwargs={'project_pk': project.id, 'pk': self.kwargs.get('pk')})
)
]
return bread_crumbs
def get_object(self):
return get_object_or_404(Project, id=self.kwargs.get('project_pk'))
def get_note(self):
project = self.get_object()
return get_object_or_404(project.notes, id=self.kwargs.get('pk'))
def related_project(self, **kwargs):
project = get_object_or_404(Project, id=self.kwargs.get('project_pk'))
return project
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
context["note"] = self.get_note()
context['project'] = self.get_object()
return context
def get_success_url(self):
return reverse('company_project:project_detail', args=[(self.object.id)])
The URL:
path('project/<int:project_pk>/note/<int:pk>/delete', ProjectNoteDeleteView.as_view(), name='project_note_delete'),
The template:
<!-- templates/company_accounts/delete_project_note.html -->
{% extends 'base.html' %}
{% block content %}
<div >
<div >
<div >
<form method="post">{% csrf_token %}
<p>Are you sure you want to permanently delete project note "{{ note }}"?</p>
<input type="submit" value="Confirm">
</form>
</div>
</div>
</div>
{% endblock content %}
CodePudding user response:
Look at the DeleteView
implementation here.
As we can see DeleteView
calls delete
method for the result of calling get_object
function, but your implementation of get_object
return instance of Project model:
def get_object(self):
return get_object_or_404(Project, id=self.kwargs.get('project_pk'))
so this is a reason why your project deletes after you try to delete project note.