Django view gets unexpected keyword argument - python

I tried get the id from my database and make something like /article/1/. 1 is the id of my article but it didn't work.
views.py
def article(request, article_id):
return render_to_response('article.html', {{'article': Articles.objects.get(id=article_id)}})
my urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
path('showall/', views.articles, name='articles'),
path('<int:article_id>/', views.articles, name='article'),
]
I get the error:
TypeError at /article/1/ articles() got an unexpected keyword argument 'article_id'
I also include image of my datebase
Datebase

It looks as if you are using views.articles for the article detail view:
path('<int:article_id>/', views.articles, name='article'),
You should use views.article instead:
path('<int:article_id>/', views.article, name='article'),
Note that there are a few improvements/fixes you can make to your article view:
Use get_object_or_404 so that you don't get a server error when the article does not exist in the database
Use render instead of the obsolete render_to_response
The context dictionary should be a dictionary {...}. You currently have double curly brackets {{...}}
Putting that together you get:
from django.shortcuts import get_object_or_404, render
def article(request, article_id):
article = get_object_or_404(Article, id=article_id)
return render(request, 'article.html', {'article': article})

Your views.py defines an article function while your urls.py makes use of an articles (note the plural) function. Is this a typo, or is there any articles function in views.py that does not support an optional article_id parameter?

You are using views.articles in article/id/ url which most likely you have used for article/showAll/ url. Use this instead:
path('<int:article_id>/', views.article, name='article')

Related

DRF- Django Rest Framework re_path query params - "Method \"GET\" not allowed."

I've been trying to GET on generics RetrieveAPIView class using the re_path method in urls.py file. After trying several combinations, I can only get the path method to work. I would like to get an endpoint something similar to /file?id={some_uid}.
So far I have the following:
django: 3.0.6
djangorestframework=3.11.0
views.py:
class UploadFileInfoView(generics.RetrieveAPIView):
lookup_field = "id"
queryset = Upload.objects.all()
serializer_class = UploadModelSerializer
urls.py:
from django.urls import path, re_path
from . import views
urlpatterns = [
path("file/", views.UploadFileView.as_view(), name="UploadFile"),
# this works
# path("file/<uuid:id>", views.UploadFileInfoView.as_view(), name="UploadFileInfo"),
# this does not
re_path(r"^file/(?P<id>[0-9A-Fa-f-]+)", views.UploadFileInfoView.as_view(), name="UploadFileInfo"),
]
Have not used url method as the documentation says
This function is an alias to django.urls.re_path(). It’s likely to be deprecated in a future release.
As far as I know, Query param is passed to the django views by default. So you don't need to handle it explicitly in the URL. In your case if you want /file?id={some_uid} , you should handle it in the view or overwrite the get_queryset method.
urls.py
urlpatterns = [
# ** your other urls **
path(r"file", views.UploadFileInfoView.as_view(), name="UploadFileInfo"),
]
views.py
class UploadFileInfoView(generics.ListAPIView):
lookup_field = "id"
queryset = Upload.objects.all()
serializer_class = UploadModelSerializer
def get_queryset(self):
return Upload.objects.get(id=self.request.GET.get('id'))
the above setup will work for /file/?id=1234 and return Upload.objects.get(id=1234). I have not tested this code but it should work and also you need to handle exception if the object is not present.

Is it required to add custom views in admin page in ModelAdmin class when we can do it normally by adding views in views.py and urls in urls.py?

According to django docs:
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.my_view),
]
return my_urls + urls
def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)
If I am not wrong, we can do the same thing by adding url in urls.py and the views in views.py as it is normally done then, what is the use of introducing this way? I am a newbie to django and I may be missing something here.
Can you please provide an example where we cannot do it in views.py and we must use the above method?
Any guidance/help would be appreciated.
I think I figured out, both of them can be used to do the same thing but the key difference is that the views which you write using above method will belong to admin app while the general views in views.py belongs to the particular app in you have written.
Hence, the url in ModelAdmin need to be called using name admin:url_name since the url goes as admin/my_views/ in given example.

NoReverseMatch for the new object

