Django Querying Self-referential Many-To-Many relations - python

I am trying to get a list of all manuscripts in my db, print out the shelfmarks for each of them and in case that they are linked to other manuscripts also print out the shelfmarks of those manuscripts.
Here is what my models look like:
class MSS(models.Model):
shelfmark = models.CharField(max_length=50)
MSSLink = models.ManyToManyField('self',through='MSSLink',symmetrical=False)
[...]
class MSSLink(models.Model):
link1 = models.ForeignKey('MSS', related_name='First_MSS')
link2 = models.ForeignKey('MSS', related_name='Second_MSS')
[...]
Here is the code in views.py
def show_all_MSS(request):
all_MSS = MSS.objects.select_related().all() # get all MSS
t = loader.get_template('list.html')
c = Context({'all_MSS': all_MSS, })
return HttpResponse(t.render(c))
The question is then what to do in my template. I thought about doing something like this, but I don't know how I can test whether the current MS in the for-loop has been linked to another MS and if so how to display those shelfmarks:
{% if all_MSS %}
<ul>
{% for i in all_MSS %}
<li>{{ i.shelfmark }}</li>
{% if i.MSSLink %}
<p>This MS is linked to the following MSS: {{ i.MSSLink.link1 }}</p>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No MSS found</p>
{% endif %}

Your models are a bit complicated - you can probably get rid of MSSLink:
class MSS(models.Model):
shelfmark = models.CharField(max_length=50)
links = models.ManyToManyField('self', symmetrical=False, blank=True)
def __unicode__(self):
return self.shelfmark
and add this to your template:
{% if i.links.all %}
<ul>
{% for l in i.links.all %}
<li>{{ l.shelfmark }}</li>
{% endfor %}
</ul>
{% endif %}

Related

The 'Thumbnail' attribute has no file associated with it. Django {% if %} {% else%} {% endif %}

The 'Thumbnail' attribute has no file associated with it.
I have tried Django {% if %} {% else %} {% endif %} in my HTML list and it works on the page, but when I do the same for a detailview HTML it doesn't work and returns "The 'Thumbnail' attribute has no file associated with it."
** Models.py **
class Article(models.Model):
Title = models.CharField(max_length=150)
Thumbnail = models.ImageField(blank=True, null=True)
Author = models.ForeignKey(Author, on_delete=models.CASCADE)
Content = QuillField()
Date = models.DateField(auto_now_add=True)
slug = AutoSlugField(populate_from='Title')
** Views.py**
class ArticlesDetailView(DetailView):
model = Article
template_name = 'articles_app/articles_detail.html'
def get_context_data(self, **kwargs):
latest = Article.objects.order_by('-id')[0:3]
context = super().get_context_data(**kwargs)
context['latest'] = latest
return context
** HTML - List (articles_list.html) ** It works perfectly fine here!!!
<img src=" {% if articles.Thumbnail %}
{{ articles.Thumbnail.url }}
{% else %}
{% static 'img/add-ons/article_thumbnail_default.jpg' %}
{% endif %} " alt="..." class="card-img-top">
** HTML - Detail (articles_detail.html) ** It doesn't work here.
{% for obj in latest %}
<img src="{% if obj.Thumbnail %}
{{ obj.Thumbnail.url }}
{% else %}
{% static 'img/add-ons/article_thumbnail_default.jpg' %}
{% endif %} " alt="..." class="card-img-top">
{% endfor %}
What am I doing wrong? Please help!
try object.Thumbnail instead of obj.Thumbnail, I think that will solve your problem.

Displaying ManyToManyField on Django Page [duplicate]

I've got these models in my Django project:
class Area(models.Model):
name = models.CharField(max_length=100, primary_key=True)
def __unicode__(self):
return self.name
class Place(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100, primary_key=True)
area = models.ManyToManyField(Area,related_name='area')
How can I show the Place's area name(s) in my template? Currently I have:
{% for place in places %}
Name: {{ place.name }}, Area: {{ place.area}}
{% endfor %}
which gives:
Area: <django.db.models.fields.related.ManyRelatedManager object at 0x10435a3d0>
And {{ place.area}} is just blank. Can anyone help?
Use place.area.all in the template
http://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships
{% for place in places %}
Name: {{ place.name }}<br/>
Area: <br/>{% for area in place.area.all %}{{ area }}<br/>{% endfor %}
{% endfor %}
You can use the existing join template tag.
https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#join
Here's the code
{% for place in places %}
Name: {{ place.name }}, Area: {{ place.area.all|join:", " }}
{% endfor %}
What does your view code look like?
Here's one way you can return the related models:
from myapp.models import Area, Place
def detail(request, place_id):
place = Place.objects.get(pk=place_id)
areas = place.area.all()
return render_to_response('detail.html', {
"place": place,
"areas": areas,
})
This example is just for illustration; you'd want to include error-handling code.
Your template might look something like this:
<h3>{{ place }}</h3>
{% if areas %}
<ul>
{% for area in areas %}
<li>{{ area.name }}</li>
{% endfor %}
</ul>
{% endif %}
For show only ManyToMany field:
{% for place in places.area.all %}
{{ place.name }}
{% endfor %}

Trying to display a list of youtube videos into django template with django-embed-video

