sorry for all the code given but i have tried so hard for a day still ending up with a problem when passing stage_id as a parameter in the form action url
I have a class Rapports that holds a file (i prefer pdf files) and have a 1to1 relationship with an other class from an other application, i'm sending the stage.id from a html page in Stages app and it's working the id is passed and i can pass it to an other html page but when i write the code i need and passe the same url pattern in the action attribute of the template i want to show(rapport/test.html down below) it return NoReverseMatch and i can't figure out why. Is it because i'm trying to upload a file or is it something else? (1st time working with files)
{% block rpt %}
<li >
<a href="{% url 'rapport:depo' stages.id %}">
déposer le rapport
</a>
</li>
{% endblock rpt %}
rapport.Rapports
from django.db import models
from satges.models import Stages
class Rapports(models.Model):
stage=models.OneToOneField(
Stages,
on_delete=models.CASCADE,
primary_key=True,
)
src=models.FileField(
("rapport"),
upload_to='rapports/',
max_length=100
)
r_soummit=models.DateTimeField(
auto_now=False,
auto_now_add=False,
)
satges.Stages
class Stages(models.Model):
#Stages attrs that are saved so i think no need to show them here
def est_ete(self):
# comment: this fn returns true if it's a summer intership
if(self.deb.month in[6,7,8]):
return True
# end def
def get_absolute_url(self):
return reverse("satges:det_stg", kwargs={"pk": self.pk})
#saving Stages to database with CreateView is working
def __str__(self):
return self.etd ' ' self.nature " - " self.au
rapport.forms.py
from django import forms
from .models import Rapports
class RapportsForm(forms.ModelForm):
class Meta:
model = Rapports
fields = ['src']
widgets = {
'src': forms.FileInput(),
}
rapport.views
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from django.views.generic import CreateView
from satges.models import Stages
from .models import Rapports
from .forms import RapportsForm
# Create your views here.
def afficher(request, stage_id):
# comment:
#return HttpResponse('stage: %s'% stage_id)
if request.method == 'POST':
form = RapportsForm(request.POST, request.FILES)
else:
form=RapportsForm()
return render(request, 'rapport/test.html', {'form': form})
class RapportCreateView(CreateView):
model = Rapports
form_class=RapportsForm
template_name = "rapport/test.html"
# end def
'''
def afficher_depo(request, stage_id):
form=RapportsForm()
print(stage_id)
return render(request,'rapport/depo.html', {'form': form})
def depo(request, stage_id):
if request.method == 'POST':
form = RapportsForm(request.POST)
stage=get_object_or_404(Stages, pk=stage_id)
src = form.cleaned_data['src']
rpt=Rapports(stage=stage,src=src)
rpt.save()
else:
return HttpResponse('rapport isn\'t saved')
return render(request,'rapport/depo.html', {'form':form})
'''
the project url conf
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('satges.urls')),
path('journal/', include('journaux.urls')),
path('rapport/<int:pk>', include('rapport.urls')),
] static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
rapport.urls.py
from django.urls import path, re_path
from . import views
app_name = 'rapport'
urlpatterns = [
path('',views.RapportCreateView.as_view(), name='depo'),
]
test.html (this file is just for testing the main file is called depo.html and it extends otthe page and have the same behavior when i remove the url in action the form appears)
<html>
<head>
<title>test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" action="{% url 'rapport:depo' satge_id %}">
<!--when i remove the url tag the input form appears and i can choose a file but i ofc can't send it without the action-->
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="déposer votre rapport" name="depo">
</form>
</body>
</html>
this should be all the code related to the problem, i have tried googling, youtube, django doc and with the changes i made along the day the errors differed but the one i couldn't get through is NoReverseMatch
error
Error during template rendering
In template /home/ssoya/Documents/pfe/new/pages/templates/rapport/test.html, error at line 6
Reverse for 'depo' with arguments '('',)' not found. 1 pattern(s) tried: ['rapport/(?P<pk>[0-9] )\\Z']
after the 1st answer my view became like this but no matter i change it still no use
class RapportsCreateView(CreateView):
model = Rapports
form_class=RapportsForm
template_name = "rapport/depo.html"
def get_context_data(self, **kwargs):
context=super(RapportsCreateView, self).get_context_data(**kwargs)
#stage=Stages.objects.get(pk=self.kwargs.get('pk'))
context['stages'] = Stages.objects.filter(pk=self.kwargs.get('pk'))
return context
then i tried something else: I replaced stage.id with 1 then 13 to see what happens. It raised IntegrityError
NOT NULL constraint failed: rapport_rapports.stage_id
The above exception (NOT NULL constraint failed: rapport_rapports.stage_id) was the direct cause of the following exception:
response = get_response(request)
i'm willing to restructure the question once i found a soloution or understand it more
CodePudding user response:
it's because of stage_id as it's not defined so url will not be found as it needs the parameter stage_id, check the view that rendering your template it is not retuning the stage_id variable
add this to your create view
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# context is a dict so
#update it with your stage id
return context
in this function add the stage_id so it get passed to the template
CodePudding user response:
i can say it is 90% Solved
the problem i had in this question was related to the context in my view and after the answer of @mohamed and some googling and tries i made the view ended up working and saving the file to the server and the database and putting the id of the Satges object as the id of rapport as the attribute satge_id then redirects the user to an other page
here are the modifications i made
views.py
class RapportsCreateView(CreateView):
model = Rapports
form_class = RapportsForm
template_name = "rapport/depo.html"
def form_valid(self, form):
self.stage_id = self.kwargs['pk']
stage = Stages.objects.get(id=self.stage_id)
form.instance.stage_id = stage.id
form.instance.r_soummit = timezone.now()
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
stage = Stages.objects.get(pk=self.kwargs.get('pk'))
context['stage'] = stage
context['stage_id'] = stage.id
return context
models.Rapports
def get_absolute_url(self):
return reverse("rapport:det_rpt", kwargs={"pk": self.pk})
def __str__(self):
return self.src