Display PostgreSQL tables contents in Django - python

EDIT: Fixed it! in models.py I had to add this to point it to the right table as it uses the folder name as a prefix.
class Meta:
managed = False
db_table = 'tablename'
I'm looking to display the contents of a postgres table in Django. Clearly I'm doing something wrong but can not figure out why the data won't show.
Below is what I have so far, the tables headers show but there is no data or any error messages. Checked the table in pgAdmin and there is plenty of data there.
# models.py
from django.db import models
from datetime import datetime
# Create your models here.
class SensorData(models.Model):
device_name = models.TextField()
sensor_type = models.TextField()
sensor_data = models.SmallIntegerField()
sensor_date = models.DateTimeField()
def __str__(self):
return self.device_name
# views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import ListView
from .models import SensorData
# Create your views here.
class ErrorView(ListView):
model = SensorData
template_name = 'errors.html'
# urls.py
from django.urls import path
from .views import ErrorView
urlpatterns = [
path('errors/', ErrorView.as_view(), name='errors'),
path('', ErrorView.as_view(), name='errors'),
]
# errors.html
{% extends 'layout.html' %}
{%block content %}
<section class ='infoContainer'>
<div id = 'sensorInfo'>
<h2> Error Information </h2>
<table id = "deviceTable">
<tr>
<th><strong>Device </strong></th>
<th><strong>Sensor Type </strong></th>
<th><strong>Date</strong></th>
<th><strong>Information</strong></th>
</tr>
{% for error in object_list %}
<tr>
<td> {{error.device_name}} </td>
<td> {{error.sensor_type}} </td>
<td> {{error.sensor_date}} </td>
<td> {{error.sensor_data}} </td>
</tr>
{% endfor %}
</table>
</div>
</section>
{% endblock content %}

Related

Why the ListView not showing data in the template?

I'm working on my first Django project (the final project for codecademy's Django class) and I'm making webpages to show the inventory and menu that a restaurant has. I made the model, view, template, etc. for inventory and it displays the ListView perfectly. I did the same thing for my menu and it doesn't work. The page loads but the table that's supposed to output data is empty.
Any insight on what might be going wrong?
PS I'm new to programming and this is my first stackoverflow post so forgive any formatting errors or other faux pas
## views.py
from django.http import HttpResponse
from django.shortcuts import render
from .models import Inventory, MenuItem, RecipeRequirement, Purchase
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic import ListView
# Create your views here.
def index(request):
return render(request, "index.html")
class InventoryList(ListView):
template_name = "inventory.html"
model = Inventory
class MenuList(ListView):
template_name = "menu.html"
model = MenuItem
Inventory (below) works fine! :)
{% extends './base.html' %}
{% block content %}
<h2>Inventory</h2>
<table id="inventory">
<tr>
<th>Ingredient</th>
<th>Price</th>
<th>Units Available</th>
</tr>
{% for ingredient in inventory_list %}
<tr>
<tr>
<td>{{ ingredient.ingredient_name }}</td>
<td>{{ ingredient.price }}</td>
<td>{{ ingredient.units_avail }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
This one (Menu) is the problematic one :(
{% extends './base.html' %}
{% block content %}
<h2>Menu</h2>
<table id="menu">
<tr>
<th>Item</th>
<th>Price</th>
<th>In Stock?</th>
</tr>
{% for food in menu_list %}
<tr>
<tr>
<td>{{ food.menu_item_name }}</td>
<td>{{ food.price }}</td>
<td>{{ food.available }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Models below
from django.db import models
from django.forms import DateTimeField
# Create your models here.
class Inventory(models.Model):
ingredient_name = models.CharField(max_length=30)
price = models.DecimalField(max_digits=5, decimal_places=2)
units_avail = models.IntegerField()
def __str__(self):
return self.ingredient_name + " avail: " + str(self.units_avail)
class MenuItem(models.Model):
menu_item_name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return self.menu_item_name + " with Price: " + str(self.price)
def available(self):
return all(recipe_req.enough() for recipe_req in self.reciperequirement_set.all())
class RecipeRequirement(models.Model):
ingredient = models.ForeignKey(Inventory, on_delete=models.CASCADE)
menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
quantity = models.IntegerField()
def __str__(self):
return self.ingredient.ingredient_name + " in " + self.menu_item.menu_item_name
def enough(self):
return self.quantity <= self.ingredient.units_avail
class Purchase(models.Model):
menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
timestamp = models.DateTimeField()
def __str__(self):
return self.menu_item.menu_item_name + " at " + self.timestamp
URLs below
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("inventory", views.InventoryList.as_view(), name="inventory_list"),
path("menu", views.MenuList.as_view(), name="menu_list"),
]
I could see one problem, you have one extra <tr> tag open in both the templates just below the loop.
Also think some problem with available method you manually defined in MenuItem model, so I removed it, try without it.
Also I'd recommend you to use context_object_name which is by default object_list so:
views.py
class InventoryList(ListView):
template_name = "inventory.html"
model = Inventory
context_object_name="inventories"
class MenuList(ListView):
template_name = "menu.html"
model = MenuItem
context_object_name="menu_list"
inventory.html template
{% extends './base.html' %}
{% block content %}
<h2>Inventory</h2>
<table id="inventory">
<tr>
<th>Ingredient</th>
<th>Price</th>
<th>Units Available</th>
</tr>
{% for ingredient in inventories %}
<tr>
<td>{{ ingredient.ingredient_name }}</td>
<td>{{ ingredient.price }}</td>
<td>{{ ingredient.units_avail }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
menu.html template
{% extends './base.html' %}
{% block content %}
<h2>Menu</h2>
<table id="menu">
<tr>
<th>Item</th>
<th>Price</th>
<th>In Stock?</th>
</tr>
{% for food in menu_list %}
<tr>
<td>{{ food.menu_item_name }}</td>
<td>{{ food.price }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Note: It's recommended to give / at the end of every route so your urls.py should be:
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("inventory/", views.InventoryList.as_view(), name="inventory_list"),
path("menu/", views.MenuList.as_view(), name="menu_list"),
]
Note: class based views in Django requires their name to be written as model name as prefix and actual view name as suffix, so you may change it to InventoryListView and MenuItemListView from InventoryList and MenuList respectively.
I notice that the RecipeRequirement model Class has the method available. This method calls the method enough from the RecipeRequirement model Class.
One troubleshooting strategy is to disable (comment out) the methods enough and available as they are introducing logic that would prevent display of menu items. In other words, your code appears to read: If we don't have enough ingredients there is no point returning menu items for recipes that we cannot make.
An alternative troubleshooting strategy is to populate the RecipeRequirement table with sufficient ingredients and it should work. Caveat: This answer is untested.
Here's a tip for a newcomer to coding that has served me well in my brief journey into software development. Errors have been my greatest teacher. When there are errors try to reduce as many elements as you can. When you hit a wall like this consider what is essential and comment out the rest. I suggested commenting out the two methods first because they are not required for the tables to display (or for what you report as being central to your question). Once you get the menu items displaying then you can re-introduce those methods one at time.

why I can not link these two pages in my django project

I have 2 models named "developer" and "skill". I made a page for all the developers that have their respective information. Now, I want to make a page that lists all the developers with links that navigate to their respective information page.
The page that shows all the developers' URLs is 'developers/' and its name is "developers". The URL of the second page is 'developers/id' and its name is developer, however it instead navigates to 'developers/developers/id'.
I tried the page that shows the information of a certain developer and it was ok but I have problem with this one cause it won't navigate.
here are my codes :
views.py
from django.shortcuts import render
from .models import Developer, Skill
# Create your views here.
def show_developers(request):
query = Developer.objects.all()
context = {'devs': query}
return render(request, 'users/devs.html', context=context)
def show_single_developer(request, pk):
query = Developer.objects.get(id=pk)
context = {'dev': query}
return render(request, 'users/single_dev.html', context=context)
models.py
from django.db import models
# Create your models here.
class Skill(models.Model):
choices = (
('Beginner', 'Beginner'),
('Junior', 'Junior'),
('Senior', 'Senior'),
)
name = models.CharField(max_length=50)
level = models.CharField(choices=choices, max_length=10)
class Developer(models.Model):
full_name = models.CharField(max_length=50)
username = models.CharField(max_length=50)
intro = models.TextField(blank=True, null=True)
image = models.ImageField()
skills = models.ForeignKey(Skill, on_delete=models.CASCADE)
urls.py
from django.urls import path
from .views import show_developers, show_single_developer
urlpatterns = [
path('developers/', show_developers, name='developers'),
path('developers/<str:pk>/', show_single_developer, name='developer'),
]
devs.html
{% include 'navbar.html' %}
<table>
<tr>
<th>FullName</th>
<th>Username</th>
<th>details</th>
</tr>
{% for dev in devs %}
<tr>
<td>{{dev.full_name}}</td>
<td>{{dev.username}}</td>
<td>View</td>
</tr>
{% endfor %}
</table>
{% include 'footer.html' %}
single_dev.html
{% include 'navbar.html' %}
<h2>{{dev.full_name}}</h2>
<hr>
<h3>Intro</h3>
<h4>{{dev.intro}}</h4>
{% for skill in dev.sills.all %}
<div>
<p>{{skill.name}}</p>
<p>{{skill.level}}</p>
</div>
{% endfor %}
{% include 'footer.html' %}
TraceBack Section
and I add the structures of this app too
Error page

Users can see each others posts. I used #loginrequired decorator but it did not work

I want a logged in user to see only his posts. But in my site user can see all the posts posted by the users.
Here is github link https://github.com/ualmaz/post. You are welcome to clone and check it if you want.
I tried to use #loginrequired decorator. But it was not useful.
my models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import AbstractUser
from PIL import Image
from django.db.models.signals import post_save
class User(AbstractUser):
first_name = models.CharField(verbose_name="First name", max_length=255)
last_name = models.CharField(verbose_name="First name", max_length=255)
country = models.CharField(verbose_name="Country name", max_length=255)
city = models.CharField(verbose_name="City name", max_length=255)
email = models.EmailField(verbose_name="Email", max_length=255)
def __str__(self):
return self.username
class Post(models.Model):
title = models.CharField(max_length=255)
country = models.CharField(max_length=255)
city = models.CharField(max_length=255)
address = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
phone = models.CharField(max_length=255)
website = models.CharField(max_length=255)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = Profile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
my views.py
from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, DetailView
from .forms import UserCreationModelForm, UserUpdateForm, ProfileUpdateForm
from .models import User, Profile, Post
from django.http import HttpResponse
class UserRegistrationView(CreateView):
form_class = UserCreationModelForm
success_url = reverse_lazy('login')
template_name = 'users/registration.html'
class CabinetView(LoginRequiredMixin, DetailView):
model = User
def get_object(self):
return self.request.user
#login_required
def blog(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'users/post_list.html', context)
def home(request):
return render(request, 'registration/home.html')
my urls.py
from django.urls import path
from .views import UserRegistrationView, CabinetView
from . import views
app_name = 'users'
urlpatterns = [
path('accounts/register/', UserRegistrationView.as_view(), name='register'),
path('accounts/cabinet/', CabinetView.as_view(), name='cabinet'),
path('', views.home, name='home'),
path('accounts/cabinet/blog/', views.blog, name='blog'),
]
my post_list.html
{% extends 'shared/base.html' %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block content %}
<br>
<br>
<div class="container mt-5">
{% for post in posts %}
<table class="table table-hover">
<tbody>
<tr>
<th>Name: </th>
<td>{{ post.title }}1</td>
</tr>
<tr>
<th>Country: </th>
<td>{{ post.country }}</td>
</tr>
<tr>
<th>City: </th>
<td>{{ post.city }}</td>
</tr>
<tr>
<th>Address: </th>
<td>{{ post.address }}</td>
</tr>
<tr>
<th>Email: </th>
<td>{{ post.email }}</td>
</tr>
<tr>
<th>Phone: </th>
<td>{{ post.phone }}</td>
</tr>
<tr>
<th>Website: </th>
<td>{{ post.website }}</td>
</tr>
</tbody>
</table>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
I want that each user can see only their own posts.
Problem is in your view function: It should filter posts depending on requests user (currently logged-in user).
loginrequired decorator django.contrib.auth.middleware.AuthenticationMiddleware places the corresponding User object as the attribute user to the request dictionary, so you can access it in your view function easily.
Like this:
#login_required
def blog(request):
context = {
'posts': Post.objects.filter(author=request.user)
}
return render(request, 'users/post_list.html', context)

Django button in Modelclass

I'm making an inventory app in which I could update the values of the products from my 'home.html'.
My proj name is Inventory
App name is myapp
Problem I am facing is that every time I update the value of a Stock from my homepage, it adds a new Product instead of updating the one that I want!
I am using the ModelsForm Class provided by Django.
Using Django=1.11 and Python=3.6
My project's urls.py:
from django.conf.urls import url,include
from django.contrib import admin
from myapp.views import home
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^myapp/', include('myapp.urls', namespace="myapp")),
url(r'^myapp/home/', home, name='home'),
]
My forms.py:
from django import forms
from .models import Inventory
class Operations(forms.ModelForm):
class Meta:
model = Inventory
fields = ('stocks_left',)
My app's Model.py:
from django.db import models
import uuid
class Inventory(models.Model):
"""
Model representing a the inventory.
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
inventory_name = models.CharField("INVENTORY NAME" ,max_length=200, help_text="This contains the Inventory name:")
short_name = models.CharField(max_length=20, help_text="This contains an abbreviation:")
inventory_code = models.IntegerField("INVENTORY CODE" ,default = '0', help_text="This contains the Inventory code:")
price = models.IntegerField(default = '0')
stocks_left = models.IntegerField("STOCKS LEFT",default = '0')
def __str__(self):
"""
String for representing the Model object (in Admin site etc.)
"""
return '{0} ({1}) ({2})'.format(self.inventory_name,self.inventory_code,self.stocks_left)
My app's urls.py
from django.conf.urls import url
from . import views
from django.contrib.auth.views import login
app_name= 'myapp'
urlpatterns = [
url(r'^$', login, {'template_name': 'myapp/login.html'}),
]
and my views.py
from django.shortcuts import render,redirect
from django.contrib import auth
from django.contrib.auth.models import User
from django.views import generic
from django.http import HttpResponse
from myapp.models import Inventory
from .forms import Operations
def home(request):
names = Inventory.objects.all()
if request.method == "POST":
form = Operations(request.POST)
if form.is_valid():
stocks_left = form.save(commit=False)
stocks_left.save()
return redirect('myapp/home.html')
else:
form = Operations()
return render(request, 'myapp/home.html', { "names": names, "form": form})
and my home.html template:
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<title>Inventory</title>
</head>
<body>
<h1>Welcome!</h1>
<div class="container">
<table border="5" cellpadding="10" width="1000">
<thead align="center">
<tr>
<th align="center">#</th>
<th align="center">Name</th>
<th align="center">Inventory Code</th>
<th align="center">Stocks left</th>
<th align="center">Operations</th>
</tr>
<tr>
{% for x in names %}
<td align="center"> {{ x }}</td>
<td align="center"> {{ x.inventory_name }}</td>
<td align="center"> {{ x.inventory_code }}</td>
<td align="center"> {{ x.stocks_left }}</td>
<td><form method="POST">{% csrf_token %}{{form}}<button type="button" class="btn btn-primary"><span class="glyphicon glyphicon-plus"></span></button></form><br></td>
</tr>
{% endfor %}
</table>
</div>
</body>
Here is what you can do,
Create 2 fields in forms,
class Operations(forms.ModelForm):
class Meta:
model = Inventory
fields = ('stocks_left','inventory_name')
When you get the data in the view,
if request.method == "POST":
form = Operations(request.POST)
if form.is_valid():
inv_obj = form.cleaned_data.get('inventory_name')
inv_model_obj = Inventory.objects.get(inventory_name=inv_obj) #make sure to declare in the models that this inventory_name is unique
inv_model_obj.stocks_left = form.cleaned_data.get('stocks_left')
inv_model_obj.save()
return redirect('myapp/home.html')
If you do not pass instance=the_instance_you_want_to_edit to a ModelForm it will create a new instance. How else would the ModelForm know what model instance you mean to edit?
BaseModelForm.init
if instance is None:
# if we didn't get an instance, instantiate a new one
self.instance = opts.model()
object_data = {}
else:
self.instance = instance
object_data = model_to_dict(instance, opts.fields, opts.exclude)
Anyway, it is not really going to work well if you want to keep it all on one page. Either you manually type in the object_id to pass to the ModelForm later. Or you create a FormSet with each Form representing an Inventory object plus an input field for 'stocks_left'.
The former is a bit iffy because if you mistype the primary key you are going to change the stock of the wrong Inventory without noticing (or throw a DoesNotExist error down the road).
And the latter is total overkill if you only want to change a single Inventory.
You have two options and either option requires another page/template.
One page displays your overview and the other serves to update an Inventory's stock. The overview contains links to the individual update pages.
Capture the primary key of the object you want to edit from the url.
url(r'^myapp/home/([0-9]+)/$)', home, name='home-update')
The URL dispatcher will then call your home view function with the request and the captured parameter and you can instantiate the ModelForm with it.
def home(request, pk):
names = Inventory.objects.all()
if request.method == "POST":
form = Operations(request.POST, instance=Inventory.objects.get(pk=pk)
if form.is_valid():
form.save()
return redirect('myapp/home.html')
else:
form = Operations()
return render(request, 'myapp/a_very_basic_template_to_display_a_form.html', {"form": form})
Or use a class based UpdateView (for your 'update' page):
class InventoryStockUpdateView(views.generic.UpdateView):
model = Inventory
template_name = 'myapp/a_very_basic_template_to_display_a_form.html'
fields = ['stocks_left']
success_url = reverse_lazy('home')
With this in urls.py:
url(r'^myapp/home/(?P<pk>[0-9]+)/$)', InventoryStockUpdateView.as_view(), name='home-update')
To edit Inventory with the primary key 31415 you would then type '...home/31415' into your browser.
UPDATE:
Have you had a look at django's admin actions? They let you edit instances from the changelist by selecting them via a checkbox and then running an admin action on them. While that may not be quite what you want, investigating how exactly they work should teach you some tricks that would help you in your current task.
To maybe give you a few pointers on how to proceed: add <a> tags to your template, two (+/-) for every 'row' of instances you are displaying.
The href attribute of each tag of a should contain the row's instance and the element's 'job' (adding or subtracting a stock). These two values will be used in the url conf much like I described above...
As to how you properly build the href attribute; the template tag docs should help.
Maybe like so:
<tr>
{% for x in names %}
<td align="center"> {{ x }}</td>
<td align="center"> {{ x.inventory_name }}</td>
<td align="center"> {{ x.inventory_code }}</td>
<td align="center"> {{ x.stocks_left }}</td>
<td><a href={% url ??? %}>click me to subtract!</a></td>
<td><a href={% url ??? %}>click me to add!</a></td>
</tr>
{% endfor %}
Of course, you would also need a new view function to handle those urls, but those shouldn't be very difficult to figure out.

Django - Delete an specific record

I need your help please I'm trying to delete an specific record in my table that I already created, I have trying some codes but not working in my django version 1.10.4, Can someone help me?
Here's what I have:
Views.py
from django.shortcuts import render
from django.conf import settings
from .forms import regForm
from .models import registro
from registro.forms import regForm
from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse
def test_reg(request):
form = regForm(request.POST or None)
queryset = registro.objects.all()
# query_delete = queryset.delete()
context = {
"form": form,
"queryset": queryset,
}
if form.is_valid():
instance = form.save()
return render(request, "registro.html", context)
def delete(request, id):
note = get_object_or_404(registro, pk=id).delete()
return HttpResponseRedirect(reverse('/'))
Template
<form method="POST" action="">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Registrame" />
</form>
<style>
table, th, td {
border: 1px solid black;
}
</style>
<table>
<tr>
<th>Name</th>
...
<th>Age</th>
...
<th>Delete</th>
</tr>
{% for item in queryset %}
<tr>
...
<td>{{ item.name }}</td>
...
<td>{{ item.age }}</td>
...
<td> Delete </td>
</tr>
{% endfor %}
</table>
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from myselect import views
from registro import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^select/', include('myselect.urls')),
url(r'^delete/(?P<id>\d+)/$',views.delete, name='delete'),
url(r'^$', views.test_reg, name='test_reg')
]
Model.py
from __future__ import unicode_literals
from django.db import models
# Create your models here.
from django import forms
# Create your models here.
class registro(models.Model):
name = models.CharField(max_length=100)
age = models.CharField(max_length=100)
def __unicode__(self):
return self.name
def __str__(self):
return self.name
Basically I have some users in my Database where I'm showing this through a table in my template, I want to delete the first one for example by clicking in my delete option where is in my last cell of my table
I tried this code and I got:
Reverse for 'delete' with arguments '()' and keyword arguments '{u'pk': ''}' not found. 1 pattern(s) tried: ['delete/(?P<id>\\d+)/$']
How can I solve this and make it work good?
Help please... thanks !
The problem is in your template change:
Delete
To:
Delete

Categories