Для цикла работает только в одном шаблоне в Django - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь создать образовательный сайт и пытаюсь поместить все категории, использующие циклы for, в выпадающий список в панели навигации. Я положил его в base.html и все другие шаблоны расширяют base.html. Но элементы отображаются только на корневой странице с шаблоном home.html.

Я попытался использовать несколько контекстов для всех сообщений.

base.html:

{% load static %}
<!doctype html>
<html>
<head>
     <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <link rel="stylesheet" type="text/css" href="{% static 'blog/main.css' %}">


        <title>{% block title %}ION{% endblock %}</title>
</head>
<body>
    <header class="site-header">
      <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
        <div class="container">
          <a class="navbar-brand mr-4" href="{% url 'blog-home' %}">ION</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarToggle">
            <div class="navbar-nav mr-auto">
              <a class="nav-item nav-link" href="{% url 'blog-home' %}">Home</a>
              <a class="nav-item nav-link" href="{% url 'post-all' %}">Posts</a>
                    <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Categories</a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                          {% for cate in cat %}
                              <a class="dropdown-item" href="{% url 'category' cate.pk %}">{{ cate.name }}</a>
                          {% endfor %}
                        </div>
                    </li>
              <a class="nav-item nav-link" href="{% url 'blog-about' %}">About</a>
            </div>
            <!-- Navbar Right Side -->
            <div class="navbar-nav">
                {% if user.is_authenticated %}
                    <a class="nav-item nav-link" href="{% url 'post-create' %}">New Post</a>
                    <a class="nav-item nav-link" href="{% url 'profile' %}">Profile</a>
                    <a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
                {% else %}
                    <a class="nav-item nav-link" href="{% url 'login' %}">Login</a>
                    <a class="nav-item nav-link" href="{% url 'register' %}">Register</a>
                {% endif %}
            </div>
          </div>
        </div>
      </nav>
    </header>
    <main role="main" class="container">
      <div class="row">
        <div class="col-md-12">
            {% if messages %}
                {% for message in messages %}
                    <div class="alert alert-{{message.tags}}">
                        {{message}}
                    </div>
                {% endfor %}
            {% endif %}
            {% block content %}{% endblock %}
        </div>
        </div>
      </div>
    </main>
        <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
<!--From snippets navigation, main, and the starter template: https://getbootstrap.com/docs/4.3/getting-started/introduction/

home.html (только место, где он работает):

{% extends "blog/base.html" %}
{% block title %}
ION Home
{% endblock %}
{% block content %}
    <div class="text-center">
        <h1>Home</h1>
    </div>
    <div class="card">
        <img class="card-img-top" src="https://www.litmos.com/wp-content/uploads/2016/06/blog-eLearning-templates.png" alt="Card image cap">
        <div class="card-body">
            <h3 class="card-title text-center">Learning Reimagined</h3>
            <p class="card-text">
                ION is an open network that intends to reimagine learning. Anyone from anywhere can upload courses and help those unable to go to conventional schools or as an aid for education.
                We promote education to the fullest. We believe in equal right for everyone. Students can take the help of ION to study or even make ION their primary study source.
            </p>
        </div>
    </div>

{% endblock %}


views.py:



def home(request):
    context = {
    'posts': Post.objects.all(),
    'cat': Category.objects.all()
    }

    return render(request, 'blog/home.html', context)


def about(request):
    return render(request, 'blog/about.html', {'title':'About'})


class PostListView(ListView):
    model = Post
    template_name = 'blog/posts.html' #<app>/<model>_<viewtype>.html
    context_object_name = 'posts'        #It needs the specifying to loop over just like it did in the context of home
    ordering = ['-date_posted']
    paginate_by = 15


class UserPostListView(ListView):
    model = Post
    template_name = 'blog/user_posts.html' #This is when you click a profile in a post, it takes you to his posts only
    context_object_name = 'posts'
    paginate_by = 15

    def get_queryset(self):#This does so that it takes you to the user posts only if he currently still exists
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        return Post.objects.filter(author=user).order_by('-date_posted')


class PostDetailView(DetailView):
    model = Post


class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    fields = ['title', 'content', 'display', 'category']

    def form_valid(self, form):#This sets the user to be the author of the  blog you're trying to create
        form.instance.author = self.request.user
        return super().form_valid(form)


class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Post
    fields = ['title', 'content', 'display', 'category']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def test_func(self):#This is where only the author can update the post
        post = self.get_object()
        if self.request.user == post.author:
            return True
        return False


class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Post
    success_url = '/'
    def test_func(self):#This is where only the author can update the post
        post = self.get_object()
        if self.request.user == post.author:
            return True
        return False


class CatPostListView(ListView):
    model = Post
    template_name = 'blog/science.html' #This is when you click a profile in a post, it takes you to his posts only
    context_object_name = 'posts'
    paginate_by = 15

    def get_queryset(self):
        return Post.objects.filter(category=2).order_by('-date_posted')

models.py:

class Category(models.Model):
    name = models.CharField(max_length=200)
    slug = models.SlugField()
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.SET_NULL)

    class Meta:
        # enforcing that there can not be two categories under a parent with same slug

        # __str__ method elaborated later in post.  use __unicode__ in place of

        # __str__ if you are using python 2

        unique_together = ('slug', 'parent',)
        verbose_name_plural = "categories"


    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.SET_NULL)
    display = models.TextField(max_length=250)
    date_posted = models.DateTimeField(default=timezone.now)#DON'T USE () HERE Just auto_now_ will show the date of the current day
    author = models.ForeignKey(User, on_delete=models.CASCADE)#No () #This deletes the posts when the user is deleted


    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('post-detail', kwargs={'pk': self.pk})

Iожидать, что категории будут отображаться на всех страницах.

1 Ответ

2 голосов
/ 14 октября 2019

Не будет, потому что на других страницах нет данных категорий (кроме домашней страницы). Так что либо вы можете отправить переменную Category через контекстную переменную cat в каждом представлении, либо вы можете создать custom context processor, например:

def cat_on_all_pages(request):
    return {'cat': Category.objects.all()}

И добавьте его в настройках:

'OPTIONS': {
        'context_processors': [
            'path.to.cat_on_all_pages',
            # other context processors
        ],
     }

Если вы добавите пользовательский контекстный процессор, то вы можете удалить cat из контекста в домашнем представлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...