简体   繁体   中英

Django Reverse Foreign Key filter

I have what I think is a not-normal case, but as I'm new to this Django filled world I could be wrong.

# Create your models here.
class Country(models.Model):
    name = models.CharField(max_length=100)
    code = models.CharField(max_length=2, default="US")

    def __str__(self):
        return self.name

class State(models.Model):
    name = models.CharField(max_length=100)
    code = models.CharField(max_length=2, default="ME")

    country = models.ForeignKey(Country, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class City(models.Model):
    name = models.CharField(max_length=100)
    state = models.ForeignKey(State, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class ProjectSite(models.Model):
    name = models.CharField(max_length=100)
    city = models.ForeignKey(City, on_delete=models.PROTECT)

    def __str__(self):
        return self.name

The above is a subset of the app models. When I create a list of all of the "ProjectSites", I want to sort them by Country-State-City, preferably in a way ahead of time so I can create dynamic tabs for the above but I'll start small.

If I try:

queryset = ProjectSite.objects.all()

I end up with the ProjectSites, but I can't come up with an elegant way to pass that information to the template, just subsets of each project in each city. I'd like to end up with at least a list like:

  • Country 1
    • State
    • City 1
      • Project A
      • Project B
    • City 2
      • Project C
  • Country 2

Is there a proper way to filter into an ordered area? Ideally I'd have a series of tabs, The first row of Countries, the Second of States in that Country, the third of Cities in that State and below that is all of the Project Sites in that City.

This uses the reverse foreign key relation ( <model>_set ) that is implicitly added to all models with foreign keys to build up your data in a dictionary.

data = {"countries": []}
for country in Country.objects.all():
    country_data = {"country": country, "states": []}

    for state in country.state_set.all():
        state_data = {"state": state, "cities": []}

        for city in state.city_set.all():
            city_data = {"city": city, "projects": []}

            for project in city.project_set.all():
                city_data["projects"].append(project)

            state_data["cities"].append(city_data)

        country_data["states"].append(state_data)

    data["countries"].append(country_data)

Which should return a dictionary roughly like the following:

{
    "countries": [
        {
            "country": <Country object>,
            "states": [
                {
                    "state": <State object>,
                    "cities": [
                        {
                            "city": <City object>,
                            "projects": [
                                <Project object>,
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

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