Reputation:
I have a list of countries they all have there own url www.example.com/al/ for example. But when I want to filter the view per country_id it gives me this error:
get_queryset() missing 1 required positional argument: 'country_id'
class Country(models.Model):
COUNTRY_CHOICES = (
('Albania', 'Albania'),
('Andorra', 'Andorra'),
# etc. etc.
)
name = models.CharField(max_length=255, choices=COUNTRY_CHOICES, default='Netherlands')
def __str__(self):
return self.name
class City(models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
def __str__(self):
return self.name
class CityOverview(generic.ListView):
template_name = 'mytemplate.html'
def get_queryset(self, country_id, *args, **kwargs):
return City.objects.get(pk=country_id)
# Albania
path('al', views.CityOverview.as_view(), name='al'),
# Andorra
path('ad', views.CityOverview.as_view(), name='ad'),
# etc. etc.
Upvotes: 0
Views: 1851
Reputation: 51988
You need to change in several places, lets start from the models:
class Country(models.Model):
COUNTRY_CHOICES = (
('al', 'Albania'), # changing the first value of the touple to country code, which will be stored in DB
('an', 'Andorra'),
# etc. etc.
)
name = models.CharField(max_length=255, choices=COUNTRY_CHOICES, default='nl')
def __str__(self):
return self.name
Now, we need to update the url path to get the value of the country code:
path('<str:country_id>/', views.CityOverview.as_view(), name='city'),
Here we are using str:country_id
, as a dynamic path variable, which will accept string in the path which will be passed to the view as country_id. Meaning, whenevenever you are using for example localhost:8000/al/
, it will pass the value al
as country code to the view.
Finally, getting the value of the country_id
in ListView, and using it in queryset. You can do it like this:
class CityOverview(generic.ListView):
template_name = 'mytemplate.html'
def get_queryset(self, *args, **kwargs):
country_id = self.kwargs.get('country_id')
return City.objects.filter(country__name=country_id)
You need to make sure to return a queryset from the get_queryset
method, not an object.
Upvotes: 2
Reputation: 5669
Just get country_id
from kwargs
. For get_queryset
you need to return queryset
but not a single object. So use filter
instead of get
.
def get_queryset(self, *args, **kwargs):
country_id = self.kwargs['country_id']
return City.objects.filter(country=country_id)
Upvotes: 1
Reputation: 2084
This is happening because your urls.py
is not passing views.py
the positional argument country_id
. You can fix it like so:
path('<str:country_id>', views.CityOverview.as_view())
Now this path will work if the user navigates to both /al and /ad, and the string will be passed to your CityOverview
view as a positional argument. See the Django Docs on the URL Dispatcher for more info.
Upvotes: 2