I am trying to embed a list of youtube videos, in which more videos will be added over time, into my django app using django-embed-video. Going after their documentation I did the following:
models.py
from embed_video.fields import EmbedVideoField
class Youtube(models.Model):
video = EmbedVideoField()
slug = models.SlugField(max_length=200, db_index=True, unique=True)
def __str__(self):
return self.video
admin.py
from .models import Youtube
from embed_video.admin import AdminVideoMixin
class YoutubeAdmin(AdminVideoMixin, admin.ModelAdmin):
list_display = ('video', 'slug')
admin.site.register(Youtube, YoutubeAdmin)
views.py
from .models import Youtube
def display_video(request):
videos = Youtube.objects.all()
context = {'videos': videos}
return render (request, 'scienceblog/post/videos.html', context)
videos.html
{% extends "base.html" %}
{% load embed_video_tags %}
{% video item.video 'small' %}
{% block content %}
{% if videos %}
{% for v in videos %}
{{ v }}
{% endfor %}
{% else %}
<p>No videos yet</p>
{% endif %}
{% endblock %}
Everything works perfect in the admin site. The youtube links are added and the videos are displayed. However I am very unsure about the HTML tags. The browser only displays the youtube links as a string when videos.html is rendered. How can I display the videos?
Thanks for the quick answer raratiru! It brought me on the idea to look into the code of the django-embed-video app itself. I fiddled around with it a bit and now it works just how I wanted it to work. The relevant code is:
videos.html
{% load embed_video_tags %}
{% for v in videos %}
{% video v.video as my %}
<iframe width="{{ 480 }}" height="{{ 320 }}" src="{{ my.url }}"
frameborder="0" allowfullscreen></iframe>
{% endvideo %}
{% endfor %}
You need to acquire the EmbedVideoField() which is video according to models.py. Therefore, the loop should read something like:
{% extends "base.html" %}
{% load embed_video_tags %}
{% video item.video 'small' %}
{% block content %}
{% if videos %}
{% for v in videos %}
{{ v.video }}
{% endfor %}
{% else %}
<p>No videos yet</p>
{% endif %}
{% endblock %}
It is possible that the EmbedVideoField() has more attributes that have to be accessed, you have to check the relevant docs. For example, if the embed code is stored in EmbedVideoField().embed_code you can reach it as such:
{% for v in videos %}
{{ v.video.embed_code }}
{% endfor %}

how to categorize sql inputs according to models in django

I want to learn django and I should categorize my sql inputs according to my models.
For example I have some models like this:
class Author(models.Model):
authorName = models.CharField(max_length=30)
def __str__(self):
return self.authorName
class Book(models.Model):
author = models.ForeignKey(Authors, on_delete=models.CASCADE)
bookName = models.CharField(max_length=60)
downloadLink = models.FileField()
downloadCount = models.IntegerField(default=0)
def __str__(self):
return self.bookName
and I want to an output in my .html file like this;
Sherlock Holmes
A Study in Scarlet
The Sign of the Four
The Hound of the Baskervilles
Suzanne Collins
The Hunger Games
Catching Fire
Mockingjay
I tried this code in my html file but it doesn't work
<ul>
{% for author in all_authors %}
<h2>{{ author.authorName }}</h2>
{% for book in all_books %}
{% if book.author == author.authorName %}
<li>{{ book.bookName }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
My output is;
Sherlock Holmes
Suzanne Collins
Here is my view.py file;
def books(request):
return render(request,'../templates/library/library-template.html', {
'all_authors': Author.objects.all(),
'all_books': Book.objects.all(),
})
How can I fix it? Or are there any different solution for fix this?
Thank you.. :)
Your if statement will never be true, you are comparing an object and a string
{% if book.author == author.authorName %}
So you could change this to
{% if book.author == author %}
But this is still wasteful, you can just use the reverse lookup so you won't need the if statement at all
<ul>
{% for author in all_authors %}
<h2>{{ author.authorName }}</h2>
{% for book in author.book_set.all %}
<li>{{ book.bookName }}</li>
{% endfor %}
{% endfor %}
</ul>

Something like publish notes in a webpage

I'm building a site where I publish a notice and it appear in one webpage but my code dosen't return the objects. I post my code then:
Models:
from django.db import models
class Contenidos(models.Model):
title = models.CharField(max_length = 255)
content = models.TextField()
created = models.DateTimeField(auto_now_add=True)
published = models.BooleanField(default=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s' % self.title
Views:
from django.shortcuts import render
from granada.models import Contenidos
def contenidos(request):
contenido_list = Contenidos.objects.all()
return render(request, 'contenidos.html', {'contenido_list' : contenido_list})
contenidos.html
{% extends 'base.html' %}
{% block title %} Contenidos {% endblock %}
{% block content %}
<h2> contenidos </h2>
{% for contenido in contenido_list %}
<h3>
{{ contenido_list.title }}
</h3>
<p>{{ contenido_list.content }}</p>
{% endfor %}
{% endblock %}
You're accessing the wrong object in your loop, contenidos instead of contenido.
{% extends 'base.html' %}
{% block title %} Contenidos {% endblock %}
{% block content %}
<h2> contenidos </h2>
{% for contenido in contenidos %}
<h3>
{{ contenido.title }} {# was contenidos.title #}
</h3>
<p>{{ contenido.content }}</p>
{% endfor %}
{% endblock %}

Categories