Bootstrap navbar dropdown populated with database entries in Django 2

强颜欢笑 提交于 2019-12-11 15:17:06

问题


I am trying to populate a navbar "dropdown-menu" with individual "dropdown-item"'s populated from data in the sqlite3 DB.

I have something similar working on other pages but I cant get it to work in my navbar.

I am creating a record label, and want the list of artists populated from entries in the DB. I have found one tutorial on doing something similar in php, but doesn't translate, and there doesn't seem to be anything either on youtube or here other than populating form data.

Any help is greatly appreciated, as I have been trying to get it working for about a week now. I know it should be simple, but im missing something.

the app is called "music"

models.py

class Artist(models.Model):
    artist_name = models.CharField(max_length=250, default='')
    artist_logo = models.FileField()
    artist_url = models.URLField(blank=True)

    def __str__(self):
        return self.artist_name

class Release(models.Model):
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
    release_title = models.CharField(max_length=500)
    release_cover = models.FileField()
    release_duration = models.IntegerField()

    def __str__(self):
        return self.release_title

class Track(models.Model):
    release = models.ForeignKey(Release, default='', on_delete=models.CASCADE)
    artist = models.ForeignKey(Artist, default='', on_delete=models.CASCADE)
    track_title = models.CharField(max_length=200)
    track_version = models.CharField(max_length=200)
    track_genre = models.CharField(max_length=100)
    track_duration = models.IntegerField()
    track_number = models.SmallIntegerField()

    class Meta:
        ordering = ["track_number"]

    def __str__(self):
        return self.track_title

views.py

from django.contrib.auth import authenticate, login
from django.views import generic
from django.views.generic import ListView, View
from .models import Artist, Track, Release
from .forms import UserForm

# class IndexView(ListView):
#     template_name = 'music/index.html'

class ReleaseView(generic.ListView):
    template_name = 'music/releaselist.html'
    context_object_name = 'all_releases'

    def get_queryset(self):
        return Release.objects.all()

class ArtistView(generic.ListView):
    model = Artist
    template_name = 'music/artistlist.html'
    context_object_name = 'all_artists'

    def get_queryset(self):
        return Artist.objects.all()

class DetailView(generic.DetailView):
    model = Release
    template_name = 'music/detail.html'

urls.py (Main)

from django.contrib import admin
from django.urls import path, include, re_path
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
# include urls from the music app
    path('music/', include('music.urls'))

urls.py ("music" aka the app urls)

from django.contrib import admin
from django.urls import path, include, re_path
from . import views

# defined the app name in case the same fields are used in other apps
app_name = 'music'

urlpatterns = [
    # no info past music return index EG /music/
    # path('', views.IndexView.as_view(), name='index'),
    # albums/releases
    re_path(r'^release/$', views.ReleaseView.as_view(), name='release'),
    # looking for music page with album id afterwards /music/1
    re_path(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name="detail"),
    re_path(r'^(?P<pk>[0-9]+)/$', views.ArtistView.as_view(), name="artist"),

base.html

      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Artists
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            {% for artist in all_artists %}
                <li><a class="dropdown-item" href="#">{{ artist.artist_id }}</a></li>
            {% endfor %}
        </div>

      </li>

Update: Here is my releases.html which works using similar code, and at the bottom has a test which looks like the for loop is incorrect

{% extends 'music/base.html' %}
{% block title %}KOLD FUZEON: Releases{% endblock %}

{% block body %}

        {% if all_releases %}
            <ul>
                {% for release in all_releases %}
                    <div class="releaseitem">
                        <li><a href="{% url 'music:detail' release.id %}">{{ release.artist }} - {{ release.release_title }}</a></li>
                        <li><a href="{% url 'music:detail' release.id %}"</a><img src="{{ release.release_cover.url }}" style="width: 300px"></li>
                    </div>
                {% endfor %}
            </ul>
        {% else %}
            <h3>We currently dont have any releases yet.</h3>
        {% endif %}


{#basic test for the artist list to be printed to screen#}
            <ul>
                <li>test1</li>
                {% for artist in all_artists %}
                    <li>test2</li>
                {% endfor %}
            </ul>



{% endblock %}

回答1:


I believe there is some problem in the name of the 'key' that you are passing in the context.

In ReleaseView the context object name is all_releases, while you are trying to iterate on "all_artists".

Even if these changes not work, you can always try running your code on a normal view instead of the a generic view and pass the context in the template.




回答2:


In your View.py you have ArtistView where template is artistlist.html and your context is all_artist & you get all objects from db.

Code:

class ArtistView(generic.ListView):
model = Artist
template_name = 'music/artistlist.html'
context_object_name = 'all_artists'

def get_queryset(self):
    return Artist.objects.all()

Now i believe you have a template named artistlist.html. If not create it in templates in which you will use for Loop to render artist list so the code should be this for artistlist.html:

{% extends 'music/base.html' %}
{% block body %}

   <h1>Artists!</h1>

<ul>
{% for artist in all_artists %}
  <li class="artist">
     <h1>
         <a href='/music/{{ artist.id }}'>{{artist.artist_name }}</a>  
     </h1>
  </li>
{% endfor %}
</ul>

</div>

{% endblock %}

You can Render Artist list in Base.html. Using: Context Processor

First Create a file named context_processors.py in your App.Then add this code in that file.

from .models import Artist

def basetest(request):

    hello = Artist.objects.values_list("artist_name", flat=True)
    return {
        'testname': hello
    }

After that, open Settings.py and find context_processors and add the following settings 'yourapp.context_processors.add_variable_to_context'.

Settings.py

TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [],
    'APP_DIRS': True,
    'OPTIONS': {
        'context_processors': [
            'django.template.context_processors.debug',
            'django.template.context_processors.request',
            'django.contrib.auth.context_processors.auth',

            #This one is from my code so set it according to you
            #appname.context_processors.function_name_context_processor.py',

            'blog.context_processors.basetest',

        ],
    },
},
]

After this just place {{ testname }} in your base.html according to your need. it will work. No need for looping just the interpolation will render you a list. Format it according to your need by following this doc



来源:https://stackoverflow.com/questions/51279768/bootstrap-navbar-dropdown-populated-with-database-entries-in-django-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!