Skip to content

Commit

Permalink
Merge pull request #5 from esoergel/feature/cities
Browse files Browse the repository at this point in the history
Built out some heavily commented example code in the cities app
  • Loading branch information
tedtieken committed May 20, 2013
2 parents 21f63d7 + b516e6a commit 4ef55b9
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 16 deletions.
6 changes: 6 additions & 0 deletions apps/cities/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.contrib import admin

from .models import City, Cohort

admin.site.register(City)
admin.site.register(Cohort)
21 changes: 20 additions & 1 deletion apps/cities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@
# City
class City(models.Model):
name = models.CharField(max_length=255)
# slug = models.SlugField()
description = models.TextField()
organizers = models.ManyToManyField(UserProfile)

def __unicode__(self):
"""
adding this function to your models lets you define how each
object appears, rather than "City object", I want the city's
name
"""
return self.name


# Cohort
class Cohort(models.Model):
Expand All @@ -15,9 +24,19 @@ class Cohort(models.Model):
eg: City: Boston, Cohort: May-2013
"""
name = models.CharField(max_length=255)
# slug = models.SlugField()
description = models.TextField()
city = models.ForeignKey(City)
start_date = models.DateField()
end_date = models.DateField()
members = models.ManyToManyField(UserProfile, related_name="cohort_members_set")
organizers = models.ManyToManyField(UserProfile, related_name="cohort_organizers_set")
organizers = models.ManyToManyField(UserProfile, related_name="cohort_organizers_set")

def __unicode__(self):
"""
I'm including self.city in the unicode representation of this
object. That will render according to City()'s __unicode__
method. Now in the admin site, the "May 2013" cohort will appear
in the form "Boston - May 2013"
"""
return "%s - %s" % (self.city, self.name)
22 changes: 22 additions & 0 deletions apps/cities/templates/cities/city_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "base.html" %}

{% comment %}
{% endcomment %}

{% block meta_title %}
{{city.name}}
{% endblock %}


{% block content %}
<p>The city name is {{city.name}}</p>

<p>The city description is: {{city.description}}</p>

<p>
Here are
<a href="{% url "cohort_list" city.name %}">
{{city.name}} cohorts
</a>
</p>
{% endblock %}
33 changes: 33 additions & 0 deletions apps/cities/templates/cities/city_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{% extends "base.html" %}

{% comment %}

Take special notice at the syntax in here, notice how I generated the link to the city detail page.

Right now I'm overriding content instead of canvas, this means that the sidebar will be the same here as everywhere else (and it won't be city specific). This may be changed.
{% endcomment %}

{# This is what a single-line comment looks like #}
<!--HTML comments show up in the html-->
{# but django comments don't #}

{% block meta_title %}
CodeRaising Cities
{% endblock %}


{% block content %}
<p>The city names are:</p>

{% for city in city_list %}
<p>
{# This generates the city_detail url for each city #}
<a href="{% url "city_detail" city.name %}">
{# the second argument can be the url name or view path #}

{{city.name}} - {{city.description}}
</a>
</p>
{% endfor %}

{% endblock %}
22 changes: 22 additions & 0 deletions apps/cities/templates/cities/cohort_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "base.html" %}


{% block meta_title %}
{# I'm using a variable here so this same template can be reused #}
{{cohort_category}} Cohorts
{% endblock %}


{% block content %}
<h1>{{cohort_category}} Cohorts</h1>

{% for cohort in cohort_list %}
<p>
{# the cohort_detail url captures two kwargs, so I'm using named args in my reverser to avoid ambiguity #}
<a href="{% url "cohort_detail" city=cohort.city.name cohort=cohort.name %}">
{{cohort.name}} - {{cohort.description}}
</a>
</p>
{% endfor %}

{% endblock %}
45 changes: 45 additions & 0 deletions apps/cities/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from django.conf.urls.defaults import patterns, include, url
from django.views.generic import TemplateView

from mezzanine.core.views import direct_to_template

from .views import (
CitiesListView,
CityDetailView,
CohortListView,
CohortDetailView,
)

# Note: these views will not work if there's nothing in the database.
# well ListView will show nothing, and DetailView will 404.
# I added a couple cities to my dev db just for testing.
# Also, the url reversing seems to break if names contain spaces.
# We should add a "slug" field to any model for which we want to use
# the name in urls. Django has a function that converts arbitrary
# strings into url-safe strings called slugs. I'll do this later,
# but for now I don't want us to worry about db migrations.
# anyways, to stay safe while testing, don't have spaces in city
# or cohort names.

urlpatterns = patterns("",
url(
r"^$",
CitiesListView.as_view(),
name="cities_list"
),
url(
r"^(?P<city>[\w-]+)/$",
CityDetailView.as_view(),
name="city_detail"
),
url (
r"^(?P<city>[\w-]+)/cohorts/$",
CohortListView.as_view(),
name="cohort_list"
),
url( # this view has not yet been built
r"^(?P<city>[\w-]+)/(?P<cohort>[\w-]+)/$",
CohortDetailView.as_view(),
name="cohort_detail"
),
)
80 changes: 79 additions & 1 deletion apps/cities/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,83 @@
from django.shortcuts import render
from django.views.generic import TemplateView
from django.views.generic import TemplateView, ListView, DetailView

from .models import City, Cohort


class CitiesListView(ListView):
"""
Definitely read up on ListView here:
http://ccbv.co.uk/projects/Django/1.5/django.views.generic.list/ListView/
By default it'll show all objects that match the model
you reference. get_context_data will define two context variables
that point to this queryset, "object_list" and another one that's
either <lowercase_model_name>_list (as defined in get_context_object_name)
or context_object_name if you define it in the class attributes
"""
model = City
# ListView generates a template name from the model, so I don't
# need to define it here.
# template_name="cities/city_list.html"
# context_object_name = variable_to_use_in_templates

# def get_context_data(self, **kwargs):
# "This is to print your context variables during testing ONLY"
# context = super(CitiesListView, self).get_context_data(**kwargs)
# print context
# return context


class CityDetailView(DetailView):
"""
Definitely read up on DetailView here:
http://ccbv.co.uk/projects/Django/1.5/django.views.generic.detail/DetailView/
This is similar to ListView (context_object_name and all that), but
here you also need a field to identify the object.
"""
model = City
slug_field = "name"
slug_url_kwarg = "city"


class CohortListView(ListView):
"""
If I only list the model (like on CitiesListView), it'll show all
cohorts, but we want to filter by city, so I need to restrict the
queryset by overriding get_queryset()
"""
model = Cohort

def get_queryset(self):
queryset = super(CohortListView, self).get_queryset()
city_name = self.kwargs['city']
return queryset.filter(city__name__exact=city_name)

def get_context_data(self, **kwargs):
"""
I wanted to make the template reusable, so it can show
city cohorts or django cohorts or whatever, so any view that
renders it just needs to add a "cohort_category" to the context
"""
context = super(CohortListView, self).get_context_data(**kwargs)
context['cohort_category'] = self.kwargs['city']
return context


class CohortDetailView(DetailView):
# make this work
pass







####################################
# Old stuff below this line #
# I'm leaving it in for reference #
####################################


def functional_dummy_view(request, *args, **kwargs):
context = {"variable": "it's much better to store logic in views"}
Expand Down
30 changes: 16 additions & 14 deletions urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
# to the project's homepage.

urlpatterns = patterns("",
url("^myprofile/$", TemplateView.as_view(template_name="profile.html"), name="myprofile"),
url("^profilelist/$", TemplateView.as_view(template_name="profilelist.html"), name="profilelist"),
url(r"^myprofile/$", TemplateView.as_view(template_name="profile.html"), name="myprofile"),
url(r"^profilelist/$", TemplateView.as_view(template_name="profilelist.html"), name="profilelist"),

url(r"^cities/", include("apps.cities.urls")),
# once we compartmentalize the function into apps (profiles, projects, etc...)
# it'll make sense to use include() and store the relevant urls within that app
# Here are four different ways to render a template:
Expand All @@ -26,34 +28,34 @@
# template in the "params" dictionary, but you should generally avoid
# this by using an actual view.
url(
"^dummy1/$",
r"^dummy1/$",
direct_to_template,
{"template": "dummy.html", "variable": "You shouldn't put this much in your URLconf"},
name="dummy1"
),
# this is a better dummy1 implementation (with no additional context passed)
# url(
# "^dummy1$",
# r"^dummy1/$",
# direct_to_template,
# {"template": "dummy.html"},
# name="dummy1"
# ),
url("^dummy2/$", TemplateView.as_view(template_name="dummy.html"), name="dummy2"),
url(r"^dummy2/$", TemplateView.as_view(template_name="dummy.html"), name="dummy2"),

# these two examples refer to actual views in apps/core/views.py For the
# purposes of just creating a template, it's fine to use one of the two
# methods above, but once you start making the template do stuff, you'll
# want to use a custom view.
url("^dummy3/$", "apps.cities.views.functional_dummy_view", name="dummy3"),
url("^dummy4/$", ClassyDummyView.as_view(), name="dummy4"),
url(r"^dummy3/$", "apps.cities.views.functional_dummy_view", name="dummy3"),
url(r"^dummy4/$", ClassyDummyView.as_view(), name="dummy4"),


# --------------------------------------------------------------------------
# preconfigured stuff below this line.

# Change the admin prefix here to use an alternate URL for the
# admin interface, which would be marginally more secure.
("^admin/", include(admin.site.urls)),
url(r"^admin/", include(admin.site.urls)),

# We don't want to presume how your homepage works, so here are a
# few patterns you can use to set it up.
Expand All @@ -65,7 +67,7 @@
# one homepage pattern, so if you use a different one, comment this
# one out.

#url("^$", direct_to_template, {"template": "index.html"}, name="home"),
#url(r"^$", direct_to_template, {"template": "index.html"}, name="home"),

# HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
# ---------------------------------------------
Expand All @@ -80,7 +82,7 @@
# "/.html" - so for this case, the template "pages/index.html"
# should be used if you want to customize the homepage's template.

url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),
url(r"^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),

# HOMEPAGE FOR A BLOG-ONLY SITE
# -----------------------------
Expand All @@ -90,7 +92,7 @@
# ``settings.py`` module, and delete the blog page object from the
# page tree in the admin if it was installed.

# url("^$", "mezzanine.blog.views.blog_post_list", name="home"),
# url(r"^$", "mezzanine.blog.views.blog_post_list", name="home"),

# MEZZANINE'S URLS
# ----------------
Expand All @@ -103,8 +105,8 @@
# ``mezzanine.urls``, go right ahead and take the parts you want
# from it, and use them directly below instead of using
# ``mezzanine.urls``.
("^", include("mezzanine_events.urls")),
("^", include("mezzanine.urls")),
url(r"^", include("mezzanine_events.urls")),
url(r"^", include("mezzanine.urls")),

# MOUNTING MEZZANINE UNDER A PREFIX
# ---------------------------------
Expand All @@ -120,7 +122,7 @@
# Note that for any of the various homepage patterns above, you'll
# need to use the ``SITE_PREFIX`` setting as well.

# ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
# url(r"^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))

)

Expand Down

0 comments on commit 4ef55b9

Please sign in to comment.