my_app/views.py
from django.http import HttpResponse,HttpResponseRedirect
articles = {
'index' : "Hello this is a view inside my_app",
'simple' : 'simple views',
'sports' : 'Sports Page',
'finance' : 'Finance Page',
'politics' : "Politics Page"
}
def news_view(request, topic) :
try :
return HttpResponse(articles[topic])
except:
raise Http404("404 GENERIC ERROR")
def num_page_view(request,num):
topics_list = list(articles.keys())
topic = topics_list[num]
return HttpResponseRedirect(topic)
my_app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:num>',views.num_page_view),
path('<str:topic>/',views.news_view),
]
when i type /my_app/0, django automatically change 0 0/, so i think Django can't recognize that this page's parameter is pure int. It continues until I type 0,1,2
But when i type more than 2 (ex. /my_app/3), it works as i intended
(1. enter /my_app/3 2. redirect to /my_app/finance/)
I don't know why Django do recognize the int parameter more than 2 but not 0,1,2.
Expected
enter /my_app/0
redirect to /my_app/index/
But...
enter my_app/0
url is automatically changed to my_app/0/
can't redirect to the page so i got an error
Related
I'm fairly new to django and trying to build a message board app. Everything's been running smoothly up until I tried to add functionality to display a list of posts by author. I got it working but then my post detail view started throwing a 'No User matches the given query. Page Not found 404' error and I can't seem to figure out why. Can anyone help?
views.py
class UserPostList(generic.ListView):
model = Post
# queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'user_posts.html'
paginate_by = 6
def get_queryset(self):
"""
Method to return posts restricted to 'published' status AND to
authorship by the user whose username is the parameter in the
url.
"""
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(
status=1, author=user
).order_by('-created_on')
class FullPost(View):
def get(self, request, slug, *args, **kwargs):
"""
Method to get post object.
"""
queryset = Post.objects.filter(status=1)
post = get_object_or_404(queryset, slug=slug)
comments = post.comments.order_by('created_on')
liked = False
if post.likes.filter(id=self.request.user.id).exists():
liked = True
return render(
request,
"full_post.html",
{
"post": post,
"comments": comments,
"liked": liked
},
)
# I'll be adding a comment form in here too
urls.py
urlpatterns = [
...
path('<slug:slug>/', views.FullPost.as_view(), name='boards_post'),
...
path('<str:username>/', views.UserPostList.as_view(), name='user_posts'),
...
]
Error message
(When trying to view a single post (previously working) after adding the UserPostList view and route)
Using the URLconf defined in mhcmsgboard.urls, Django tried these URL patterns, in this order:
1. admin/
2. summernote/
3. register/ [name='register']
4. profile/ [name='profile']
5. login/ [name='login']
6. logout/ [name='logout']
7. new/ [name='create_post']
8. <slug:slug>/update/ [name='update_post']
9. <slug:slug>/delete/ [name='delete_post']
10. <str:username>/ [name='user_posts']
The current path, test-post/, matched the last one.
for <str:name> in path "-" not allowed to use in name,
when you use Slug both paths are equal.
urlpatterns = [
...
path('<slug:slug>/', views.FullPost.as_view(), name='boards_post'),
...
path('<slug:username>/', views.UserPostList.as_view(), name='user_posts'),
]
there are 2 simple ways
use sub path for one or both paths : user_post/<slug:username>/
Use re_path and define the regex to change path
exp:
re_path(r'^(?P\<username>\w+)/$', views.UserPostList.as_view()),
The problem is that you match update_post, delete_post and user_posts URL's to the root. As the error message explains, the current request is made against user_posts. And it seems that you don't have a user called test-post.
You could solve it e.g. with the following URL conf:
urlpatterns = [
...
path('board/<slug:slug>/', views.FullPost.as_view(), name='boards_post'),
...
path('posts/<str:username>/', views.UserPostList.as_view(), name='user_posts'),
...
]
That way, each path is unique and Django knows which View it has to call.
I want to return 4 different versions of the homepage
Homepage with search bar. No data present from API
Homepage with search bar. Data present from API
Homepage with search bar. No data present if request doesn't exist in API
Homepage with search bar. No data present if submit button is hit without any data being entered.
Version two, three and four all work.
However version 1, the homepage without a GET request is not returned. Due to:
MultiValueDictKeyError at / 'city'" in the views.py file.
How can this be resolved? Any help will be greatly appreciated
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
]
views.py
from django.shortcuts import render
import requests
def index(request):
# Query API with user input
payload = {'q': request.GET['city'], 'appid': 'API-KEY'}
response = requests.get('http://api.openweathermap.org/data/2.5/weather', params=payload)
# successful request
if response.status_code == 200:
# Parse json output for key value pairs
e = response.json()
context = {
'city_name': e['name'],
'weather':e['weather'][0]['main'],
'description' : e['weather'][0]['description'],
'temp' : e['main']['temp'],
'pressure':e['main']['pressure'],
'humidity':e['main']['humidity'],
'visibility':e['visibility'],
'wind_speed':e['wind']['speed'],
'wind_deg':e['wind']['deg']
}
return render(request, 'index.html', {'context': context})
else: # returns homepage if invalid city name is given in form
return render(request, 'index.html')
Instead of calling request.GET['city'] directly, check if city is set first, like:
if 'city' in request.GET:
payload = {'q': request.GET['city'], 'appid': 'API-KEY'}
I want to load a default django page. Nothing fancy. However, the error I get, hints at an id that is incorrectly set.
"Field 'id' expected a number but got 'zoekboek'."
The confusing things here (I am a django beginner, so I wouldn't be surprised if this is not confusing at all for you):
the path for this page in the urls.py is not asking for an id.
the view is not querying anything yet (I found some posts that had similar errors,
but related to a filter).
the debug info points to another view that indeed is requesting an id.
when I add a slash at the beginning of the path, the error is gone!
The code
urls.py
urlpatterns = [
path('', views.scholen, name='scholen'),
path('<school_id>', views.school_detail, name='school_detail'),
path('<school_id>/<groep_id>', views.school_groep, name='school_groep'),
path('<school_id>/<groep_id>/<UserProfile_id>', views.leerling_page, name='leerling_page'),
path('zoekboek', views.zoekboek, name='zoekboek'),
]
views.py
from django.shortcuts import render, redirect, reverse, get_object_or_404
from books.models import Book, Rating
from .models import School, Groep
from profiles.models import UserProfile, Hobby, Sport
from django.contrib.auth.models import User
# Create your views here.
def scholen(request):
"""
Homepage for participating
schools.
"""
scholen = School.objects.all()
context = {
'scholen': scholen,
}
return render(request, 'schools/school_landing.html', context)
def school_detail(request, school_id):
"""
Details of individual schools.
"""
school = get_object_or_404(School, pk=school_id)
groep = Groep.objects.filter(school=school)
context = {
'school': school,
'groep': groep,
}
return render(request, 'schools/school_detail.html', context)
def school_groep(request, school_id, groep_id):
"""
Details of groep.
"""
school = get_object_or_404(School, pk=school_id)
groep = get_object_or_404(Groep, pk=groep_id)
a = groep.naam
kinderen = UserProfile.objects.filter(groep=a)
context = {
'school': school,
'groep': groep,
'kinderen': kinderen,
}
return render(request, 'schools/school_groep.html', context)
def leerling_page(request, school_id, groep_id, UserProfile_id):
"""
Personal page of school kids.
"""
profile = get_object_or_404(UserProfile, pk=UserProfile_id)
# If viewer is owner of page, viewer can edit
owner = False
if request.user == profile.user:
owner = True
context = {
'profile': profile,
'owner': owner,
}
return render(request, 'schools/leerling_page.html', context)
def zoekboek(request):
"""
Page for kids to search their favorite book
"""
context = {
}
return render(request, 'schools/zoek_boek.html', context)
Is this enough information?
Simple fix: move path('zoekboek', views.zoekboek, name='zoekboek'), from the last place to the second place in your urls.
Why?
Because Django URLs are resolved using regular expressions; the docs say here in point 3:
Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL, matching against path_info.
Since your URL path path('<school_id>', views.school_detail, name='school_detail'), is very generic, it matches any string including the string zoekboek; so the request to zoekboek falls into the second line in your URL conf and gets routed to the view school_detail() and a school_id is expected for that view.
Suggestion: to make the URL handling easier and so you can order the URL paths however you like, you could change the URL a bit and add a prefix (for example school/) so that not any string matches the URL paths. For example, this schould work:
urlpatterns = [
path('', ...),
path('school/<school_id>', ...),
path('school/<school_id>/<groep_id>', ...),
path('school/<school_id>/<groep_id>/<UserProfile_id>', ...),
path('zoekboek', ...),
]
I'm new to Django and I'm working on an app that display the objects of a primary key. The server runs fine but I get an error on the browser that says:
'master_courses' objects has no attribute 'masterCourses_slug'
The code looks like this:
from django.shortcuts import render, redirect
from .models import master_courses, course_category, course_series
def single_slug(requests, single_slug):
categories = [c.course_slug for c in course_category.objects.all()]
if single_slug in categories:
matching_series = course_series.objects.filter(course_category__course_slug=single_slug)
series_urls = {}
for ms in matching_series.all():
part_one = master_courses.objects.filter(course_series__course_series=ms.course_series).earliest("date_added")
series_urls[ms] = part_one return render(request, "main/category.html", {"the_series": series_urls})
masterCourses = [ m.masterCourses_slug for m in master_courses.objects.all()]
if single_slug in masterCourses:
return HttpResponse(f"{single_slug} is a single slug.")
The error points to the code below (which is on the last line of the code above:
masterCourses = [ m.masterCourses_slug for m in master_courses.objects.all()]
if single_slug in masterCourses:
return HttpResponse(f"{single_slug} is a single slug.")
The error isn't on the code section, but on the browser.
Any suggestions on how I could Sol this please.
My redirect function is causing some issues. I call a url from a view using reverse with the parameters required for the view. There are no errors and in the browser of the url it correctly displays these parameters. However it seems like it redirects to the new url, but immediately after requesting the new view for the new url the page returns to the original view with the new url still displayed in the browser. Can anyone tell me if I am using the redirect function correctly or maybe I am using the reverse incorrectly?
P.S. I chopped out a lot of code because StackOverflow won't let me post all of it.
home/urls.py
from django.conf.urls import url
from home import views
app_name = 'home'
urlpatterns = [
url('^$', views.index, name='index'),
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/', views.patient_summary, name='patient_summary'),
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/careplanid=(?P<careplan_id>\d+)/', views.care_plan, name='care_plan'),
]
home/views.py
def patient_summary(request, token, patient_id, clinic_id):
user = get_user(token)
if request.method == "POST":
if ('careplanselected' in request.POST):
props = request.POST.get('careplan')
props = props.split("#")
CPID = props[0]
cpname = props[1]
my_dict = {'token': token, 'patient_id': patient_id, 'clinic_id': clinic_id, 'careplan_id': CPID}
return redirect(reverse('home:care_plan', kwargs=my_dict))
return render(request, 'home/patient_summary.html')
def care_plan(request, token, patient_id, clinic_id, careplan_id):
user = get_user(token)
care_plan = []
cpname = ''
return render(request, 'home/care_plan.html' )
Your URL patterns are missing dollars to mark the end of the URL. That means that your patient_summary view will be handling requests meant for the care_plan view.
Change the patterns to:
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/$', views.patient_summary, name='patient_summary'),
url('^patient_summary/patientid=(?P<patient_id>\d+)&clinicid=(?P<clinic_id>\d+)/careplanid=(?P<careplan_id>\d+)/$', views.care_plan, name='care_plan'),