Model data not displayed on template - django - python

Short Story: I have made two apps. Properties and Tenants within a django project. First I started rendering data from Property model to property_detail.html template and it works fine, but after I created & migrated the Tenants model, and I try to render data from there to property_detail.html it doesn't work. Yet it doesn't give me any errors. It just doesn't show up.
Models.py
import arrow
import uuid
from django.db import models
from django_countries.fields import CountryField
from django.urls import reverse
from django.conf import settings
from properties.models import Property
class Tenant(models.Model):
id = models.UUIDField( # new
primary_key=True,
default=uuid.uuid4,
editable=False)
full_name = models.CharField("Full Name", max_length=255, null=True)
email = models.EmailField(unique=True, null=True)
phone = models.CharField(max_length=20, unique=True, null=True)
description = models.TextField("Description", blank=True)
country_of_origin = CountryField("Country of Origin", blank=True)
creator = models.ForeignKey(
settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
created_on = models.DateTimeField(
"Created on", auto_now_add=True, null=True)
is_active = models.BooleanField(default=False)
apartment = models.ForeignKey(
Property,
on_delete=models.CASCADE,
related_name='reviews',
)
rent_tenant = models.CharField(
"Rent he/she pays", max_length=10, blank=True)
def __str__(self):
return self.full_name
def get_absolute_url(self):
""""Return absolute URL to the Contact Detail page."""
return reverse('tenant_detail', kwargs={'pk': str(self.pk)})
urls.py
from django.urls import path
from .views import TenantListView, TenantDetailView
urlpatterns = [
path('', TenantListView.as_view(), name='tenant_list'),
path('<uuid:pk>', TenantDetailView.as_view(), name='tenant_detail'), # new
]
views.py
from django.views.generic import ListView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin # new
from .models import Tenant
class TenantListView(LoginRequiredMixin, ListView): # new
model = Tenant
context_object_name = 'tenant_list'
template_name = 'tenants/tenant_list.html'
login_url = 'account_login' # new
class TenantDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): # new
model = Tenant
context_object_name = 'tenant'
template_name = 'tenants/tenant_detail.html'
login_url = 'account_login' # new
permission_required = 'books.special_status' # new
and here is the html template section where I need it to be rendered.
<li class="list-group-item">
{% if tenant.full_name %}
<b>Layout</b> <a class="float-right">{{ tenant.full_name }}</a>
{% endif %}
</li>
<li class="list-group-item">
{% if property.usable_sqm %}
<b>SQM</b> <a class="float-right">{{ property.usable_sqm }}</a>
{% endif %}
</li>
The other app is EXACTLY the same. Basically I copy-pasted everything from there and then just changed the fileds and renamed all the fields from Property to Tenant (By that I mean all the functions and urls ... ) What seems to be the problem? Because by my logic this should work.

The views.py document you have provided doesn’t have property_details.html template, instead it has tenant templates( you trying to render tenant objects into property template right?). I am not sure how you trying passing tenant model to property template from the code provided.
Why don’t you import tenant model into property views and pass whatever tenant objects you want to the property template?

Related

How can I configure these multiple slugs in my urls and views: Django

