I have two Models, reseller and customer. I can generate Tree hierarchy for reseller, But I want to list down Customers under their immediate parent reseller.
models.py
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
# Create your models here.
class Reseller(MPTTModel):
reseller_name = models.CharField(max_length=40)
reseller_email = models.EmailField(max_length=70,blank=True)
reseller_code = models.CharField(max_length=40)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
class MPTTMeta:
order_insertion_by = ['reseller_name']
def __str__(self):
return self.reseller_name
class Customer(models.Model):
customer_name = models.CharField(max_length=40)
customer_email = models.EmailField(max_length=70,blank=True)
customer_code = models.CharField(max_length=40)
reseller = models.ForeignKey(Reseller, on_delete=models.CASCADE, null=True, blank=True, related_name='cust_children')
def __str__(self):
return self.customer_name
This is the view :
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import *
from .forms import *
# Create your views here.
def index(request):
return render(request, 'main/login.html')
def home(request):
resellers = Reseller.objects.all()
customers = Customer.objects.all()
context = { 'resellers' : resellers, 'customers' : customers }
return render(request, 'main/home.html', context)
This the recursetree tag that is been cited in mptt docs.
home.html
{% recursetree resellers %}
<li>
{{ node.reseller_name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
Here is the order I'm aiming to:
reseller1
-reseller2
-customer1
--reseller3
----customer2
The reason it doesn't work is because customers aren't part of the resellers tree, you need to get them manually. Something like this will give you a start:. If customers aren't always at a lead node you'll need to make some changes, though.
{% recursetree resellers %}
<li>
{{ node.reseller_name }}
{% if node.cust_children.all %}
<ul>
{% for customer in node.cust_children.all %}
<li>{{ customer.customer_name }}</li>
{% endfor %}
</ul>
{% endif %}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
Related
How can I render the data in from the model to the html? The way they describe it in the docs doesn´t work for me. Here is what I have:
class Thema(models.Model):
title = models.CharField(max_length=70, help_text="The title of the Post")
publication_date = models.DateField(verbose_name="Date the Post was published.")
text = models.TextField(max_length=5000,default='kein Textinhalt vorahnden')
category = models.ForeignKey(Category, on_delete=models.CASCADE)
bilder = models.ForeignKey(Bilder, on_delete=models.CASCADE)
links = models.ManyToManyField(Link)
files = models.ManyToManyField(File)
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.title
The View:
from .models import Thema
from django.views.generic import TemplateView
class HomePageView(TemplateView):
model = Thema
context_object_name = 'themas'
template_name = "home/home.html"
And the template:
<h2>THEMAS</h2>
<ul>
{% for thema in themas %}
<li>{{ thema.title }}</li>
{% endfor %}
</ul>
How can I render the many to many fields?
thanks for answers
Your template assumes that themas is a list. But themas is actually only one model instance of Thema.
class HomePageView(TemplateView):
model = Thema # model is Thema
context_object_name = 'thema' # 'themas' is missleading --> change to 'thema'
# because this view only passes ONE Thema to the view
template_name = "home/home.html"
<h1>Thema: {{ thema.title }}</h1>
<h3>Links:</h3>
{% for link in thema.links.all %}
<li>{{ link }}</li>
{% endfor %}
<h3>Tags:</h3>
{% for tag in thema.tags.all %}
<li>{{ tag }}</li>
{% endfor %}
I have created a productForArt and albomForArt model
From producForArt I inherit to albomForArt
Making a view based on generic.ListView
And I output it in the template,
Can I access the number Of Pages field in the template
albomForArt models, or in this case Django returns an object of the albomForArt model, but with properties that were inherited from albomForArt?
models
from django.db import models
class productForArt(models.Model):
class Meta:
verbose_name = u'товар'
verbose_name_plural = u'товары'
price = models.IntegerField(verbose_name="цена", default=0)
title = models.CharField(max_length=300, verbose_name="название товара", null=True)
description = models.CharField( max_length=1000,verbose_name="Описание товара", null=True)
type = models.ForeignKey('typeProductForArt', on_delete=models.PROTECT)
def getType(self):
return self.type
def __str__(self):
return str(self.title) + ' по цене' + str(self.price) + ' шт'
class albomForArt(productForArt):
numberOfPages = models.IntegerField(default=10,verbose_name="количество станиц" )
class typeProductForArt(models.Model):
title = models.CharField(max_length=200, default="none")
def __str__(self):
return self.title
vievs
from django.views import View, generic
from .models import productForArt
class startPage(generic.ListView):
model = productForArt
template_name = "startPage.html"
context_object_name = "productForArt_list"
queryset = productForArt.objects.all()[:20]
templates
{% if productForArt_list %}
<section class="productsStartpage">
{% for productForArt in object_list %}
<article class="productForArtStartpage">
<h1>{{productForArt.title}}</h1>
<p>{{productForArt.description}}</p>
{% endif %}
</article>
{% endfor %}
</section>
{% else %}
<p>товара нету</p>
{% endif %}
You can use One-to-one relationships
class albomForArt(productForArt):
product_for_art = models.OneToOneField(productForArt, on_delete=models.CASCADE)
numberOfPages = models.IntegerField(default=10,verbose_name="количество станиц" )
Then in Template
{% if productForArt_list %}
<section class="productsStartpage">
{% for productForArt in object_list %}
<article class="productForArtStartpage">
<h1>{{productForArt.product_for_art.title}}</h1>
<p>{{productForArt.product_for_art.description}}</p>
{% endif %}
</article>
{% endfor %}
</section> {% else %} <p>товара нету</p>{% endif %}
I am doing a training project and have encountered a problem. I try to display the "events" block and the "news" block on the main page, but when I run the loop cycle, only one block is displayed, and the second is not displayed. Explain who knows what I'm doing wrong. I have been solving this problem for three days now. Thanks in advance who will respond to help
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% if post %}
{% for post in post %}
{{ post.title }}
{% endfor %}
{% else %}
<p>У вас нет материала</p>
{% endif %}
{% if event %}
{% for event in event %}
{{ event.name }}
{% endfor %}
{% else %}
<p>У вас нет материала</p>
{% endif %}
</body>
</html>
Views:
from django.shortcuts import get_object_or_404, render
from django.views.generic.base import View
from .models import Blog, Event
# Create your views here.
class EventView(View):
def get(self, request):
event = Event.objects.all()
return render(request, "home/home_list.html", {"event": event})
class BlogView(View):
def get(self, request):
post = Blog.objects.all()
return render(request, "home/home_list.html", {"post": post})
Urls:
from django.urls import path
from . import views
urlpatterns = [
path("", views.EventView.as_view()),
path("", views.BlogView.as_view())
]
Models:
from django.db import models
from datetime import date
# Create your models here.
class Blog(models.Model):
"""Новости"""
title = models.CharField("Заголовок", max_length=100)
description = models.TextField("Описание")
descriptionTwo = models.TextField("Описание (второй абзац)", blank=True, default="")
blockquote = models.TextField("Цитата", blank=True, default="")
short = models.TextField("Краткое описание", max_length=300)
poster = models.ImageField("Изображение", upload_to="post/")
prewiew = models.ImageField("Превью", upload_to="post/")
dataPost = models.DateField("Дата публикации", default=date.today)
url = models.SlugField(max_length=160, unique=True, blank=True)
draft = models.BooleanField("Черновик", default=False)
def __str__(self):
return self.title
class Meta:
verbose_name = "Новости"
verbose_name_plural = "Новости"
class Event(models.Model):
"""События"""
name = models.CharField("Заголовок", max_length=100)
adress = models.TextField("Адрес")
description = models.TextField("Описание")
short = models.TextField("Краткое описание")
phone = models.TextField("Контактный номер телефона")
email = models.EmailField()
image = models.ImageField("Изображение", upload_to="event/")
dataStart = models.DateField("Дата старта", default=date.today)
def __str__(self):
return self.name
class Meta:
verbose_name = "Событие"
verbose_name_plural = "События"
Admin:
from django.contrib import admin
from .models import Blog, Event
# Register your models here.
admin.site.register(Event)
admin.site.register(Blog)
Views
You need one view with a context containing both the events ant the posts
class EventView(View):
def get(self, request):
events = Event.objects.all()
posts = Blog.objects.all()
return render(request, "home/home_list.html", {"events": events, "posts":posts})
Template
In the template loop over both
{% if posts %}
{% for p in posts %}
{{ p.title }}
{% endfor %}
{% else %}
<p>У вас нет материала</p>
{% endif %}
{% if events %}
{% for e in events %}
{{ e.name }}
{% endfor %}
{% else %}
<p>У вас нет материала</p>
{% endif %}
In for each loop, use different name for the "loop Object" and the list/dictionary on which you are looping. LIKE THIS:
{% if post %}
{% for p in post %}
{{ p.title }}
{% endfor %}
{% else %}
<p>У вас нет материала</p>
{% endif %}
{% if event %}
{% for e in event %}
{{ e.name }}
{% endfor %}
{% else %}
<p>У вас нет материала</p>
{% endif %}
Did it solve your problem?
I'm trying to display a photographic session with all of it photos, so I have the session name in one model and I have the pictures in
another model linked by a foreign key. I'm not able to display it in
the HTML I'm not sure if I'm using the ListView get_context_data
correctly and I'm certainly sure the the html code is not correct but
I have not found how to do it.
views.py
class SessionPictures(generic.ListView):
model = PostSession
template_name = 'photoadmin/gallery.html'
def get_context_data(self, **kwargs):
context = super(SessionPictures, self).get_context_data(**kwargs)
context['picture'] = Images.objects.all()
return context
models.py
class PostSession(models.Model):
session_name = models.CharField(max_length=25)
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.session_name)
class Images(models.Model):
name = models.ForeignKey(
PostSession, related_name='images', on_delete=models.CASCADE, null=True, blank=True)
picture = models.ImageField(upload_to='pictures')
html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h2>Images</h2>
<ul>
{% for session in object_list %}
<li>{{ session.session_name }}</li>
<ul>
<li>{{session.picture_set.all.url}}</li>
</ul>
{% endfor %}
</ul>
{% endblock %}
I'm expecting this:
Woods
picture1.url
picture2.url
picture3.url
Beach
Picture4.url
picture5.rul
As you already defined related_name="images" in Images model, so, session.images_set attribute won't work with PostSession.
class Images(models.Model):
name = models.ForeignKey(
PostSession,related_name='images', on_delete=models.CASCADE, null=True, blank=True)
Instead, use session.image.all in template(FYI: it returns a queryset, so you need to iterate through it to get the image object):
{% for session in object_list %}
<li>{{ session.session_name }}</li>
<ul>
{% for i in session.images.all %}
<li> i.picture.url </li>
{% endfor %}
</ul>
{% endfor %}
More information on reverse relation can be found in documentation.
I'm new to Django, so thanks for any help.
I have an Article model, and I would like to display related/similar articles by assigning tags to each article.
I've tried making a function/filter in my views.py that inherits from self (that particular article) and filters out the articles with the same tag, but with no success.
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200, blank=True)
thumbnail = models.ImageField(max_length=200, blank=True)
tag = models.CharField(max_length=200, blank=True)
from .models import Article
class ArticleView(DetailView):
template_name = "article/article.html"
model = Article
def related_articles(self):
tagged = Article.objects.filter(tag=self.tag)
return tagged
{% if articles.objects.all %}
{% for article in article.objects.all|related_articles %}
<div>
<img src="{{ article.thumbnail.url }}">
<span>{{ article.title }}</span>
</div>
{% endfor %}
{% endif %}
So, whenever I try to use this filter I get no results.
I think the related_articles function should be on the model class.
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200, blank=True)
thumbnail = models.ImageField(max_length=200, blank=True)
tag = models.CharField(max_length=200, blank=True)
def related_articles(self):
tagged = Article.objects.filter(tag=self.tag).exclude(pk=self.pk)
Suppose your have a view like this:
def articles(request):
articles = Articles.objects.all()
context = dict(articles=articles)
return render(request, 'app/articles.html', context)
You could have a template like this:
{% if articles|length %}
{% for article in articles %}
<div>
<img src="{{ article.thumbnail.url }}">
<span>{{ article.title }}</span>
{% for related_article in article.related_articles %}
<span>{{ related_article.title }}</span>
{% endfor %}
</div>
{% endfor %}
{% endif %}