Django: Certain users get random 404 error - django

I'm facing a strange issue that I can't handle on my own.
In normal cases when users click on a link, then they are directed to a page where they can edit their hook baits (objects). However, certain users get 404 errors, but I don't know why because the page is rendered for most users.
html where the link is
<div class="row justify-content-center mx-2" >
<div class="col-12 p-0">
<ul class="list-group text-center custom-borders m-2 p-0">
{% if own_hookbaits.count == 0 %}
<a href="{% url 'user_profile:hookbaits' request.user.fisherman.fisherman_id %}" class="list-group-item" >No hook baits yet</a>
{% else %}
{% for hookbait in own_hookbaits %}
{{ hookbait.name }}
{% endfor %}
{% endif %}
</ul>
</div>
views.py
class HookBaitUpdateView(UpdateView):
model = HookBait
template_name = "user_profile/hookbaits.html"
form_class = HookBaitForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['formset'] = HookBaitFormset(queryset=HookBait.objects.filter(fisherman=self.request.user.fisherman))
return context
def post(self, request, *args, **kwargs):
formset = HookBaitFormset(request.POST)
if formset.is_valid():
return self.form_valid(formset)
else:
return self.form_invalid(formset)
def form_valid(self, formset):
instances = formset.save(commit=False)
for instance in instances:
instance.fisherman = self.request.user.fisherman
instance.save()
return super().form_valid(formset)
def form_invalid(self, formset):
return HttpResponse("Invalid")
def get_success_url(self):
return reverse('user_profile:profile', args=(self.kwargs['pk'],))
urls.py
app_name = "user_profile"
urlpatterns = [
path("profile/<int:pk>/", views.ProfileView.as_view(), name="profile"),
path("profile/<int:pk>/hookbaits/", views.HookBaitUpdateView.as_view(), name="hookbaits"),
]
rendered html
<div class="row justify-content-center m-0">
<div class="col-12 col-md-6 col-lg-4 p-0">
<div class="row mx-3 my-3 justify-content-center text-center">
<div class="card p-2 custom-borders">
<div class="card-body p-2">
<form method="POST">
{% csrf_token %}
<table class="d-flex justify-content-center">
{{ formset.management_form }}
{% for form in formset %}
<tr class="formset_row">
{% for field in form.visible_fields %}
<td class="pb-2">
{% if form.instance.pk %}{{ form.DELETE }}{% endif %}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" class="btn btn-primary w-50 mt-1" style="background-color: #00754B;" value="Mentés">
</form>
</div>
</div>
</div>
</div>
</div>
Any suggestions what the solution would be? Thanks!

there are some possibilities
the wrong link clicked like if your trying access this URL profile/25/hookbaits/
and in the data index there is no HookBait with the id of 25
in HookBaitUpdateView you are trying to get queryset=HookBait.objects.filter(fisherman=self.request.user.fisherman)
maybe there is no hookbait associate with user.fisherman
404 page mostly served when you call get_object_or_404(HookBait, pk=25)
and update view may call this method

Related

HTMX form submission produces a duplicate form