I've been trying to configure my urls and views for this password safe app
a site can have many accounts, and to edit an account I plan to use this url config:
home/[sitename]/[accountusername]/edit/. but its bringing errors. How do I go about this?
views.py:
class SiteDetailView(DetailView):
model = Site
template_name = "site_detail.html"
class SiteDeleteView(DeleteView):
model = Site
template_name = "site_delete.html"
success_url = reverse_lazy("home")
class SiteEditView(UpdateView):
model = Site
template_name = "site_edit.html"
fields = ("siteName",)
class AccountDeleteView(DeleteView):
model = Account
template_name = "account_delete.html"
# def get_success_url(self):
# return reverse_lazy("site_detail", kwargs={"slug": self.object.slug})
class AccountEditView(UpdateView):
model = Account
template_name = "account_edit.html"
fields = (
"username",
"password",
)
urls.py:
from django.urls import path
from .views import (
IndexView,
HomePageView,
SiteDetailView,
SiteDeleteView,
AccountDeleteView,
AccountEditView,
SiteEditView,
)
urlpatterns = [
path("home/<slug:slug>/edit/", SiteEditView.as_view(), name="site_edit"),
path(
"home/<slug:slug>/<slug:slug_field>/edit/",
AccountEditView.as_view(),
name="account_edit",
),
path(
"home/<slug:slug>/<slug:slug_field>/delete/",
AccountDeleteView.as_view(),
name="account_delete",
),
path("home/<slug:slug>/delete/", SiteDeleteView.as_view(), name="site_delete"),
path("home/<slug:slug>/", SiteDetailView.as_view(), name="site_detail"),
path("home", HomePageView.as_view(), name="home"),
path("", IndexView.as_view(), name="index"),
]
models.py:
from django.db import models
from django.urls import reverse
from django.conf import settings
from django.template.defaultfilters import slugify
class Site(models.Model):
siteName = models.CharField(max_length=200)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
slug = models.SlugField(null=False, unique=True)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.siteName
def get_absolute_url(self):
return reverse("site_detail", kwargs={"slug": self.slug})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.siteName)
return super().save(*args, **kwargs)
class Account(models.Model):
site_name = models.ForeignKey(Site, on_delete=models.CASCADE)
username = models.CharField(max_length=140)
password = models.CharField(max_length=50)
slug_field = models.SlugField(null=False, unique=True)
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse("home")
def save(self, *args, **kwargs):
if not self.slug_field:
self.slug_field = slugify(self.username)
return super().save(*args, **kwargs)
my site_detail.html:
{% extends 'base.html' %}
{% block content %}
<h2>{{ object.siteName }}</h2>
<hr>
{% for username in object.account_set.all %}
<p>Username: {{ username.username }}</p>
<p>Password: {{ username.password }}</p>
<p><button type="button">Edit account</button>
<button type="button">Delete account</button></p>
<hr>
{% endfor %}
<p><button type="button">Delete site</button>
<button type="button">Edit site</button></p>
{% endblock content %}
The current error I am facing:
raise FieldError(
django.core.exceptions.FieldError: Cannot resolve keyword 'site' into field. Choices are: id, password, site_name, site_name_id, slug_field, username
This is how a detail view looks at url http://127.0.0.1:8000/home/redditcom/
this is how a detail view looks at url http://127.0.0.1:8000/home/redditcom/
For Django to clearly handle the slug, the field name should be named as "slug", so, for your Site model there will be no problem, but, for account model you named it "slug_field", then, you have 2 options:
Change the "slug_field" to just "slug".
Override the slug field in the Account Views so Django takes them as the slug field, like this:
slug_field = "slug_field"
slug_url_kwarg = "slug_field"
You use siteName in your Site model and site_name in your Account model. I'm not sure what code is generating the error since I don't see anything referencing just site in what you posted here, but if you look at the error, you can see from the other fields listed that it's referencing the Account model. So you need to replace site with site_name somewhere.
For me, when doing stuffs like this, you use use a unique slug. You can add a random unique number to the slug by generating it from uuid4, and using a while loop go make sure no slug repeats its self .
Just create a util.py file in your app and write the function to generate a random unique number the add it to your slug in the models

My django generic DetailView doens't show any data

Hello everyone I have just started developing my blog with django but I don't get to display my posts individually. DetailView doesn't work, please help!
here is my url
from django.urls import path
from .views import Home, ArticleDetailView
urlpatterns = [
path('', Home.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article_details'),
]
Here is my view.
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from .models import Article
# Create your views here.
class Home(ListView):
model = Article
template_name = 'home.html'
class ArticleDetailView(DetailView):
model = Article
template_name = 'article_detail_view.html'
My model
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
def __str__(self):
return self.title + '|' + str(self.author)
class Meta:
verbose_name = 'Article'
verbose_name_plural = 'Articles'
Home.html
<h2>Post</h2>
<ul>
{% for post in object_list %}
<li>{{post.title}} by {{ post.author }}</br>
<p>{{post.body}}</p></li>
{% endfor %}
</ul>
article_detail_view.html
<h2>Article Detail View</h2>
<h2>{{post.title}} By {{ post.author }}</h2></br>
<p>{{post.body}}</p>
Thanks for updating the question.
First add the get_absolute_url method to the model as follows:
class Article(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
def __str__(self):
return self.title + '|' + str(self.author)
class Meta:
verbose_name = 'Article'
verbose_name_plural = 'Articles'
def get_absolute_url(self):
return reverse("article_details", kwargs={"pk": self.pk})
In your article_detail_view.html, you can access the article using the article instance:
<h2>Article Detail View</h2>
<h2>{{article.title}} By {{ article.author }}</h2></br>
<p>{{article.body}}</p>
in your article_detail_view.html
you can access the article by: {{object.title}}
you can also specify what to return in template and how you wanna name it by overriding get_context_data
check this
in models.py
class Meta:
managed = True
verbose_name = 'Article'
verbose_name_plural = 'Articles'

How to retrieve data using id or pk in django

I am working on a project but after trying multiple ways I still couldn't find the solution. I need to get the current room on the page so that user can leave room, I am aware that it has to do with making queries or using pk,id. (My 1st question ever, sorry if it is not correct way to ask).
This is the code from Views.py:
def leave_room(request, room):
room = request.GET['room.pk']
room_details = Room.objects.get(name=room)
messages = Messages.objects.filter(room=room_details.pk)
membership = RoomMember.objects.filter(user=request.user, room=messages)
membership.delete()
return redirect("/")
urls.py:
path("leave/<int:pk>/join/", views.leave_room, name="leave_room"),
html:
<a class="btn btn-danger" href="{% url 'leave_room' pk=room.pk %}">Leave Room</a>
models.py:
class Room(models.Model):
name = models.CharField(max_length=100)
about = models.TextField(max_length=500, null=True, blank=True)
creator = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='room_creator')
members = models.ManyToManyField(User, through="RoomMember")
class RoomMember(models.Model):
approved = models.BooleanField(default=False, blank=False)
room = models.ForeignKey(Room, related_name='memberships', on_delete=models.CASCADE)
user = models.ForeignKey(User, related_name='user_groups', on_delete=models.CASCADE)
class Messages(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False)
text = models.CharField(max_length=10000, blank=False, null=False)
date = models.DateTimeField(default=datetime.now)
room = models.ForeignKey(Room, null=True, blank=False, on_delete=models.CASCADE)
Since you have a parameter <int:pk> the primary key of the room is passed through the pk parameter. This thus means that leave_room should be implemented as:
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
#require_POST
#login_required
def leave_room(request, pk):
nitems, __ = RoomMember.objects.filter(
user=request.user, room_id=pk
).delete()
if not nitems:
raise Http404
else:
return redirect('name-of-some-view')
The removal link is thus a mini form to make a POST request to the view:
<form method="post" action="{% url 'leave_room' pk=room.pk %}">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Leave Room</button>
</form>
Note: Section 9 of the HTTP protocol
specifies that requests like GET and HEAD should not have side-effects, so you
should not change entities with such requests. Normally POST, PUT, PATCH, and
DELETE requests are used for this. In that case you make a small <form> that
will trigger a POST request, or you use some AJAX calls.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

How can I order post entries in a Django template

I made my post model where I store all the post info, like the title, the body, the tags an so on. And I linked it to my index template with a for loop:
<!-- Blog Post -->
{% for blog in object_list %}
<div class="card mb-4">
<div class="card-body">
<h4 id="post_title" class="card-title">{{blog.title}}</h2>
<div id="post_body" class="card-text">{{blog.formatted_markdown|safe}}</div>
Read More
</div>
<div class="card-footer text-muted">
<p id="foot_page">{{blog.date}}</p>
<a id="foot_page" href="#">{{blog.author}}</a>
</div>
</div>
{% endfor %}
And when I run my server the post appear on the blog ordered by pub_date ascending, so the new ones appear delow the old ones.
What can I do to make the newest post appear on top?
Here's my Post model class if it's useful:
class Post(models.Model):
title = models.CharField(max_length=255)
body = MarkdownxField()
tags = models.ManyToManyField(Tag)
author = models.CharField(max_length=255, default='Raúl Chirinos')
date = models.DateTimeField(auto_now_add=True, blank=True)
#property
def formatted_markdown(self):
return markdownify(self.body)
def __str__(self):
return self.title
I managed the views within the urls file:
from django.conf.urls import url
from django.urls import include, path
from django.contrib import admin
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from raulchirinos.models import Post
app_name = 'raulchirinos'
urlpatterns = [
url(r'^markdownx/', include('markdownx.urls')),
url(r'^admin/', admin.site.urls, name='admin-site'),
url(r'^$', ListView.as_view(model=Post, template_name='raulchirinos/index.html'), name='index'),
url(r'^details/(?P<pk>[0-9]+)/$', DetailView.as_view(model=Post, template_name='raulchirinos/post_template/post.html'), name='post_details'),
]
Add a meta class to the models and set the sort according to your requirement.
Ex:
class Post(models.Model):
title = models.CharField(max_length=255)
body = MarkdownxField()
tags = models.ManyToManyField(Tag)
author = models.CharField(max_length=255, default='Raúl Chirinos')
date = models.DateTimeField(auto_now_add=True, blank=True)
class Meta:
ordering = ['-date']
#property
def formatted_markdown(self):
return markdownify(self.body)
def __str__(self):
return self.title
You have several options depending on the level where you need the ordering to happen:
Set a Meta subclass to your Post model with the ordering attribute set to order by date descending. See: https://docs.djangoproject.com/en/2.0/ref/models/options/#ordering
class Post(models.Model):
# ...
class Meta:
ordering = ["-date"]
Order the data from the modle in your view before passing it onto the context.
Reverse the for loop in the template.
Of course the best option is probably the first one, since it's likely that you want this ordering in any case when you retrieve multiple Posts.

Showing images on my homepage using the data from my Django Model

Would like to simplely show multiple pictures from my model data that I inputted via the Admin in my template file between the UL tag. I am having trouble rendering the data to show the image. I dont need to route anything in URL.py yet, just need to pollute the images on my homepage first. Can someone please help troubleshoot my issue? Thank you!
Models.py
class Product(models.Model):
name = models.CharField(max_length=254, blank=True, null=True)
description = models.TextField(blank=True, null=True)
color_name = models.CharField(max_length=254, null=True, blank=True)
size_types = models.CharField(max_length=7, null=True, blank=True)
product_price = models.DecimalField(max_digits=9,decimal_places=2)
old_price = models.DecimalField(max_digits=9,decimal_places=2, blank=True,default=0.00) #To show original price if, new price has been added
product_tags = models.CharField(max_length=254, null=True, blank=True, help_text='Comma-delimited set of SEO keywords for product tag area')
novelty = models.CharField(max_length=254, null=True, blank=True)
product_website = models.URLField(max_length=200, null=True, blank=True) #To show other sites to Users, where they can purchase the particular product
image = models.ImageField(upload_to='images/products/main',max_length=100, null=True) #For the argument upload_to, will add to the static folder and generated image will be stored in suing that path specified
slug = models.SlugField(max_length=255, unique=True, help_text='Unique value for product page URL, created from name.')
#This shows when each item was uploaded & by who, to the User
uploaded_by = models.CharField(max_length=254, blank=True, null=True)
uploaded_at = models.DateTimeField(auto_now=True)
#For Admin Purposes, to track and see which if still active by for administrative users only
is_active = models.BooleanField(default=True)
#Foreign Keys & other relationships
designer = models.ForeignKey(Designer)
boutique = models.ForeignKey(Boutique)
category = models.ForeignKey(ProductCategory)
#Metadata
class Meta:
verbose_name = _("Product")
verbose_name_plural = _("Products")
#Helps return something meaningful, to show within the admin interface for easy interaction
def __unicode__(self):
return "{0}".format(self.name)
Forms.py
from __future__ import unicode_literals
from django import forms
from django.forms import extras, ModelForm
from products.models import Designer, Product, ProductCategory, Boutique
class DesignerForm(ModelForm):
class Meta:
model = Designer
class ProductForm(ModelForm):
class Meta:
model = Product
class BoutiqueForm(ModelForm):
class Meta:
model = Boutique
class ProductCategoryForm(ModelForm):
class Meta:
model = ProductCategory
Views.py
from __future__ import unicode_literals
from django.http import Http404, HttpResponseForbidden
from django.shortcuts import redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView
from django.contrib import auth, messages
from django.contrib.sites.models import get_current_site
from django.shortcuts import render
from products.forms import ProductForm, ProductCategoryForm
from products.forms import BoutiqueForm
from products.forms import DesignerForm
from products.models import Boutique, Product, ProductCategory, Designer
class ProductView(DetailView):
model = Product
context_object_name = "task"
Template
{% extends "site_base.html" %}
{% load i18n %}
{% block body %}
<div id="main" role="main">
<ul id="tiles">
<li>
{% for task in products %}
<img src="{{MEDIA_URL}}images/product/main {{task.image.url}}" />
{% endfor %}
</li>
</ul>
</div>
{% endblock %}
There are some odd things in this code.
Firstly, you want to do something with all products. So why are you using a DetailView, which is for selecting and displaying a single item? You need to use a ListView, which will pass a list of products.
Secondly, for some reason you override context_object_name to be "task". But then in the template, you iterate through "products" - a name that is not provided. If you've called the context object "task", that's what you should be iterating over.
Figured out what I was doing wrong!
Apparently I needed to go within my urls and change my already existing TemplateView in the first url tuple:
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic import TemplateView
from django.contrib import admin
urlpatterns = patterns('',
url(r"^$", TemplateView.as_view(template_name="homepage.html"), name="home"),
url(r'^admin/', include(admin.site.urls)),
url(r"^account/", include("account.urls")),
url(r'^likes/', include('likes.urls')),
)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and change the URL tuple to a ListView, to generate the image from my django models.
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic import ListView
from products.models import Product
from django.contrib import admin
urlpatterns = patterns('',
url(r"^$", ListView.as_view(
template_name="homepage.html",
model = Product,
context_object_name = "products",
), name="home"),
url(r'^admin/', include(admin.site.urls)),
url(r"^account/", include("account.urls")),
url(r'^likes/', include('likes.urls')),
)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Categories