HI working on a new site using Django. can't seem to figure this bug out. First the intended site will be structured as;
Home page - Showing different languages with links to countries you can learn those languages in.
Click on a country on home page -> Country page
Country page will list all fo the schools that teach that language in that country.
Click on a school on country page -> School page.
I figured out this line of code in the Country page is causing the issue, but I don't know how to fix it
<a href="{% url 'schools' schools.id %}">
<div class="left"><h4>Test Link</h4></div>
</a>
This is the error I get in the browser
NoReverseMatch at /5/ Reverse for 'schools' with arguments '('',)' not found. 1 pattern(s) tried: ['(?P<country_id>[0-9]+)/(?P<schools_id>[0-9]+)/$']
Code from the project:
Models.py
from django.db import models
class Languages(models.Model):
language = models.CharField(max_length=100, blank=True, null=True)
country = models.ManyToManyField('Country', blank=True)
image = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.language
class Country(models.Model):
country_name = models.CharField(max_length=50)
country_image = models.CharField(max_length=100, blank=True)
country_city = models.ManyToManyField('City', blank=True)
def __str__(self):
return self.country_name
class City(models.Model):
city_name = models.CharField(max_length=50)
city_image = models.CharField(max_length=1000, blank=True)
city_schools_in = models.ManyToManyField('Schools', blank=True)
def __str__(self):
return self.city_name
class Schools(models.Model):
school_name = models.CharField(max_length=100)
school_image = models.CharField(max_length=1000, blank=True)
school_country = models.ManyToManyField('Country', blank=True)
school_city = models.ManyToManyField('City', blank=True)
school_description = models.TextField()
school_accreditations = models.ManyToManyField('Accreditations', blank=True)
school_lpw = models.IntegerField()
school_cs = models.IntegerField()
school_course = models.ManyToManyField('CoursePrices', blank=True)
def __str__(self):
return self.school_name
class Accreditations(models.Model):
accreditation_name = models.CharField(max_length=50)
def __str__(self):
return self.accreditation_name
class CoursePrices(models.Model):
course_title = models.CharField(max_length=50, blank=True)
lessons_per_week = models.IntegerField()
class_size = models.IntegerField()
weekly_price = models.IntegerField()
language_level = models.CharField(max_length=50, blank=True)
def __str__(self):
return self.course_title
Views.py
from django.shortcuts import render
from django.http import Http404
from .models import Schools, CoursePrices, Languages, Country, City
def home(request):
languages = Languages.objects.all()
return render(request, 'home.html', {
'languages': languages,
})
def country(request, country_id):
try:
country = Country.objects.get(id=country_id)
except Languages.DoesNotExist:
raise Http404('Language not found')
return render(request, 'country.html', {
'country': country,
})
def schools(request, country_id, schools_id):
try:
schools = Schools.objects.get(id=schools_id)
except Schools.DoesNotExist:
raise Http404('school not found')
return render(request, 'schools.html', {
'schools': schools,
})
urls.py
from django.contrib import admin
from django.urls import path
from schools import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name='home'),
path('<int:country_id>/', views.country, name='country'),
path('<int:country_id>/<int:schools_id>/', views.schools, name='schools'),
]
Project structure screenshot
Any help would be greatly appreciated. Also please forgive any mistakes in posting or coding, still very new to coding and stack overflow / life in general :)
Your path named schools requires two arguments, you only passed one, so it failed to match any route.
Your comment on Rafael's answer that it is still not matching the path, even with two arguments provided, is because of the order of the paths in your urls.py file.
Django will go through the list of paths in order, and because a path with the single parameter country_id is found first it tries that but fails because you have a second parameter.
To fix that change the order of your paths
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name='home'),
# next two lines have been swapped.
path('<int:country_id>/<int:schools_id>/', views.schools, name='schools'),
path('<int:country_id>/', views.country, name='country'),
]
The 'schools' url needs two (2) arguments. You only pass one (1). In this case: schools.id
Django only finds a reverse match if you pass the correct amount of arguments. In this case, you should pass a country id AND a school id.
E.g. {% url 'schools' country_id=country.id schools_id=schools.id %} if you also have a country variable.
EDIT: '('',)' in your error message don't really look like integers. Are you sure the template variables exists and are integers?
Related
I am trying to get all the post, posted in the same category. So my url looking like this, '..../category/Sports' where sports is a category. But if I enter this url, I got page, not found. I have also a html file called category. I also made makemigrations and migrate a several times
My views.py file:
from .models import Post, Category
..............
def CatView(request, cats):
posts = Post.objects.filter(category=cats)
return render(request,'category.html',{"cats":cats, 'posts':posts})
urls.py file:
from django.urls import path
from .views import *
urlpatterns = [
path('',HomeView.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article_detail'),
path('add-post/', Addblogview.as_view(), name='add_post'),
path('add-category/', AddCategoryview.as_view(), name='add_category'),
path('article/edit/<int:pk>', UpdatethePost.as_view(), name='add_task'),
path('article/delete/<int:pk>', DeleteThePost.as_view(), name='delete_task'),
path('category/<int:cats>', CatView, name='category'),
]
If I change <str:cats> I ended up with ValueError Field 'id' expected a number but got 'Sports'
My models.py file:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import datetime, date
class Category(models.Model):
name = models.CharField(max_length=255, default='uncategorized')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('article_detail',args=str(self.id))
class Post(models.Model):
title = models.CharField(max_length=255)
title_tag=models.CharField(max_length=255)
author = models.ForeignKey(User,on_delete=models.CASCADE)
body = models.TextField()
post_date = models.DateField(auto_now_add= True)
category = models.ForeignKey(Category,on_delete=models.CASCADE)
def __str__(self):
return self.title + "|" + str(self.author)
def get_absolute_url(self):
return reverse('article_detail',args=str(self.id))
My category.html:
{{cats}}
You haven't set a primary key for Category, so the primary key becomes the numeric ID of the row, and the ForeignKey in Post needs to match that. You really want to set primary_key=True when you create the name field in Category.
Maybe you should just add a slash to the end of your URL in urls.py and try again? :)
this is my viewset:
class PollViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Poll.objects.all()
serializer_class = PollSerializer()
def get_queryset(self):
country = self.kwargs.get('pk', None)
if country is not None:
django_countries.Countries.name(country)
return self.queryset.filter(personality__country__name=country)
else:
country = self.request.user.preferred_country
return self.queryset.filter(personality__country=country)
model.py :
from django_countries.fields import CountryField
class Personality(models.Model):
name = models.CharField(max_length=100)
bio = models.TextField()
age = models.IntegerField()
class Gender(models.TextChoices):
MALE = 'MALE', _('Male')
FEMALE = 'FEMALE', _('Female')
OTHER = 'OTHER', _('Other')
gender = models.CharField(
max_length=6,
choices=Gender.choices,
default=Gender.MALE,
)
country = CountryField(null=True)
picture = models.ImageField(upload_to='uploads/profile_images/%Y/%m/%d')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Poll(RulesModel):
personality = models.OneToOneField(Personality, related_name='polls', on_delete=models.CASCADE)
start_date = models.DateTimeField(null=True)
end_date = models.DateTimeField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return 'poll#' + str(self.id) + ' ' + self.personality.name
Urls.py
from django.conf.urls.static import static
from django.urls import path, include
from liderate import settings
from .views import PollViewSet, PersonalityViewSet, PollListViewSet
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'polls', PollViewSet)
router.register(r'polls-list', PollListViewSet)
router.register(r'personalities', PersonalityViewSet)
urlpatterns = [
path('', include(router.urls)),
]
here it raises exception that "Unsupported lookup 'name' for CountryField or join on the field not permitted."
this is raised in the if condition (else condition works perfectly fine). is there any other way of filtering the query set based on the country's name
i actually want to view only the polls related to country passed as a param in the get url
I had a field named location_countries in my project model based on CountryField. It was a multiselect and I needed to create a search based on country name or any other information available in project's other fields. conventional ways e.g "filter(fieldname__icontains) or Q(fieldname__country__name) etc failed. After a lot of trouble, search and thinking, I finally devised a workaround that is working as I intended. Now by giving any keywords for example "samo" in my search field it returns all projects based in "American Samoa" or "afghan" and it retruns all projects based in "Afghanistan". Hope This helps you also. Search field in normal html input tag named "searchTxt". to avoid duplication i first converted result to set and then back to list.
def viewProjects(request):
if request.user.is_authenticated:
if 'searchTxt' in request.GET:
qry = request.GET['searchTxt']
countries_list = []
pros = Project.objects.all()
for pro in pros:
for i in pro.location_countries:
if qry.lower() in i.name.lower():
countries_list.append(pro.project_heading)
res=Project.objects.filter(project_heading__in=countries_list)
projs = Project.objects.filter(
Q(project_id__icontains=qry)|
Q(project_heading__icontains=qry) |
Q(project_description__icontains=qry)|
Q(sla_type__icontains=qry)|
Q(project_type__icontains=qry)|
Q(project_priority__icontains=qry)|
Q(location_countries__exact=qry)|
Q(location_cities__icontains=qry)|
Q(project_manager__username__icontains=qry)|
Q(escalation_manager__username__icontains=qry)
)
project = list(chain(res, projs))
prj = set(project)
projects=list(prj)
context = { 'projects':projects }
return render(request, 'admin_view_projects.html', context)
else:
projects = Project.objects.all()
context = { 'projects':projects }
return render(request, 'admin_view_projects.html', context)
else:
return redirect('index')
I have two models - the Company and Department. The Company can have many Departments - this is all connected with Foreign Key and works as expected. I have URLs and templates/views nicely setup and I can add the Company and then I can add Depratments to it. I am also able to access and create new Departments and assign them to the Company.
To see, say 5 last companies and last 5 Departments I have in the system I use this:
class IndexView(generic.ListView):
model = Company
template_name = 'company/index.html'
context_object_name = 'latest_company_list'
def get_queryset(self):
"""Return the last five created companies."""
return Company.objects.order_by('company_name')[:5]
class DeptIndexView(generic.ListView):
model = Department
template_name = 'department/index.html'
context_object_name = 'latest_department_list'
def get_queryset(self):
"""Return the last five created companies."""
return Department.objects.order_by('dept_name')[:5]
And here are the models from models.py
class Company(models.Model):
company_name = models.CharField(max_length=200)
company_dba = models.CharField(max_length=200)
class Meta:
verbose_name_plural = "companies"
def __str__(self):
return self.company_name
# on submit click on the company entry page, it redirects to the url below.
def get_absolute_url(self):
return reverse('company:index')
class Department(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
dept_name = models.CharField(max_length=200)
dept_code = models.IntegerField(default=0)
def __str__(self):
return self.dept_name
# on submit click on the department entry page, it redirects to the url below.
def get_absolute_url(self):
return reverse('company:index')
My urls.py file looks like this
app_name = 'company'
urlpatterns = [
# Company management views
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('add/', views.CompanyEntry.as_view(), name='add'),
path('update/<int:pk>/', views.CompanyUpdate.as_view(), name='update'),
path('delete/<int:pk>/', views.CompanyDelete.as_view(), name='delete'),
#Department management views
path('<int:pk>/department/', views.DeptIndexView.as_view(), name='dept_index'),
path('<int:pk>/department/add/', views.DeptEntry.as_view(), name='dept_add'),
path('<int:pk>/department/<int:fk>/', views.DeptDetailView, name='dept_detail'),
]
The issue here is that I don't know how to configure URL/path so that I can access details about one single Department.
I am trying to get something like http://127.0.0.1:8000/company/1/department/2/ where 2 is the id of the Department model.
And that last line in the code above doesn't seem to be working.
Instead, I am getting this as an error:
TypeError at /company/1/department/2/
init() takes 1 positional argument but 2 were given
Request Method: GET
Request URL: http://127.0.0.1:8000/company/1/department/2/
Django Version: 2.2.4
Exception Type: TypeError
Exception Value:
init() takes 1 positional argument but 2 were given
Exception Location: /Users/ABC/DjangoHR/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response, line 113
I figured it out - I missed .as_view()
path('<int:pk>/department/<int:fk>/', views.DeptDetailView.as_view(), name='dept_detail'),
Thank you all for help and comments!
I have built a guide website.
Each guide is made of steps.
Each step is made of tasks.
To go the next step, you need to complete the task and then to the next, until there are no more steps.
Example views and URL:
/1 should show you guide1
/1/3 should show the step3 of guide1
/1/3/5 should show task5 of step3 in guide1
I want the URLs to be like this: /1/3/6 (guide1/step3/task6)
I got it to work when I go to /1. Then it shows the view of the guide.
But when I go to /1/1 or 1/1/1 I get a 404 error saying that the guide does not exist.
I need help. Here is my code:
Urls.py for app
urlpatterns = [
url(r'(?P<guide_id>[0-9]+)/$', views.taskoftheday, name="taskoftheday"),
url(r'(?P<guide_id>[0-9]+)/(?P<step.sequence_num>[0-9]+)/$', views.taskoftheday_step, name="taskoftheday_step"),
url(r'(?P<guide_id>[0-9]+)/(?P<step.sequence_num>[0-9]+)/(?P<task.sequence_num>[0-9]+)/$', views.taskoftheday_task, name="taskoftheday_task"),
]
urls.py for project
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('registration.urls')),
url(r'^taskoftheday/', include('taskoftheday.urls')),
url(r'^', include('taskoftheday.urls')),
url(r'^analytics/', include('analytics.urls')),
url(r'^progress/', include('progress.urls')),
url(r'^goals/', include('goals.urls')),
url(r'^registration/', include('registration.urls')),
url(r'thanks/', views.thanks),
url(r'thanks_again/', views.thanks_again),
url(r'^$', views.landing_page),
]
models.py
class Guide(models.Model):
name = models.CharField(max_length=200)
guide_category = models.CharField(max_length=70)
guide_why = models.TextField()
guide_how = models.TextField()
is_complete = models.BooleanField(default=False)
def __unicode__(self):
return self.name
class Step(models.Model):
guide = models.ForeignKey(Guide, on_delete=models.CASCADE)
sequence_number = models.PositiveIntegerField(default=1)
name = models.CharField(max_length=10)
is_complete = models.BooleanField(default=False)
class Meta:
unique_together = ("guide", "sequence_number")
def __unicode__(self):
return self.name
class Task(models.Model):
step = models.ForeignKey(Step, on_delete=models.CASCADE)
sequence_number = models.PositiveIntegerField(default=1)
name = models.CharField(max_length=10)
task_img = models.ImageField()
task_task = models.TextField()
task_description = models.TextField()
is_complete = models.BooleanField(default=False)
class Meta:
unique_together = ("step", "sequence_number")
def __unicode__(self):
return self.name
views.py
def taskoftheday(request, guide_id):
try:
guide = Guide.objects.get(pk=guide_id)
except Guide.DoesNotExist:
raise Http404("Guide does not exist")
return render(request, 'taskoftheday/taskoftheday.html', {'guide': guide})
def taskoftheday_step(request, guide_id, step_id):
try:
guide = Guide.objects.get(pk=guide_id)
step = Step.objects.get(guide=guide, sequence_number=step_id)
except Step.DoesNotExist:
raise Http404("Step does not exist")
return render(request, 'taskoftheday/taskoftheday_step.html', {'step': step})
def taskoftheday_task(request, guide_id, step_id, task_id):
try:
guide = Guide.objects.get(pk=guide_id)
step = Step.objects.get(guide=guide, sequence_number=step_id)
task = Task.objects.get(step=step, sequence_number=task_id)
except Task.DoesNotExist:
raise Http404("Task does not exist")
return render(request, 'taskoftheday/taskoftheday_task.html', {'task': task})
models.py
class Match(models.Model):
match_name = models.CharField(max_length=100)
player = models.CharField(max_length=100, choices=match_game, default=2)
time_start = models.DateTimeField(blank=True, default=None, null=True)
match_finished = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse('match:details', kwargs={'pk': self.pk})
def __str__(self):
return self.match_name
class PlayerSignup(models.Model):
current_player = models.ForeignKey(User)
signup = models.ForeignKey(Match)
urls.py
url(r'^create/add/$', views.MatchCreate.as_view(), name='match-add'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(template_name = 'match/bracket_detail.html'), name='details'),
url(r'^search/$', views.IndexView.as_view(template_name = 'match/bracket.html'), name='search'),
url(r'(?P<pk>[0-9]+)/$', views.PlayerSign, name='join')
views.py
def PlayerSign(request):
model = PlayerSignup.objects.all()
match = Match.objects.get(pk=Match.pk)
joinmatch = PlayerSignup(current_player=request.user, signup=match)
joinmatch.save()
return render(request, 'match/bracket_detail.html', {'model': model })
template
Join Match
when a person clicks on the 'Join Match' link i would like it to create a PlayerSignup model and link it to the current match that they are on.
when i click the Join Match link nothing happens, no new model, no error
First, try to edit this statement
def PlayerSign(request):
...
match = Match.objects.get(pk=Match.pk)
to
def PlayerSign(request, pk):
...
match = Match.objects.get(pk=pk)
Because there is an request parameter in URL named pk, you should pass this parameter to the query method.
Second, review your url define
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(template_name = 'match/bracket_detail.html'), name='details'),
url(r'(?P<pk>[0-9]+)/$', views.PlayerSign, name='join')
Change to
url(r'^match_detail/(?P<pk>[0-9]+)/$', views.DetailView.as_view(template_name = 'match/bracket_detail.html'), name='details'),
url(r'^player_detail/(?P<pk>[0-9]+)/$', views.PlayerSign, name='join')