Reputation: 65
I am in process of developing a Django Project that has 3 apps namely Customer, Investments and Stocks. Each Customer can have multiple Investments and Stocks but not the other way round. So far, everything works well on Admin side of the application. I am able to CRUD as an admin, but my goal is to have a 3 separate user levels - customer, advisor and admin (this is working fine!). A customer can only view his/her profile, investments and stocks pertaining to it. An advisor can view information of multiple customers and their portfolios. I think I can separate these by different Authentication levels/restrictions. These are my files,
This is my customer model,
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Customer(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=200)
cust_number = models.AutoField(max_length=5, primary_key=True)
city = models.CharField(max_length=50)
state = models.CharField(max_length=50)
zipcode = models.CharField(max_length=10)
email = models.CharField(max_length=200)
home_phone = models.CharField(max_length=50)
cell_phone = models.CharField(max_length=50)
created_date = models.DateTimeField(
default=timezone.now)
updated_date = models.DateTimeField(
blank=True, null=True)
def created(self):
self.created_date = timezone.now()
self.save()
def updated(self):
self.updated_date = timezone.now()
self.save()
def __str__(self):
return self.name
This is my investment model,
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Investment(models.Model):
category = models.CharField(max_length=50)
description = models.CharField(max_length=200)
cust_number = models.ForeignKey('customers.Customer')
acquired_value = models.DecimalField(max_digits=10, decimal_places=2)
acquired_date = models.DateTimeField(default=timezone.now)
recent_value = models.DecimalField(max_digits=10, decimal_places=2)
recent_date = models.DateTimeField(default=timezone.now, blank=True, null=True)
def created(self):
self.acquired_date = timezone.now()
self.save()
def updated(self):
self.recent_date = timezone.now()
self.save()
def __str__(self):
return self.category
This is my stocks model,
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Stock(models.Model):
symbol = models.CharField(max_length=10)
name = models.CharField(max_length=50)
shares = models.CharField(max_length=50)
cust_number = models.ForeignKey('customers.Customer')
purchase_price = models.DecimalField(max_digits=10, decimal_places=2)
recent_date = models.DateTimeField(default=timezone.now, blank=True, null=True)
def created(self):
self.recent_date = timezone.now()
self.save()
def __str__(self):
return self.name
This is my views.py in customers app although have separate views for investments and stocks, I defined same classes in customers/views.py so it renders in single view.
from django.shortcuts import render
from django.utils import timezone
from .models import Customer
from investments.models import Investment
from stocks.models import Stock
def customer(request):
customers = Customer.objects.filter(created_date__lte=timezone.now())
return render(request, 'customers/customer.html', {'customers': customers})
def investment(request):
investments = Investment.objects.filter(created_date__lte=timezone.now())
return render(request, 'customers/customer.html', {'investments': investments})
def stock(request):
stocks = Stock.objects.filter(created_date__lte=timezone.now())
return render(request, 'customers/customer.html', {'stocks': stocks})
I am trying to render the views on single html page like this,
Here's my customer.html template
{% load staticfiles %}
<!DOCTYPE html>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link href="//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css">
<html lang="en">
<head>
<link rel="stylesheet" href="{% static 'css/customers.css' %}">
<meta charset="UTF-8">
<title>Eagle Financial Services</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-primary">
<div class="panel-heading">Welcome!</div>
<div class="panel-body">
ABC Financial Services, your Financial Services Partner.
</div>
</div>
</div>
</div>
</div>
<div class="row">
<h2 style="padding-left: 15Px">Customer Information</h2>
</div>
<div>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th>Customer ID</th>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Primary Email</th>
<th>Home Phone</th>
<th>Cell Phone</th>
<th colspan="3">Actions</th>
</tr>
</thead>
<tbody>
{% for customer in customers %}
<tr>
<td>{{ customer.cust_number }}</td>
<td>{{ customer.name }}</td>
<td>{{ customer.address }}</td>
<td>{{ customer.city }}</td>
<td>{{ customer.state }}</td>
<td>{{ customer.zipcode }}</td>
<td>{{ customer.email }}</td>
<td>{{ customer.home_phone }}</td>
<td>{{ customer.cell_phone }}</td>
<td><a href="{{ customers.customer }}" class="btn btn-primary">Read</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h2 style="padding-left: 15Px">Investments Information</h2>
</div>
<div>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th>Customer ID</th>
<th>Name</th>
<th>Category</th>
<th>Description</th>
<th>Acquired Value</th>
<th>Acquired Date</th>
<th>Recent Value</th>
<th>Recent Date</th>
<th colspan="3">Actions</th>
</tr>
</thead>
<tbody>
{% for customer in customers %}
<tr>
<td>{{ customer.cust_number }}</td>
<td>{{ customer.name }}</td>
{% for investment in investments %}
<td>{{ investment.category }}</td>
<td>{{ investment.description }}</td>
<td>{{ investment.acquired_value }}</td>
<td>{{ investment.acquired_date }}</td>
<td>{{ investment.recent_value }}</td>
<td>{{ investment.recent_date }}</td>
{% endfor %} {% endfor %}
</tbody>
</table>
</div>
<div class="row">
<h2 style="padding-left: 15Px">Stocks Information</h2>
</div>
<div>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th>Symbol</th>
<th>Name</th>
<th>Shares</th>
<th>Cust_Number</th>
<th>Purchase Price</th>
<th>Recent Date</th>
<th colspan="3">Actions</th>
</tr>
</thead>
<tbody>
{% for stock in stocks %}
<tr>
<td>{{ stock.symbol }}</td>
<td>{{ stock.name }}</td>
<td>{{ stock.shares }}</td>
<td>{{ stock.cust_number }}</td>
<td>{{ stock.purchase_price }}</td>
<td>{{ stock.recent_date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
Here's projectname.url
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('customers.urls')),
url(r'', include('investments.urls')),
url(r'', include('stocks.urls')),
]
Here's customers.url
`from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.customer, name='customer'),
]`
Investment and Stocks resemble customer.urls except the name.
Now on the webpage, only the values in customer table are being displayed, and in investment table only cust_number and name are being displayed nothing else and in stocks nothing is displayed. I have tried almost all the trial/errors for past 3 days. I am lot confused. Where I am getting it wrong. Any guidance will be highly appreciated. Thanks.
I am using Python - 3.6, Django - 1.11.1.
Upvotes: 1
Views: 121
Reputation: 11635
In your template your attempting to iterate three different templates variables, passed in through the dict to render
, which are being served by three different views. Why would you expect all of them to render when using a specific one of these views when you haven't passed this variable to the template for rendering by the server before it's displayed to the client?
The only reason you get some data in the investments table (referencing data to customers) is because it's referencing the data on a customer object from the outer (containing) forloop iterating the customer objects you passed in.
Specifically you're serving:
def customer(request):
customers = Customer.objects.filter(created_date__lte=timezone.now())
return render(request, 'customers/customer.html', {'customers': customers})
as the home view '^$'
which has a list of customer objects as the template variable customers
which is rendering the data in your {% for customer in curstomers %}
loops
Alternative Approach:
Unless there's something preventing you from changing the schema to this... which I don't see why there would be. You can just add a ForeignKey to stocks and investments to denote that specific customers stocks and investments rather than having your data as sparse as it is (although.. that's occasionally a good thing).
Example:
class Customer(models.Model):
...
created = models.DateTimeField(default=timezone.now)
**updated = models.DateTimeField(auto_now_add=True)**
stock = models.ForeignKey(Stock, related_name="stocks")
investment = models.ForeignKey(Investment, related_name="investments")
Changes:
You can reference these as customer.stock_set.(filter / all etc)
on an instance. Similarly for investment, or you can use customer.stocks
using the related name. Additionally you can also use prefetch_related
if you wanted.
Note the auto_now_add=True
on updated you can use this for timestamps rather than manually updating them since it will change the time to be the time it was saved on each successive save of the model instance.
Get rid of the foreign keys on stocks and investments.
Additional:
Why not have a OneToOneField
on your customer referencing a User model instance to define a custom user model representing customers?
Upvotes: 1
Reputation: 9931
The reason why you are facing this problem is that views.customer
only passes the information of customer and not the other variables like stocks.
So in your customer/views.py
:
def customer(request):
customers = Customer.objects.filter(created_date__lte=timezone.now())
investments = Investment.objects.filter(created_date__lte=timezone.now())
stocks = Stock.objects.filter(created_date__lte=timezone.now())
return render(request, 'customers/customer.html', {'customers': customers, 'stocks': stock, 'investments', investments})
Upvotes: 1