user11096002
user11096002

Reputation:

get_queryset() missing 1 required positional argument: 'country_id'

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'

My models

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

My Views

class CityOverview(generic.ListView):
template_name = 'mytemplate.html'

def get_queryset(self, country_id, *args, **kwargs):
    return City.objects.get(pk=country_id)

My Urls

# Albania
path('al', views.CityOverview.as_view(), name='al'),

# Andorra
path('ad', views.CityOverview.as_view(), name='ad'),

# etc. etc.

Upvotes: 0

Views: 1851

Answers (3)

ruddra
ruddra

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

Sergey Pugach
Sergey Pugach

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

Sam
Sam

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

Related Questions