Загрузить файл при наличии отношений "один к одному" в django
Простите за весь приведенный код, но я так старался в течение дня, и все равно в итоге возникла проблема при передаче stage_id в качестве параметра в url действия формы
У меня есть класс Rapports, который хранит файл (я предпочитаю pdf файлы) и имеет отношения 1to1 с другим классом из другого приложения, я отправляю stage.id с html страницы в приложении Stages и это работает, id передается и я могу передать его на другую html страницу, но когда я пишу код, который мне нужен и передаю тот же шаблон url в атрибуте action шаблона, который я хочу показать (rapport/test.html ниже), он возвращает NoReverseMatch и я не могу понять почему. Это потому что я пытаюсь загрузить файл или это что-то другое? (первый раз работаю с файлами)
{% block rpt %}
<li class="nav-item">
<a class="nav-link" 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})
'''
урл проекта 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 (этот файл просто для тестирования, основной файл называется depo.html и он расширяет страницу и имеет такое же поведение, когда я удаляю url в действии, появляется форма)
<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>
здесь должен быть весь код, связанный с проблемой, я пробовал гуглить, ютуб, django doc и с изменениями, которые я делал в течение дня, ошибки отличались, но та, которую я не смог пройти - 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']
я готов переформулировать вопрос, как только найду решение или пойму его больше
это из-за stage_id, так как он не определен, поэтому url не будет найден, так как ему нужен параметр stage_id, проверьте представление, которое рендерит ваш шаблон, оно не возвращает переменную stage_id
.
добавьте это в ваше представление создания
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
в этой функции добавьте stage_id, чтобы он был передан в шаблон
я могу сказать, что она на 90% решена
проблема, с которой я столкнулся в этом вопросе, была связана с контекстом в моем представлении, и после ответа @mohamed и некоторых гуглений и попыток я сделал представление, в итоге оно заработало и сохранило файл на сервер и в базу данных и поместило id объекта Satges как id раппорта как атрибут satge_id затем перенаправляет пользователя на другую страницу
вот изменения, которые я сделал
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