Помогите с пониманием родовых отношений в Django (и их использование в Admin)

Я создаю CMS для веб-сайта моей компании (я посмотрел на существующие решения Django и хочу что-то намного более тонкое / простое, и которое бы конкретно отвечало нашей ситуации. Плюс, я хотел бы изучить этот материал лучше). У меня проблемы с тем, чтобы обернуть голову вокруг родовых отношений.

у меня есть Page модель, SoftwareModule модель и некоторые другие модели, которые определяют контент на нашем сайте, каждая со своими get_absolute_url() определены. Я хотел бы, чтобы мои пользователи могли назначать любые Page экземпляр списка объектов любого типа, включая другие экземпляры страницы. Этот список станет тем Page подменю экземпляра.

Я пробовал следующее:

class Page(models.Model):
    body = models.TextField()
    links = generic.GenericRelation("LinkedItem")

    @models.permalink
    def get_absolute_url(self):
        # returns the right URL

class LinkedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    title = models.CharField(max_length=100)

    def __unicode__(self):
        return self.title

class SoftwareModule(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

    def __unicode__(self):
        return self.name

    @models.permalink
    def get_absolute_url(self):
        # returns the right URL

Это дает мне общие отношения с API, чтобы сделать page_instance.links.all(), Мы в пути. То, что я не уверен, как осуществить, в форме изменения экземпляра страницы, как создать связь между этой страницей и любым другим существующим объектом в базе данных. Мой желаемый конечный результат: сделать следующее в шаблоне:

<ul>
{% for link in page.links.all %}
    <li><a href='{{ link.content_object.get_absolute_url() }}'>{{ link.title }}</a></li>
{% endfor%}
</ul>

Очевидно, что я чего-то не знаю или неправильно понимаю, но я чувствую себя так, словно иду в ту область, где я не знаю, чего не знаю. Что мне не хватает?

3 ответа

Решение

Как LinkedItem связано с Page? GenericRelation используется для обратных отношений, но в настоящее время нет никаких отношений, поэтому ему нечего сопоставить. Я думаю, это то, что вы ищете в своей модели:

class Page(models.Model):
    body = models.TextField()
    # Moved generic relation to below

class LinkedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    # LinkedItems now relate to a Page model, and we're establishing the relationship
    # by specifying 'links' to keep the syntax you're looking for
    page = models.ForeignKey(Page, related_name='links')

    title = models.CharField(max_length=100)

На заметку, эта модель позволяет LinkedItem относиться к Page, Если вы хотите повторно использовать связанные элементы, вы можете сделать его M2M:

class Page(models.Model):
    body = models.TextField()
    links = models.ManyToManyField(LinkedItem)

class LinkedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    title = models.CharField(max_length=100)

В обоих этих случаях page.links.all() будет всеми связанными элементами.

Кроме того, скобки не используются в синтаксисе шаблона.

Почему вы пытаетесь получить доступ link.content_object внутри page.link.all() список? Внутри этого списка link.content_object всегда будет таким же, как page,

Я не думаю, что я понимаю, что вы пытаетесь сделать здесь, но сейчас этот код должен генерировать список ссылок на текущую страницу с link.title текст.

Можете ли вы объяснить, что вы пытаетесь сделать с LinkedItem?

Я не видел шаблоны доступа к менеджерам напрямую, как при использовании page.links.all

Насколько я понимаю, вам нужно извлечь ссылки в виде списка в представлении и передать его в качестве переменной в шаблон. Также вам нужно заранее разрешить любые внешние ключи, что вы можете сделать с помощью select_related.

то есть.

def some_view(request,*args,**kwargs):

  ...
  page_links = page_instace.links.select_related().all()
  ...

  return render_to_response(
                'the_template.html',
                #extra_context to pass to the template as var_name:value
                {
                    "page_links":page_links,
                },
                # needed if you need access to session variables like user info
                context_instance=RequestContext(request)
            )

тогда в шаблоне...

<ul>
{% for link in page_links %}
    <li><a href='{{ link.content_object.get_absolute_url() }}'>{{ link.title }}</a></li>
{% endfor%}
</ul>

увидеть

Я бы дал больше ссылок, но стек не позволил бы мне.

Другие вопросы по тегам