Как получить доступ к объектам модели прародителя, связанной с целевой моделью, через ContentType GenericForeignKey?
Я пытаюсь отфильтровать объекты модели на основе связанной модели прародителя. Они связаны друг с другом через посредническую родительскую модель. Родительская модель связана с дедушкой через ContentType GenericForeignKey. Как я могу получить доступ ко всем объектам целевой модели с общим дедом?
Я пытался использовать GenericRelations для Grandparent, но он не работал, так как он возвращает все родительские объекты, связанные с этой моделью GrandParent. Для этого я должен пройти через наборы запросов. Пожалуйста, проверьте код для деталей:
class State(models.Model):
name = models.CharField(max_length=25)
population = models.PositiveIntegerField()
class UnionTerritory(models.Model):
name = models.CharField(max_length=25)
population = models.PositiveIntegerField()
class District(models.Model):
name = models.CharField(max_length=25)
content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type','object_id')
population = models.PositiveIntegerField()
class Town(models.Model):
name = models.CharField(max_length=25)
district = models.ForeignKey(District,related_name='towns',on_delete=models.CASCADE)
population = models.PositiveIntegerField()
"""Here, District can be connected to State or UnionTerritory but town will always be part of district."""
Теперь, если я выберу любой объект State или UnionTerritory; Я хочу иметь доступ ко всем городам под ним. Я хочу отфильтровать все экземпляры Town, которые имеют один и тот же штат или союзную территорию. Города могут быть связаны с различными районами, которые принадлежат одному и тому же штату или той же территории Союза. Как я могу получить доступ к UnionTerritory или State, связанному с Town, и затем соответствующим образом отфильтровать объекты города. Есть ли способ избежать зацикливания наборов запросов для достижения этой цели?
1 ответ
Я получил ответ на вышеуказанный вопрос, несколько дней назад. Хитрость заключается в том, чтобы включить GenericRelation() в родительскую модель, на которую ContentType Foreignkey может указывать. Я использовал GenericRelation для модели Grandparent. Код выглядит так:
#in models.py:
from django.contrib.contenttypes.fields import GenericRelation
class State(models.Model):
name = models.CharField(max_length=25)
population = models.PositiveIntegerField()
**districts = GenericRelation(District)**
"""this GenericRelation allows us to access all districts under particular state using
state.districts.all() query in case of genericforeignkey reverse relation.
**note:** You can use GenericRelation(**'***module_name*.District**'**) to avoid any circular
import error if District Model lies in another module as it was in my case."""
# same can be done with UnionTerritory Model
class UnionTerritory(models.Model):
name = models.CharField(max_length=25)
population = models.PositiveIntegerField()
districts = GenericRelation(District)
#Other models required no change.
Настоящий трюк идет в views.py. Я не уверен, можно ли это назвать правильным решением или обходным путем, но это дает ожидаемые результаты. Предположим, я хочу получить доступ к списку всех городов в определенном состоянии, код выглядит так:
#in views.py,
from django.shortcuts import get_object_or_404
def state_towns(request,pk):
target_state = get_object_or_404(State,pk=pk)
districts_under_state = target_state.districts.all()
towns_under_state = Town.objects.filter(name__in=districts_under_state).all()
"""first line gives us the state for which we want to retrieve list of towns.
Second line will give us all the districts under that state and third line
will finally filter out all towns those fall under those districts.
Ultimately, giving us all the towns under target state."""
Ребята, я не очень опытен в Джанго. Поэтому, пожалуйста, сообщите мне, если есть какая-либо ошибка в этом коде или есть лучший способ реализовать это. Те, у кого такая же проблема, как и я, это может быть нашим решением, пока не придет лучшее. Благодарю.