Reputation: 303
I have a list.html
with lots of records and a column containing a button to clone the specific record like this:
{% for betr in object_list %}
....
<td>
<button type="button" class="btn btn-first" onclick="window.location='../clone/{{betr.ID}}';">
<span class="fas fa-copy" style="font-size: 1rem;"></span>
</button>
</td>
{% endfor %}
My urls.py
looks like this:
urlpatterns = [
...
path('update/<int:pk>/', UpdateView.as_view(), name='update'),
path('clone/<int:pk>/', CloneView.cloneRecord(), name='clone'),
...
]
and my views.py
contains a clone view with a function to clone the record and open the UpdateView
with the cloned record for editing:
class CloneView(LoginRequiredMixin):
login_url = '/accounts/login/'
model = mymodel
def cloneRecord(self,**kwargs):
record = mymodel.objects.filter(id=self.request.GET['ID'])[0]
record.id = None
record.save()
return http.HttpResponseRedirect(reverse('/update/', kwargs={'pk':record.id}))
At the moment I am receiving following error:
TypeError: cloneRecord() missing 1 required positional argument: 'self'
What am I missing? Any help is appreciated.
Upvotes: 0
Views: 292
Reputation: 21
Here is another variant cloning an object. Biggest advantage is that you open your desired CreateView then it fills in the object from which you have got your id and then you can save it if you want. Don't forget to implement some unique constraint into your model to avoid duplicate records! In this case you won't be in the situation where users are generating useless duplicate records, because it will only be saved when the user really saves it with the submit button in the AssemblyCloneView!
urls.py:
urlpatterns = [
...
path('assembly/clone/<int:pk>/', AssemblyCloneView.as_view(), name='assembly_clone'),
template.html:
(using a bootstrap button in my case)
<a class="btn btn-light btn-sm" href="{% url 'engineering:assembly_clone' record.id %}">Clone</a>
views.py:
class AssemblyCloneView(LoginRequiredMixin, CreateView):
model = Assembly
"""
Get object desired from url with record.id and override the object context with it.
"""
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
print(context)
return self.render_to_response(context)
def get_success_url(self):
return reverse_lazy('engineering:assembly_detail', kwargs={'pk': self.object.pk})
Upvotes: 1
Reputation: 14391
if you have seperate urls for both views, then you should write your code in GET
method like this
class CloneView(LoginRequiredMixin, View):
login_url = '/accounts/login/'
def get(self,**kwargs):
record = mymodel.objects.filter(id=self.request.GET['ID'])[0]
record.id = None
record.save()
return http.HttpResponseRedirect(reverse('/update/', kwargs={'pk':record.id}))
Your url should be like this
path('clone/<int:pk>/', CloneView.as_view(), name='clone'),
Remember that as_view
is used to call a class based view. You cannot change according to function you are calling.
Upvotes: 0
Reputation: 1609
remove parenthesis, CloneView.cloneRecord()
path('clone/<int:pk>/', CloneView.cloneRecord, name='clone'),
Upvotes: 0