Change url in Django

6.8k Views Asked by At

I am trying to load a pdf file in django which is already present in the database. I can access the pdf file using the url, "localhost:8000/documents/file.pdf" but when I perform the query and return the response containing this file, url it redirects to "localhost:8000/ans/documents/file.pdf" which doesn't exist. The html code is:

<form id="signup-form" method="POST" action="ans/">
        {% csrf_token %}
            <input type="text" name="id" id="id" placeholder="Report id" />
            <input type="submit" value="Check" />
        </form>

The path in urls.py is

path('ans/',views.func),

The view is:

def func(request):
if request.method=="POST":
    id=request.POST.get("id")
    ans = query.objects.get(id=id)
    response=ans.repo
    if ans is None:
        return render(request,"index.html",{})
    else:
        return redirect(response)

The bottomline is, I wan't to get rid of the "/ans/" in the url.

2

There are 2 best solutions below

12
On BEST ANSWER

When you put ans/ it adds this to the url and file location is added right after it. To solve the issue remove ans/ and give name.

path('',views.func, name='func'),

Moreover, you have logical mistakes in view and form. You should have used either normal form or ModelForm to get id to form the form.

def func(request):
    if request.method=="POST":
        id=request.POST.get("id") # do not get id from url in post method
        ans = query.objects.get(id=id)
        response=ans.repo
        if ans is None:
            return render(request,"index.html",{})# do not render index.html just use HttpResponseRedirect. rendering is used for forms.
        else:
            return redirect(response) # redirecting to the file directly is a bad pattern.

Instead of these bad design, you should have used FileField in your models.py class and after that you would be eligible to get the url with file.url call in any place without redirecting it and you could easily assign it to any button.

Note: To skip the action attribute you should use I have mentioned above form and render it in the view method.

Edit : Lets say you want to view the file from a specific object(You just need to pass the pk of the object which can be done with url template tag)

<a href="{% url 'specific_request' pk=query.pk %}">Specific request</a>

urls.py

path('response/request/<int:pk>/', views.specific_request, name='specific_request')

view.py

def specific_request(request, pk):

    query = get_object_or_404(Request,
                              pk=pk)

    context = {
        'query': query
    }

    return render(request,
                  'view-request-specific.html',
                  context=context)

Now it is time to view the uploaded file on click template.py

<label for="id_file">Uploaded file:   </label>
<a id="id_file" href="{{ query.file.url}}">  {{ query.file.url}}</a>

file.url is the magic to retrieve the exact url of the file. so when it is clicked the file will be opened.

1
On

Remove the action attribute from your form tag in your template file and change your index function to something close to the following.

def index(request):
    if request.method == "POST":
        form = Form(request.POST)
        if form.is_valid():
            id=request.POST.get("id")
            ans = query.objects.get(id=id)
            response=ans.repo
            if ans is None:
                return redirect("index.html")
            else:
                #return render (request,"ans.html",{'ans':response})
                return redirect(response)
    else:
        form = Form()
    return render(request,"index.html",{'form':form})

I have not tested the above code, so please provide feedback of any errors that you are seeing.