baqyoteto
baqyoteto

Reputation: 344

Models not rendering in Django templates

I'm trying to pass an abstract model to an inclusion tag like via takes_context=True. The abstract model contains choices for a model field. I want to pass the abstract model instead of hardcoding the choices in the template to stay DRY. While debugging I realized that the template isn't receiving the model as expected.

# urls.py
...
urlpatterns = [
    path('', IndexView.as_view(), name='index'),
]
# views.py
...
class IndexView(TemplateView):
    """Home Page"""
    template_name = 'index.html'

    def get_context_data(self, **kwargs):
        kwargs['model'] = MyModel
        return super(IndexView, self).get_context_data(**kwargs)

...
# index.html
{{model}}

The above renders nothing in the browser. When I change the variable to a string, the context renders as expected.

# views.py
...
class IndexView(BaseSearchBarMixin, TemplateView):
    """Home Page"""
    template_name = 'index.html'

    def get_context_data(self, **kwargs):
        kwargs['model'] = 'testing 123'
        return super(IndexView, self).get_context_data(**kwargs)

...
# index.html
{{model}}  # fixed typo
# browser
testing 123

I have a feeling I'm doing something stupid but don't know what

EDIT: Per the accepted answer, passing classes to templates isn't possible. Since the class I wanted to pass is an abstract model, there are cases where MyModel.objects.first() could return an empty queryset. I ended up making a custom ContextMixin that added the choices to my class based views.

# myapp.models.users.py

class MyModel(models.Model):
    """shared fields and functions for MyModel models"""
    class Meta:
        abstract = True

    DOWN_VOTE = 'DOWN'
    UP_VOTE = 'UP'
    VOTE_CHOICES = [
        (DOWN_VOTE, 'Down vote'),
        (UP_VOTE, 'Up vote'),
    ]
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    vote = models.CharField(choices=VOTE_CHOICES, default=UP_VOTE, max_length=255)
# views.py
...
class MyModelChoicesContextMixin(ContextMixin):
    """add choices from abstract model to context"""
    def get_context_data(self, **kwargs):
        """add choices from abstract model to context"""
        context = super(MyModelChoicesContextMixin, self).get_context_data(**kwargs)
        context['user_DOWN_vote'] = MyModel.DOWN_VOTE
        context['user_UP_vote'] = MyModel.UP_VOTE
        return context


class IndexView(MyModelChoicesContextMixin, BaseSearchBarMixin, TemplateView):
    """Home Page"""
    template_name = 'index.html'

Upvotes: 0

Views: 58

Answers (2)

the4thv
the4thv

Reputation: 591

You are passing in a class, not an instance of the class or a queryset, try:

kwargs['model'] = MyModel.objects.first()

(for example - to get the first).

You can't use the class in the template.

Upvotes: 1

Muhammad Faizan Fareed
Muhammad Faizan Fareed

Reputation: 3758

In kwargs you are passing keyword 'model' but in template you are using 'Mymodel' keyword that's why empty template is showing.

2nd thing display model fields like model.field_name.

Upvotes: 0

Related Questions