{% extends "IntakeApp/base3.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block heading %}
<h2>Allergies for {{request.session.report_claimant}}</h2>
{% endblock %}
{% block content %}
<form hx-post="{% url 'allergy' %}" hx-target="#allergy_target" hx-swap="outerHTML">{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-2 mb-0">
{{ form.allergen|as_crispy_field }}
</div>
</div>
<button type="submit" class="btn btn-primary">Add</button>
</form>
<div class="container-fluid">
<table class="table table-striped table-sm" id="med-table">
<thead>
<tr>
<th>Allergen</th>
</tr>
</thead>
<tbody id="allergy_target">
{% for allergy in allergy_list %}
<tr>
<td>{{allergy.allergen}}</td>
<td>
<form method="POST" action="{% url 'allergy-delete' allergy.id %}">{% csrf_token %}
<input class="btn btn-danger btn-sm" type="submit" value="Delete">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
class AllergyCreateView(generic.CreateView):
model = Allergy
template_name = 'IntakeApp/allergy_form.html'
form_class = AllergyForm
def form_valid(self, form):
form.instance.assessment = Assessment.objects.get(id=self.request.session['assessment_id'])
return super(AllergyCreateView, self).form_valid(form)
def get_success_url(self):
return reverse_lazy("allergy")
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
assessment_id = self.request.session['assessment_id']
allergy_list = Allergy.objects.filter(assessment=assessment_id)
context["allergy_list"] = allergy_list
return context
I tried to all the different hx-swap options, but none fix it...It does post correctly and the swap does work, just not sure why I am getting another form in there. Please help
I added the View above. I think thats were my issue is...not sure if I am supposed to be doing this way or not?
Seems like you're trying to render the same html content in your view, which instead should only take a specific element.
You can try to use hx-select="#allergy_target" so htmx will only fetch the table content.

Django search pagination error, page not found error each time I try to move to page 2

I'm popping up with an error on my comic book ecommerce application. It's a Django app. Basically, the search function isn't paginating properly, giving me a page not found error each time I try to move to page 2 and onwards. It works fine in my general products listing area though, where there is no q-based search.
It works fine when I paginate just the products section, adding in...
paginate_by = 6
...into the class ListView section...
...and adding this section into the view.html section...
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div>
...But, once I try to paginate the search function in the same way, it appears to paginate, but page 2 and onwards just gives me a page not found error...
http://127.0.0.1:8000/search/?page=2
Request Method: GET
Request URL: http://127.0.0.1:8000/search/?page=2
Raised by: search.views.SearchProductView
....I think it has something to do with q, and the view.html section, but I'm not sure.
Any help would be much-appreciated.
Also, here's my view.html:
{% extends "base.html" %}
{% block content %}
<!-- <div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div> -->
<!--the heading with the result of the name-->
<div class="row mb-3">
{% if query %}
<div class="col-12">
Results for <b>{{ query }}</b>
<hr/>
</div>
{% else %}
<div class="col-12 col-md-8 mx-auto py-5">
{% include 'search/snippets/search-form.html' %}
</div>
<div class="col-12">
<hr>
</div>
{% endif %}
</div>
<!--create a card/item for each comic-->
<div class="row">
{% for obj in object_list %}
<div class="col">
{% include 'products/snippets/card.html' with instance=obj %}
{% if forloop.counter|divisibleby:3 %}
</div>
</div>
<!--or else if no item just create a blank row and column-->
<div class='row'><div class='col-12'><hr/></div>
{% else %}
</div>
{% endif %}
{% endfor %}
{% endblock %}
And here's a snippet that works within the view.html (search-form.html)
<form method="GET" action='{% url "search:query" %}' class="form my-2 my-lg-0 search-form">
<div class="input-group">
<input class="form-control" type="search" placeholder="Search" name='q' aria-label="Search" value='{{ request.GET.q }}'>
<span class='input-group-btn'>
<button class="btn btn-outline-success" type="submit">Search</button>
</span>
</div>
</form>
As well, here's my view.py backend:
from django.shortcuts import render
from django.views.generic import ListView
from products.models import Product
from django.core.paginator import Paginator
class SearchProductView(ListView):
#PROBLEM WITH PAGINATION IN THE SEarch function and view
#https://stackoverflow.com/questions/48436649/django-pagination-page-not-found?rq=1
#https://www.youtube.com/watch?v=acOktTcTVEQ
#https://www.youtube.com/watch?v=q-Pw7Le30qQ
#https://docs.djangoproject.com/en/3.1/topics/pagination/
#paginate_by = 6
template_name = "search/view.html"
def get_context_data(self, *args, **kwargs):
context = super(SearchProductView, self).get_context_data(*args, **kwargs)
context['query'] = self.request.GET.get('q')
return context
def get_queryset(self, *args, **kwargs):
request = self.request
method_dict = request.GET
query = method_dict.get('q', None) #method_dict['q']
if query is not None:
return Product.objects.search(query).order_by('title')
return Product.objects.filter(featured=True).order_by('title')
'''
__icontains = field contains this
__iexact = field is exactly this
'''
Finally, here are my urls:
from django.conf.urls import url
from .views import (
SearchProductView
)
urlpatterns = [
url(r'^$', SearchProductView.as_view(), name='query'),
]

Django : How can I update my views? url problem

Like below code, I made update view but it doesn't work. after I click the , it doesn't work an just
"GET /moneylogs/update/7/ HTTP/1.1" 200 6243
console log printed. the page remain like just refresh.
How can I update my moneylog?
views.py
class moneylog_update(UpdateView):
model = moneylog_models.Moneylog
form_class = forms.UpdateMoneylogForm
template_name = "moneylogs/update.html"
def form_valid(self, form):
moneylog = form.save(commit=False)
moneybook = moneybook_models.Moneybook.objects.get(
pk=self.kwargs["pk"])
moneylog.save()
form.save_m2m()
return redirect(reverse("moneybooks:detail", kwargs={'pk': moneybook.pk}))
urls.py
app_name = "moneylogs"
urlpatterns = [
path("create/<int:pk>/",
views.moneylog_create.as_view(), name="create"),
path("update/<int:pk>/",
views.moneylog_update.as_view(), name="update"),
path("<int:moneybook_pk>/delete/<int:moneylog_pk>/",
views.moneylog_delete, name="delete"),
]
moneylog_form_update.html
<div class="input {% if field.errors %}has_error{% endif %}">
<div class="flex">
<div class="w-1/4">
{{form.memo.label}}
</div>
<div class="w-3/4 border-b my-2 py-3">
{{form.memo}}
</div>
</div>
{% if form.memo.errors %}
{% for error in form.memo.errors %}
<span class="text-red-700 font-medium text-sm">{{error}}</span>
{% endfor %}
{% endif %}
</div>
<a href="{% url 'moneylogs:update' moneylog.pk %} ">
<div class="px-2 py-1 rounded bg-red-500 text-white">{{cta}}</div>
</a>
Since Update view processes the form on a post request, you need HTML form with post request to submit your data.
<form method="post" action="{% url 'moneylogs:update' moneylog.pk %}">
<div class="input {% if field.errors %}has_error{% endif %}">
<div class="flex">
<div class="w-1/4">
{{form.memo.label}}
</div>
<div class="w-3/4 border-b my-2 py-3">
{{form.memo}}
</div>
</div>
{% if form.memo.errors %}
{% for error in form.memo.errors %}
<span class="text-red-700 font-medium text-sm">{{error}}</span>
{% endfor %}
{% endif %}
</div>
<input type="submit" value="{{cta}}" />
</form>
<a></a> will hit the server using the GET request.

How load to Django Paginator Page (next/ previous)?

Hy,
i followed a tutorial for a multiple model search and it worked. now i want to paginate the output. But how can i load my paginator page (next/ previous) data into my template? So far if i push next i get an error.
views.py
from django.views.generic import TemplateView, ListView
from django.views.generic import View
from django.shortcuts import render
from django.db.models import Q
from django.core.paginator import Paginator
from itertools import chain
# --- Import Models
from datainput.models import Animal
from datainput.models import Farmer
<....>
class SearchView(ListView):
template_name = 'farmapi/searchview.html'
paginate_by = 2
count = 0
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['count'] = self.count or 0
context['query'] = self.request.GET.get('q')
return context
def get_queryset(self):
request = self.request
query = request.GET.get('q', None)
if query is not None:
farmer_results = Farmer.objects.search(query)
animal_results = Animal.objects.search(query)
# combine querysets
queryset_chain = chain(
farmer_results,
animal_results
)
qs = sorted(queryset_chain,
key=lambda instance: instance.pk,
reverse=True)
self.count = len(qs) # since qs is actually a list
return qs
return Farmer.objects.none() # just an empty queryset as default
template.html
{% extends 'base.html' %}
{% load class_name %}
{% load static %}
{% block custom_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/home_styles.css' %}">
{% endblock %}
{% block content %}
<div style="height: 10px;">
</div>
<div class="container-fluid">
<div class='row'>
<div class="col-4 offset-md-8">
<form method='GET' class='' action='.'>
<div class="input-group form-group-no-border mx-auto" style="margin-bottom: 0px; font-size: 32px;">
<span class="input-group-addon cfe-nav" style='color:#000'>
<i class="fa fa-search" aria-hidden="true"></i>
</span>
<input type="text" name="q" data-toggle="popover" data-placement="bottom" data-content="Press enter to search" class="form-control cfe-nav mt-0 py-3" placeholder="Search..." value="" style="" data-original-title="" title="" autofocus="autofocus">
</div>
</form>
</div>
</div>
</div>
<div style="height: 10px;">
</div>
<div class="container-fluid">
<div class="row">
<div class="col-6 offset-md-4">
{% for object in object_list %}
{% with object|class_name as klass %}
{% if klass == 'Farmer' %}
<div class='row'>
Farmer: <a href='{{ object.get_absolute_url }}'> {{ object.first_name }} {{ object.last_name }}</a>
</div>
{% elif klass == 'Animal' %}
<div class='row'>
Animal: <a href='{{ object.get_absolute_url }}'> {{ object.name }} {{ object.species }}</a>
</div>
{% else %}
<div class='row'>
<a href='{{ object.get_absolute_url }}'>{{ object }} | {{ object|class_name }}</a>
</div>
{% endif %}
{% endwith %}
{% empty %}
{% endfor %}
<div style="height: 10px;">
</div>
<div class='row'>
<results>{{ count }} results for <b>{{ query }}</b></results>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<!-- Pagniator Data -->
<div class="paginator">
<span class="step-links">
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_previous %}
« first
previous
{% endif %}
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div>
</div>
{% endblock %}
if i my template shows me for instance "4 Results for xyz" and "Page 1 of 2" and i push next or last Page, then i get this Error Message:
Page not found (404) Request Method: GET Request URL:
http://127.0.0.1:8000/data/searchview/?page=2 Raised by:
farmapi.views.SearchView
Invalid page (2): That page contains no results
So as far as i understand i have to explicit paginate the return of my queryset so that the paginator will put it into? Or did i miss to set a request for the paginator?
I also use a paginator where the number of items per page can be defined by the user. I added following method:
def get_paginate_by(self, queryset):
limit = int(self.request.POST.get('limit', 25))
return limit
In the template it looks like:
{% if is_paginated %}
{{ page_obj|render_paginator }}
{% endif %}
where render_paginator a template tag is.
In your template call a url like: your_url?page=2

Reverse for 'edit' with no arguments not found. 1 pattern(s) tried: ['articles/edit/(?P<pk>[0-9]+)/$']

I am a beginner in Django and now i am developing a blogging application. At the article editing section i got stucked and I dont know why its showing this error. Searched a lot and cant find an answer
NoReverseMatch at /articles/edit/2/
Reverse for 'edit' with no arguments not found. 1 pattern(s) tried: ['articles/edit/(?P<pk>[0-9]+)/$']
edit_articles section in
views.py
#login_required(login_url="/accounts/login/")
def edit_articles(request, pk):
article = get_object_or_404(Article, id=pk)
if request.method == 'POST':
form = forms.CreateArticle(request.POST, instance=article)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('articles:myarticles')
else:
form = forms.CreateArticle(instance=article)
return render(request, 'articles/article_edit.html', {'form': form})
article_edit.html
{% extends 'base_layout.html' %}
{% block content %}
<div class="create-article">
<form class="site-form" action="{% url 'articles:edit' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="jumbotron">
<div class="heading col-md-12 text-center">
<h1 class="b-heading">Edit Article</h1>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
{{ form.title }}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
{{ form.slug }}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
{{ form.thumb }}
</div>
</div>
<div class="col-md-12">
<div class="form-group">
{{ form.body }}
</div>
</div>
</div>
<button type="submit" class="btn btn-primary btn-lg btn-block">Update</button>
</div>
</form>
</div>
{% endblock %}
urls.py
from django.urls import path
from . import views
app_name = 'articles'
urlpatterns = [
path('', views.article_list, name='list'),
path('create/', views.article_create, name='create'),
path('edit/<int:pk>/', views.edit_articles, name='edit'),
path('myarticles/',views.my_articles, name='myarticles'),
path('<slug>/', views.article_detail, name='details'),
]
my_articles.html
That button in 4th is triggering the edit function with primary key and redirects to edit page
<tbody>
{% if articles %}
{% for article in articles %}
<tr class="table-active">
<th scope="row">1</th>
<td>{{ article.title }}</td>
<td>{{ article.date }}</td>
<td><button type="button" class="btn btn-info">Edit</button></td>
{% endfor %}
</tr>
{% else %}
<tr>
<td colspan=4 class="text-center text-danger">Oops!! You dont have any articles.</td>
</tr>
{% endif %}
In your template article_edit.html - post url is expecting a pk, you need to pass a pk just like you are doing it for template my_articles.html
<div class="create-article"><form class="site-form" action="{% url 'articles:edit' pk=form.instance.pk %}" method="post" enctype="multipart/form-data">{% csrf_token %}...
This way django knows which article you are editing