Installing and developing local apps¶
First we need to set up static files serving during the development process. Ideally we should install a testing web server (nginx or apache) and develop the site in an environment as similar as possible with the production environment.
To set up static and media files serving during development, add the following to your “urls.py” file:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
To create a new app named “inventory” run the following:
./manage startapp inventory
the following python package has been added to your project:
inventory
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
Make the following changes:
inventory/settings.py:
INSTALLED_APPS = [
...
'inventory',
]
Now we have an empty app named “inventory” which is registered with the django project. We want to build a simple app containing 3 pieces of information:
- a list of machines in the department
- a list of machine owners
- a pcs price list
Add models¶
inventory/models.py:
class Machine(models.Model):
name = models.CharField(max_length=20)
mac = models.CharField('MAC address', max_length=20)
ip = models.GenericIPAddressField(blank=True, null=True)
notes = models.TextField(blank=True)
owner = models.ManyToManyField("Owner", related_name='owner')
price = models.ForeignKey("Price")
def __str__(self):
return self.name + ', ' + self.ip
class Owner(models.Model):
name = models.CharField(max_length=255)
email = models.EmailField()
phone = models.CharField(max_length=255)
def __str__(self):
return self.name
class Price(models.Model):
name = models.CharField(max_length=255)
price = models.FloatField()
def __str__(self):
return "{0}, ${1}".format(self.name, self.price)
Now run the migrations to create the necessary tables in the database:
./manage.py makemigrations
./manage.py migrate
You can now inspect the generated models and tables with the following command:
./manage.py inspectdb
Set up the admin¶
inventory/admin.py:
from .models import Machine, Owner, Price
class MachineInline(admin.TabularInline):
model = Machine
fields = ['name', 'mac', 'ip']
class MachineAdmin(admin.ModelAdmin):
fields = ['name', 'mac', 'ip', 'notes', 'owner', 'price']
list_display = ['name', 'mac', 'ip', 'price']
list_filter = ['ip', 'name']
filter_horizontal = ['owner']
class OwnerAdmin(admin.ModelAdmin):
list_display = ['name', 'email', 'phone']
class PriceAdmin(admin.ModelAdmin):
list_display = ['name', 'price']
inlines = [MachineInline]
admin.site.register(Machine, MachineAdmin)
admin.site.register(Owner, OwnerAdmin)
admin.site.register(Price, PriceAdmin)
Show content on the ‘public’ web¶
Set up templates¶
Create a directory “templates” in the root of your project. Register the template folder in the settings.
settings.py:
TEMPLATES = [
{
...
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
...
}
]
In the template dir create a html file named “base.html”. This template is the parent of all the other templates in the project. It is the best place to insert boilerplate code like css and js which will be inherited by all other child templates.
templates/base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
<div><b>Inventory app logo</b></div>
-->
{% block content %}
<h1>This is the base.html file</h1>
{% endblock content %}
</body>
</html>
Write views¶
We will write 3 views (class based generic).
- One is a plain main inventory page.
- One lists machines.
- One shows details about machines.
inventory/views.py:
from django.views.generic import DetailView, ListView, TemplateView
from .models import Machine
class InventoryHome(TemplateView):
template_name = 'inventory/index.html'
class MachineListView(ListView):
model = Machine
class MachineDetailView(DetailView):
model = Machine
Create templates for inventory app¶
Create a folder named “templates/inventory” in the inventory app.
There create the following html files:
index.html:
{% extends 'base.html' %}
{% block content %}
<h1>This is the inventory/index.html file</h1>
{% endblock content %}
machine_list.html:
{% extends 'base.html' %}
{% block content %}
<h1>Machines Inventory</h1>
<ul>
{% for machine in object_list %}
<li>
<a href="{% url 'inventory:machine-detail' machine.pk %}">
{{ machine }}
</a>
</li>
{% endfor %}
</ul>
{% endblock content %}
machine_detail.html:
{% extends 'base.html' %}
{% block content %}
<h1>Machine Details</h1>
<dl>
<dt>name</dt>
<dd>{{ object.name }}</dd>
<dt>mac</dt>
<dd>{{ object.mac }}</dd>
<dt>price</dt>
<dd>${{ object.price.price }}</dd>
<dd>{{ object.price.name }}</dd>
<dt>owner(s)</dt>
{% for owner in object.owner.all %}
<dd>{{ owner.name }}, {{ owner.email }}</dd>
{% empty %}
{{ object }} has no owner.
{% endfor %}
</dl>
{% endblock content %}
setup urls¶
First we need to create a urls.py file in the ‘inventory’ app
inventory/urls.py:
from django.conf.urls import url
from .views import InventoryHome, MachineDetailView, MachineListView
urlpatterns = [
url(r'^$', InventoryHome.as_view(), name="home"),
url(r'^machines/$', MachineListView.as_view(), name="machine-list"),
url(r'^machines/(?P<pk>\d+)/$', MachineDetailView.as_view(),
name="machine-detail"),
]
We also nedd to connect the inventory urls to the project urls:
someproj/urls.py:
urlpatterns = [
...
url(r'^inventory/', include('inventory.urls', namespace='inventory')),
...
]
Now we browse to:
http://localhost:8000/inventory
and visit the app. Also we can add some more machines through the admin.
Our inventory app is installed and functional