Use Django 1.10.4. I have a model Stream, for which I created CreateView. When objects are created through the admin panel everything works fine, but when I use the form CreateView, an object is created (either in admin or in the database is no different from the other), but attempts to provide a link to it through DetailView result in an error:
NoReverseMatch at /
Reverse for 'detail_stream' with arguments '()' and keyword arguments '{'pk': 17}' not found.
2 pattern(s) tried: ['(?P<pk>[0-9])/$', 'streams/(?P<pk>[0-9])/$']
This error occurs when displaying the ListView, and then only for an object created through CreateView.
The place where the error occurs:
{% for item in stream_list %}
<a href="/streams{% url "detail_stream" pk=item.id %}">
...
</a>
{% endfor %}
When you try to go directly to DetailView (http://127.0.0.1:8000/streams/17) 404 error.
urls.py:
from django.conf.urls import url
from .views import StreamDetail, StreamUpdate
urlpatterns = [
url(r'^$', StreamList.as_view(), name='streams'),
url(r'^(?P<pk>[0-9])/$', StreamDetail.as_view(), name='detail_stream'),
url(r'^(?P<pk>[0-9])/update/$', StreamUpdate.as_view()),
]
Also, the url for the streams added to the main site urlpatterns.
View:
class StreamCreate(LoginRequiredMixin, CreateView):
login_url = '/login/'
def form_valid(self, form):
regex = re.compile('[^a-zA-Z]')
newtags = []
for tag in form.cleaned_data['tags']:
tag = regex.sub('',tag)
newtags.append(tag)
form.cleaned_data['tags'] = newtags
return super(StreamCreate,self).form_valid(form)
def form_invalid(self, form):
print(form.errors)
return super(StreamCreate,self).form_invalid(form)
def get_success_url(self):
return reverse('streams')
I suspect that something I did not realize at CreateView, but I can not understand that and need your help.
Your regex in the given route is wrong.
url(r'^(?P<pk>[0-9])/$', StreamDetail.as_view(), name='detail_stream')
[0-9] means it expects a single-digit number. 17 has two digits, so the regexp needs to take that into account (add + there)
url(r'^(?P<pk>[0-9]+)/$', StreamDetail.as_view(), name='detail_stream')
Some other routes in there have the same issue.

Django Haystack Custom Search Form

I've got a basic django-haystack SearchForm working OK, but now I'm trying to create a custom search form that includes a couple of extra fields to filter on.
I've followed the Haystack documentation on creating custom forms and views, but when I try to view the form I can only get the error:
ValueError at /search/calibration/
The view assetregister.views.calibration_search didn't return an HttpResponse object. It returned None instead.
Shouldn't basing this on SearchForm take care of returning a HttpResponse object?
forms.py
from django import forms
from haystack.forms import SearchForm
class CalibrationSearch(SearchForm):
calibration_due_before = forms.DateField(required=False)
calibration_due_after = forms.DateField(required=False)
def search(self):
#First we need to store SearchQuerySet recieved after / from any other processing that's going on
sqs = super(CalibrationSearch, self).search()
if not self.is_valid():
return self.no_query_found()
#check to see if any date filters used, if so apply filter
if self.cleaned_data['calibration_due_before']:
sqs = sqs.filter(calibration_date_next__lte=self.cleaned_data['calibration_due_before'])
if self.cleaned_data['calibration_due_after']:
sqs = sqs.filter(calibration_date_next__gte=self.cleaned_data['calibration_due_after'])
return sqs
views.py
from .forms import CalibrationSearch
from haystack.generic_views import SearchView
from haystack.query import SearchQuerySet
def calibration_search(SearchView):
template_name = 'search/search.html'
form_class = CalibrationSearch
queryset = SearchQuerySet().filter(requires_calibration=True)
def get_queryset(self):
queryset = super(calibration_search, self).get_queryset()
return queryset
urls.py
from django.conf.urls import include, url
from . import views
urlpatterns = [
....
url(r'^search/calibration/', views.calibration_search, name='calibration_search'),
....
]
Haystack's SearchView is a class based view, you have to call .as_view() class method when adding a urls entry.
url(r'^search/calibration/', views.calibration_search.as_view(), name='calibration_search'),
This helped me.
"removing the "page" prefix on the search.html template did the trick, and was a good temporary solution. However, it became a problem when it was time to paginate the results. So after looking around, the solution was to use the "page_obj" prefix instead of "page" and everything works as expected. It seems the issue is that the haystack-tutorial assumes the page object is called "page", while certain versions of django its called "page_obj"? I'm sure there is a better answer - I'm just reporting my limited findings."
See this: Django-Haystack returns no results in search form

How to generate urls in django

In Django's template language, you can use {% url [viewname] [args] %} to generate a URL to a specific view with parameters. How can you programatically do the same in Python code?
What I need is to create a list of menu items where each item has name, URL, and an active flag (whether it's the current page or not). This is because it will be a lot cleaner to do this in Python than the template language.
If you need to use something similar to the {% url %} template tag in your code, Django provides the django.core.urlresolvers.reverse(). The reverse function has the following signature:
reverse(viewname, urlconf=None, args=None, kwargs=None)
https://docs.djangoproject.com/en/dev/ref/urlresolvers/
At the time of this edit the import is django.urls import reverse
I'm using two different approaches in my models.py. The first is the permalink decorator:
from django.db.models import permalink
def get_absolute_url(self):
"""Construct the absolute URL for this Item."""
return ('project.app.views.view_name', [str(self.id)])
get_absolute_url = permalink(get_absolute_url)
You can also call reverse directly:
from django.core.urlresolvers import reverse
def get_absolute_url(self):
"""Construct the absolute URL for this Item."""
return reverse('project.app.views.view_name', None, [str(self.id)])
For Python3 and Django 2:
from django.urls import reverse
url = reverse('my_app:endpoint', kwargs={'arg1': arg_1})
Be aware that using reverse() requires that your urlconf module is 100% error free and can be processed - iow no ViewDoesNotExist errors or so, or you get the dreaded NoReverseMatch exception (errors in templates usually fail silently resulting in None).

Categories

Resources