Got a TypeError of the upload form in Django
Question: Now I want to add a form which is to update the existing lyrics for users.
Here is my code:

urls.py:

    
    
    from django.conf.urls import url 
    from . import views
    from django.conf import settings
    urlpatterns = [
    url(r'^$', views.lyric_list, name = 'lyric_list'),
    url(r'^lyric/(?P<lyric_id>[0-9]+)/$', views.lyric_detail, name ='lyric_detail'),
    url(r'^add_lyric/$', views.add_lyric, name = "add_lyric"),
    url(r'^delete/(?P<pk>\d+)$', views.delete_lyric, name = 'delete_lyric'), 
    url(r'^update/$', views.update_lyric, name = 'update_lyric'),
    url(r'^update/(?P<pk>\d+)$', views.update_lyric_page, name = 'update_lyric_page'),]
    

views.py:

    
    
    @login_required
    def update_lyric(request, pk):
      lyric = get_object_or_404(Lyric, pk = pk)
      form = LyricForm(request.POST, initial = {'title': lyric.title, 'body': lyric.body})
      if lyric:
        username = lyric.user.username 
      if form.is_valid():
        title = form.cleaned_data['title']
        body = form.cleaned_data['body']
        lyric.title = title 
        lyric.body = body
        lyric.save()
        update_topic(request.user)
        return HttpResponseRedirect(reverse('rap_song:lyric_list'))
    return render(request, 'rap_song/update_lyric_page.html',{'pk':pk})         
    
    @login_required
    def update_lyric_page(request, pk):
      lyric = get_object_or_404(Lyric, pk = pk)
      form = LyricForm()
      return render(request, 'rap_song/update_lyric_page.html', {'pk': pk, 'form':form})
    

update_lyric_page.html:

    
    
    <div class = "col-md-6 col-md-offset-3">
    <form action="{% url 'rap_song:update_lyric' lyric_id %}" method="post" class="form">
      {% csrf_token %}
      {% bootstrap_form form layout="inline" %}
      {% buttons %}
      <button type="submit" class="btn btn-primary">
      {% bootstrap_icon "star" %} Edit
      </button>
      {% endbuttons %}
    </form >
    

But I got a error: TypeError at /rap_song/update/

update_lyric() missing 1 required positional argument: 'pk'

The whole Traceback is as below:

    
    
    Traceback:
    File "/Users/yobichi/wi/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
    132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/Users/yobichi/wi/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
    22.                 return view_func(request, *args, **kwargs)
    
    Exception Type: TypeError at /rap_song/update/
    Exception Value: update_lyric() missing 1 required positional argument: 'pk'
    

Anyone can help me with this issue? I have been struggling for this issue for
a whole day. Thank you in advance!


Answer: You need to pass the `id` of lyric in the url which needs to be updated:

    
    
    url(r'^update/(?P<pk>\d+)/$', views.update_lyric, name='update_lyric')
    

Besides, it looks like you can easily merge `update_lyrics` and
`update_lyrics_page` views into a single view function, so you'll saving an
extra url in **urls.py** :

First, remove the following url as we won't need `update_lyrics_page` anymore:

    
    
    url(r'^update/(?P<pk>\d+)$', views.update_lyric_page, name='update_lyric_page'),
    

Then, merge those two views as follows:

    
    
    @login_required
    def update_lyric(request, pk):
        lyric = get_object_or_404(Lyric, pk=pk)
        username = lyric.user.username 
        if request.POST:
            form = LyricForm(request.POST, 
                initial={'title': lyric.title, 'body': lyric.body})
            if form.is_valid():
                title = form.cleaned_data['title']
                body = form.cleaned_data['body']
                lyric.title = title 
                lyric.body = body
                lyric.save()
                update_topic(request.user)
                return HttpResponseRedirect(reverse('rap_song:lyric_list'))
            else:
                return render(request, 
                    'rap_song/update_lyric_page.html',{'pk': pk, 'form': form})
        else:
            form = LyricForm()
            return render(request, 
                'rap_song/update_lyric_page.html',{'pk': pk, 'form': form})
    

At last, I don't think you have such a variable named `lyric_id` in the
template. I suspect it should be replaced with `pk` variable that was sent so
that

    
    
    <form action="{% url 'rap_song:update_lyric' pk %}" ...
    

will resolve to a url like this:

> `/rap_song/update/1234/`

where `1234` is the id of the lyric object.

