英文:
Django HTMX NoReverseMatch Reverse for 'my_url' with arguments '('',)' not found using POST-request in view
问题
It appears that you're encountering a Django reverse URL resolution issue with your create_cv_workexp
view. The error message suggests that the URL reverse for create_cv_workexp
is being called with empty arguments.
One common reason for this issue is that the pk
argument is not being passed correctly when you make a POST request to the create_cv_workexp
view. In your JavaScript or HTML form, make sure you include the pk
value as part of the POST request to this view. Double-check that the position.id
value is correctly passed when making the POST request.
Here's a checklist to help you troubleshoot:
- Verify that
position.id
is correctly passed when making the POST request tocreate_cv_workexp
. - Check the JavaScript or HTML form that generates the POST request to ensure it includes the
pk
value. - Make sure there are no typos or errors in the JavaScript or HTML form that could lead to incorrect URL construction.
- Ensure that the
position.id
is available in the context when rendering the template that contains the form.
If you've checked these points and the issue persists, please provide more information about how you're making the POST request and how the position.id
is being passed, so I can offer more specific guidance.
英文:
I ran into the following issue on the Django framework using HTMX: django.urls.exceptions.NoReverseMatch: Reverse for 'create_cv_workexp' with arguments '('',)' not found. 1 pattern(s) tried: ['create\\-cv\\-workexp/(?P<pk>[0-9]+)/\\Z']
models.py:
class Position(models.Model):
position_name = models.CharField(max_length=255, blank=True, verbose_name='Position')
created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='user by', blank=True, null=True)
date_create = models.DateTimeField(auto_now_add=True)
date_update = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['date_create']
def __str__(self):
return self.position_name
class WorkExperience(models.Model):
pos = models.ForeignKey('Position', blank=True, null=True, on_delete=models.SET_NULL, verbose_name='Position Relative')
company = models.CharField(max_length=50, verbose_name='Company', blank=True)
position_work = models.CharField(max_length=50, verbose_name='Position', blank=True)
link_company = models.URLField(verbose_name="Company's link", blank=True)
date_of_employment = models.DateField(blank=True, verbose_name='Date of employment')
date_of_dismissal = models.DateField(blank=True, verbose_name='Date of dismissal')
def __str__(self):
return self.company
class Meta:
ordering = ["-date_of_employment"]
Here are two models two models linked by a ForeignKey.
forms.py:
class CreateCVWorkExperienceForm(forms.ModelForm):
''' form for WorkExperience object '''
class Meta:
model = resume.models.WorkExperience
fields = ('company',
'position_work',
'link_company',
'date_of_employment',
'date_of_dismissal')
views.py:
@login_required(login_url='/users/login/')
def create_cv_workexp(request, pk):
''' main views for displaying form for to add WorkExperience to CV and redirect to HTMX template '''
position = Position.objects.get(id=pk)
workexps = WorkExperience.objects.filter(pos=position)
form = CreateCVWorkExperienceForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
workexp = form.save(commit=False)
workexp.pos = position
workexp.save()
pk = workexp.pk
return redirect("resume:detail-workexp", pk=pk)
else:
return render(request, "resume/partials/workexp_form.html", context={
"form": form
})
context = {
"form": form,
"position": position,
"workexps": workexps,
'title': 'Add company'
}
return render(request, "resume/create_cv_workexp.html", context)
@login_required(login_url='/users/login/')
def create_workexp_form(request, pk):
''' view for rendering form of WorkExperience object for adding instnce during creating CV '''
form = CreateCVWorkExperienceForm()
position = {"id": pk}
context = {
"form": form,
"position": position,
}
return render(request, "resume/partials/workexp_form.html", context)
@login_required(login_url='/users/login/')
def detail_workexp(request, pk):
''' view for rendering added WorkExperience to DB and displaying it on 'resume/create_cv_workexp.html' template '''
workexp = get_object_or_404(WorkExperience, pk=pk)
context = {
"workexp": workexp,
'pk': pk
}
return render(request, "resume/partials/workexp_detail.html", context)
@login_required(login_url='/users/login/')
def update_workexp(request, pk):
''' view for updating added WorkExperience '''
workexp = WorkExperience.objects.get(id=pk)
form = CreateCVWorkExperienceForm(request.POST or None, instance=workexp)
if request.method == "POST":
if form.is_valid():
form.save()
return redirect("resume:detail-workexp", pk=workexp.id)
context = {
"form": form,
"workexp": workexp
}
return render(request, "resume/partials/workexp_form.html", context)
@login_required(login_url='/users/login/')
def delete_workexp(request, pk):
''' view for delete instance of WorkExperience object '''
workexp = get_object_or_404(WorkExperience, id=pk)
if request.method == "POST":
workexp.delete()
return HttpResponse("")
return HttpResponseNotAllowed(
[
"POST",
]
)
Here in view create_cv_workexp after POST-request i do redirect to url 'resume:detail-workexp' and pass to url the parameter pk which refers to id just saved the instance of object WorkExperience. Then the view create_cv_workexp must be rendres 'resume/create_cv_workexp.html' template because 'resume:detail-workexp' uses dynamic template (about this is next).
urls.py:
app_name = 'resume'
urlpatterns = [
...
# paths for working with WorWorkExperience objects during creating CV
path('create-cv-workexp/<int:pk>/', views.create_cv_workexp, name='create_cv_workexp'), # here
path('htmx/workexp/<int:pk>/', views.detail_workexp, name="detail-workexp"), # and here
path('htmx/workexp/<int:pk>/update/', views.update_workexp, name="update-workexp"),
path('htmx/workexp/<int:pk>/delete/', views.delete_workexp, name="delete-workexp"),
path('htmx/create-workexp-form/<int:pk>/', views.create_workexp_form, name='create-workexp-form'),
]
The detail-workexp url calls view detail_workexp in views.py:
@login_required(login_url='/users/login/')
def detail_workexp(request, pk):
''' view for rendering added WorkExperience to DB and displaying it on 'resume/create_cv_workexp.html' template '''
workexp = get_object_or_404(WorkExperience, pk=pk)
context = {
"workexp": workexp,
'pk': pk
}
return render(request, "resume/partials/workexp_detail.html", context)
This view rendres template workexp_detail.html:
<div hx-target="this" class="mt-3 py-3 px-3 bg-white shadow border border-gray-100">
<h3 class="text-lg leading-6 font-medium text-gray-900">
Company: {{ workexp.company }}
</h3>
<p class="text-gray-600">Position: {{ workexp.position_work }}</p>
<div class="mt-2">
<button hx-get="{% url 'resume:update-workexp' workexp.id %}" hx-swap="outerHTML"
class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Update
</button>
<button hx-post="{% url 'resume:delete-workexp' workexp.id %}" hx-swap="outerHTML swap:1s"
class="ml-2 inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500">
Delete
</button>
</div>
</div>
Here is template create_cv_workexp.html:
{% extends 'resume/base.html' %}
{% block content %}
<h2>Add work experience for {{ position.position_name }}</h2>
<hr>
<div class="container">
<button type="button" hx-get="{% url 'resume:create-workexp-form' position.id %}" hx-target="#workexpform" hx-swap="beforeend">
Add work experience
</button>
</div>
<div id="workexpform" class="container"></div>
<div class="container">
{% for workexp in workexps %}
{% include 'resume/partials/workexp_detail.html' %}
{% endfor %}
</div>
{% endblock content %}
Here is template workexp_form.html:
{% load tailwind_filters %}
<div hx-target="this" hx-swap="outerHTML" class="mt-3 py-3 px-3 bg-white shadow border border-gray-100">
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
{% if workexp %}
<button type="submit" hx-post="{% url 'resume:update-workexp' workexp.id %}"
class="inline-flex items-center px-3 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Submit
</button>
<button hx-get="{% url 'resume:detail-workexp' workexp.id %}" type="button"
class="ml-2 inline-flex items-center px-3 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Cancel
</button>
{% else %}
<button type="submit" hx-post="{% url 'resume:create_cv_workexp' position.id %}"
class="inline-flex items-center px-3 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Submit
</button>
{% endif %}
</form>
</div>
I think i passed all parameters from views to templates and urls, but when i mare POST-request from create_cv_view view i get exception:
Reverse for 'create_cv_workexp' with arguments '('',)' not found. 1 pattern(s) tried: ['create\\-cv\\-workexp/(?P<pk>[0-9]+)/\\Z']
I dont know why reverse for create_cv_workexp view is not working because i pass to url the id of Position object
Next is some screens about this exception:
The headers of request and response:
Here is full traceback of exception:
Internal Server Error: /create-cv-workexp/3/
Traceback (most recent call last):
File "D:\virtualenv\mysite\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\contrib\auth\decorators.py", line 23, in _wrapper_view
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\python_projects\my_site\mysite\resume\views.py", line 286, in create_cv_workexp
return render(request, "resume/partials/workexp_form.html", context={
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\shortcuts.py", line 24, in render
content = loader.render_to_string(template_name, context, request, using=using)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\loader.py", line 62, in render_to_string
return template.render(context, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\backends\django.py", line 61, in render
return self.template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 175, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\defaulttags.py", line 321, in render
return nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\template\defaulttags.py", line 471, in render
url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\urls\base.py", line 88, in reverse
return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\virtualenv\mysite\Lib\site-packages\django\urls\resolvers.py", line 828, in _reverse_with_prefix
raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'create_cv_workexp' with arguments '('',)' not found. 1 pattern(s) tried: ['create\\-cv\\-workexp/(?P<pk>[0-9]+)/\\Z']
[17/May/2023 21:00:03] "POST /create-cv-workexp/3/ HTTP/1.1" 500 150333
So i really don't know what's wrong... I didn't find the solution in Stack Overflow and other sources... Please help!!!
答案1
得分: 0
在 workexp_form.html
中还使用了 position
,但上下文中未提及:
{% else %}
<button type="submit" hx-post="{% url 'resume:create_cv_workexp' position.id %}"
class="inline-flex items-center px-3 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
提交
</button>
{% endif %}
else:
return render(request, "resume/partials/workexp_form.html", context={
"form": form
})
英文:
in workexp_form.html you also use position
but it is not in the context:
{% else %}
<button type="submit" hx-post="{% url 'resume:create_cv_workexp' position.id %}"
class="inline-flex items-center px-3 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Submit
</button>
{% endif %}
else:
return render(request, "resume/partials/workexp_form.html", context={
"form": form
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论