简体   繁体   中英

query chain of models in Django

I have three models for countries, provinces and cities. one of URLs includes the city name where a post should go. I could get the name of the city through the URL . In view function, I could find the city name and then I could find the country which the city is belong to. Now, I want to list all cities under this country. My question is how can I do this where there is no direct relation between city and country. The city is related to the province and the province related to the country. The list I want should includes all cities inside the country regardless of the province. How can I do this? is there any possible solution rather than make direct relation between city and country model? Note: I could get the country ID through the variable post_city. The country ID for selected city was 3. Therefor, I want all of cities that are under the country that has an ID of 3.
Example: through the URL: I got post_city variable as Los Angeles. Hence, I want all cities in the USA regardless of state of California. Another example, If the post_city variable was London, then, I want all cities in Britain regardless of the province. the models I have are as follow:

class Country(models.Model):
    country_name = models.CharField(max_length=64, unique=True)

    def __str__(self):
        return "%s" % (self.country_name)


class Province(models.Model):
    country_id = models.ForeignKey(Country, on_delete=models.CASCADE)
    province_name = models.CharField(max_length=64)

    def __str__(self):
        return "%s" % (self.province_name)

class City(models.Model):
    province_name = models.ForeignKey(Province, on_delete=models.CASCADE)
    city_name = models.CharField(max_length=64)

    def Country(self):
        return self.province_name.country_id.country_name

the view function as follow:

def list_page(request, post_city):

    p_c = City.objects.filter(city_name__iexact=post_city).get()
    p_p = p_c.province_name
    p_country = p_p.country_id

    pp=City.objects.all()

    print(pp)

    context = {
    'post_city' : post_city,

    'all_p_cities': all_p_cities,

    }
    return render(request, 'path/to/list_page.html', context )

You can chain multiple related model lookups by using several __ parts in the lookup argument name.

cities_in_narnia = City.objects.filter(province_name__country_id__country_name='Narnia')

Read more in the Django docs: Lookups that span relationships

As a side note. There are some naming conventions you can use that will make your code more readable, especially when seeking help from the online community.

class City(models.Model):
    # foreign key fields should be the snake_case or lower case name of the related model class
    province = models.ForeignKey(Province, on_delete=models.CASCADE)

    # there's no need to prefix field or attribute names with the class name 
    # City.city_name is superfluous. City.name is perfectly clear.  
    name = models.CharField(max_length=64)

    # methods and attributes should also be snake_case, only use CapitalCase for class names.
    @property
    def country_name(self):
        return self.province.country.name

If you follow these naming conventions, the filter lookup will also be readable and concise.

cities_in_narnia = City.objects.filter(province__country__name='Narnia')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM