Zagorodniy Olexiy
Zagorodniy Olexiy

Reputation: 2212

Right way to create urls using inherit class in Django

In Django I have my app where I place information about countries and cities of these countries. This is my model.py file:

class Country(models.Model):
        class Meta:
                verbose_name_plural = u'Countries'

        name = models.CharField(max_length=50)
        slug = models.CharField(max_length=255)
        description = models.TextField(max_length=10000, blank=True)

        def __unicode__(self):
                return self.name

class City(models.Model):
        class Meta:
                verbose_name_plural = u'Cities'

        name = models.CharField(u'city', max_length=200)
        slug = models.CharField(max_length=255, blank=True)
        description = models.TextField(max_length=10000, blank=True)
        country = models.ForeignKey('Country', blank=True, null=True)

        def __unicode__(self):
                return self.name

I have the detail view of my country, in this view there is a list of cities of this country(views.py):

def CountryDetail(request, slug):
        country = get_object_or_404(Country, slug=slug)
        list_cities = City.objects.filter(country=country)
        return render(request, 'country/country.html', {'country':country, 'list_cities':list_cities})

this is my urls.py:

url(r'^(?P<slug>[-_\w]+)/$', views.CountryDetail, name='country'),

I want to create a url of cities which contain a slug of the country and a slug of the city, for example domain.com/spain/barcelona/.

So I created the detail view of the city, and it's looks like this:

def CityDetail(request, cityslug, countryslug):
        country = Country.objects.get(slug=countryslug)
        country_city = City.objects.get(country=country)
        city = get_object_or_404(country_city, slug=cityslug)
        return render(request, 'country/city.html', {'country':country, 'city':city})

Here is my urls.py for city detail:

url(r'^(?P<countryslug>[-_\w]+)/(?P<cityslug>[-_\w]+)$', views.CityDetail, name='resort'),

And this is how it looks like in my html file detail of the country that links to the cities:

<h1>{{country.name}}</h1>
<p>{{country.description}}</p>
<h2>Cities</h2>
{% for city in list_cities %}
   <a href="/{{country.slug}}/{{city.slug}}">
      <p>{{city.name}}</p>
   </a>
{% endfor %}

But when I click on the link of the url of the city, I get error. Object is of type 'City', but must be a Django Model, Manager, or QuerySet

In traceback i see that problem in CityDetail function in views.py file: resort = get_object_or_404(country_city, slug=cityslug).

Hope you can help me with its problem. Thank You.

Upvotes: 1

Views: 337

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599630

Yes, you can't call get_object_or_404 on an actual City object; the things that you can query are models or querysets, not instances. What do you think that call would do?

But actually the underlying problem is before that; your definition of country_city makes no sense. For a start, this is only currently working because you presumably have only one City in the country you're querying. When you have more than one, that line will fail with a MultipleObjectsReturned exception, because get can only return a single object.

You should remove that line altogether, and query the city directly from the country:

country = Country.objects.get(slug=countryslug)
city = get_object_or_404(City, country=country, slug=cityslug)

Upvotes: 1

Related Questions