After lots of discussions, default commands where moved from game/gamesrc/commands/default to src/commands/default in order to make it clearer which parts are updated as part of evennia and which can be tweaked at heart's content. New templates where left in gamesrc/commands that should hopefully make it clearer how to extend the command system. Also game/web was moved to src/web - we'll likely extend this from game/gamesrc/web in the future. If you already did extensions you should just have to edit your import paths and make use of the new cmdset template supplied.

The unit testing was for commands was split out from src/objects/tests.py into the new src/commands/default/test.py in order to keep the testing modules thematically grouped with the things they are testing.
This commit is contained in:
Griatch 2010-11-23 01:24:56 +00:00
parent a3917073ff
commit 72d40285b8
61 changed files with 381 additions and 184 deletions

0
src/web/__init__.py Normal file
View file

View file

@ -0,0 +1,225 @@
/**************************************
* TITLE: Prosimii Print Stylesheet *
* URI : prosimii/prosimii-print.css *
* MODIF: 2003-Apr-30 19:15 +0800 *
**************************************/
/* ##### Common Styles ##### */
body {
color: black;
background-color: white;
font-family: "times new roman", times, roman, serif;
font-size: 12pt;
margin: 0;
padding: 0;
}
acronym, .titleTip {
font-style: italic;
border-bottom: none;
}
acronym:after, .titleTip:after { /* Prints titles after the acronyms/titletips. Doesn't work in MSIE */
content: "(" attr(title) ")";
font-size: 90%;
font-style: normal;
padding-left: 1ex;
}
a {
color: black;
background-color: transparent;
text-decoration: none;
}
a[href]:after { /* Prints the links' URIs after the links' texts. Doesn't work in MSIE */
content: "<" attr(href) ">";
font-size: 90%;
padding-left: 1ex;
}
ol {
margin: -0.25em 0 1em 0;
padding: 0;
}
ul {
list-style-type: square;
margin: -0.25em 0 1em 0;
padding: 0;
}
dl {
margin: 0 0 1em 0;
padding: 0;
}
ul li {
margin: 1ex 0 0 1.5em;
padding: 0;
}
ol li {
margin: 1ex 0 0 1.5em;
padding: 0;
}
dt {
font-weight: bold;
margin: 0;
padding: 0;
}
dd {
margin: 0 0 0 1.5em;
padding: 0;
}
.doNotPrint {
display: none;
}
/* ##### Header ##### */
#header {
}
.superHeader {
display: none;
}
.midHeader {
color: black;
background-color: transparent;
margin: 0;
padding: 0;
border-bottom: 1px solid black;
}
.headerTitle {
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 200%;
font-weight: normal;
margin: 0;
padding: 0;
}
.headerSubTitle {
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 110%;
font-weight: normal;
font-style: italic;
margin: 0;
padding: 0 0 1ex 0;
}
.headerLinks {
display: none;
}
.subHeader {
display: none;
}
/* ##### Side Menu ##### */
#side-bar {
display: none !important;
}
/* ##### Main Copy ##### */
#main-copy {
text-align: justify;
margin: 0 !important;
padding: 0;
}
#main-copy h1 {
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 120%;
margin: 2ex 0 1ex 0;
padding: 0;
}
#main-copy h2 {
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-weight: normal;
font-size: 100%;
margin: 0;
padding: 2ex 0 0.5ex 0;
}
#main-copy h1 + h2 {
padding-top: 0;
}
#main-copy p {
margin: 0 0 2ex 0;
padding: 0;
}
h2 a:after {
content: "" !important;
}
.newsDate {
font-style: italic;
margin: 0;
padding: 0;
display: inline;
}
.newsDate:before { /* Prints an '[' before the news item's date. Doesn't work in MSIE */
content: "[";
font-style: normal;
}
.newsDate:after { /* Prints a ']' after the news item's date. Doesn't work in MSIE */
content: "]";
font-style: normal;
}
.newsSummary {
display: inline;
margin: 0 0 0 1ex !important;
padding: 0;
}
.more {
display: none;
}
.smallCaps {
font-variant: small-caps;
}
.quarter, .oneThird, .half, .twoThirds, .fullWidth {
margin: 0;
padding: 0;
}
/* ##### Footer ##### */
#footer {
color: black;
background-color: transparent;
font-size: 100%;
text-align: center;
margin: 2em 0 0 0;
padding: 1ex 0 0 0;
border-top: 1px solid black;
display: block;
}
#footer a {
color: black;
background-color: transparent;
text-decoration: none;
}

View file

@ -0,0 +1,342 @@
/*************************************************
* TITLE: Prosimii Alternative Screen Stylesheet *
* URI : prosimii/prosimii-screen-alt.css *
* MODIF: 2004-Apr-28 21:56 +0800 *
*************************************************/
/* ##### Common Styles ##### */
body {
font-family: verdana, helvetica, arial, sans-serif;
font-size: 73%; /* Enables font size scaling in MSIE */
margin: 0;
padding: 0;
}
html > body {
font-size: 9pt;
}
acronym, .titleTip {
border-bottom: 1px dotted rgb(61,92,122);
cursor: help;
margin: 0;
padding: 0 0 0.4px 0;
}
a {
color: rgb(61,92,122);
background-color: transparent;
text-decoration: underline;
margin: 0;
padding: 0 1px 2px 1px;
}
a:hover {
color: rgb(117,144,174);
text-decoration: none;
}
ol {
margin: 1em 0 1.5em 0;
padding: 0;
}
ul {
list-style-type: square;
margin: 1em 0 1.5em 0;
padding: 0;
}
dl {
margin: 1em 0 0.5em 0;
padding: 0;
}
ul li {
line-height: 1.5em;
margin: 1.25ex 0 0 1.5em;
padding: 0;
}
ol li {
line-height: 1.5em;
margin: 1.25ex 0 0 2em;
padding: 0;
}
dt {
font-weight: bold;
margin: 0;
padding: 0 0 1ex 0;
}
dd {
line-height: 1.75em;
margin: 0 0 1.5em 1.5em;
padding: 0;
}
.doNotDisplay {
display: none !important;
}
.smallCaps {
font-size: 117%;
font-variant: small-caps;
}
/* ##### Header ##### */
.superHeader {
color: rgb(130,128,154);
background-color: rgb(33,50,66);
text-align: right;
margin: 0;
padding: 0.5ex 10px;
}
.superHeader span {
color: rgb(195,196,210);
background-color: transparent;
font-weight: bold;
text-transform: uppercase;
}
.superHeader a {
color: rgb(195,196,210);
background-color: transparent;
text-decoration: none;
margin: 0;
padding: 0 0.25ex 0 0;
}
.superHeader a:hover {
color: rgb(193,102,90);
background-color: transparent;
text-decoration: none;
}
.midHeader {
color: white;
background-color: rgb(61,92,122);
margin: 0;
padding: 0.26ex 10px;
}
.headerTitle {
font-size: 300%;
margin: 0;
padding: 0;
}
.headerSubTitle {
font-size: 151%;
font-weight: normal;
font-style: italic;
margin: 0 0 1ex 0;
padding: 0;
}
.headerLinks {
text-align: right;
margin: 0;
padding: 0 0 2ex 0;
position: absolute;
right: 1.5em;
top: 3.5em;
}
.headerLinks a {
color: white;
background-color: transparent;
text-decoration: none;
margin: 0;
padding: 0 0 0.5ex 0;
display: block;
}
.headerLinks a:hover {
color: rgb(195,196,210);
background-color: transparent;
text-decoration: underline;
}
.subHeader {
color: white;
background-color: rgb(117,144,174);
margin: 0;
padding: 0.5ex 10px;
}
.subHeader a, .subHeader .highlight {
color: white;
background-color: transparent;
font-size: 110%;
font-weight: bold;
text-decoration: none;
margin: 0;
padding: 0 0.25ex 0 0;
}
.subHeader a:hover, .subHeader .highlight {
color: rgb(255,204,0);
background-color: transparent;
text-decoration: none;
}
/* ##### Side Menu ##### */
#side-bar {
color: rgb(204,204,204);
background-color: transparent;
list-style-type: square;
list-style-position: inside;
width: 10em;
margin: 0;
padding: 1ex 0;
border: 1px solid rgb(204,204,204);
position: absolute;
left: 1.5ex;
top: 12em;
}
[id="side-bar"] {
position: fixed !important; /* Makes the side menu scroll with the page. Doesn't work in MSIE */
}
#side-bar a {
text-decoration: none;
}
#side-bar:hover {
color: rgb(117,144,174);
background-color: transparent;
border-color: rgb(117,144,174);
}
#side-bar li {
margin: 0;
padding: 0.75ex 0 1ex 1.75ex;
}
#side-bar li:hover {
color: rgb(61,92,122);
background-color: transparent;
}
#side-bar li a:hover {
text-decoration: underline;
}
/* ##### Main Copy ##### */
#main-copy {
text-align: justify;
margin: -0.5ex 1em 1em 12.5em;
padding: 0.5em 10px;
clear: left;
}
#main-copy h1 {
color: rgb(117,144,174);
background-color: transparent;
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 186%;
margin: 0;
padding: 1.5ex 0 0 0;
}
#main-copy h2 {
color: rgb(61,92,122);
background-color: transparent;
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-weight: normal;
font-size: 151%;
margin: 0;
padding: 1ex 0 0 0;
}
#main-copy p {
line-height: 1.75em;
margin: 1em 0 1.5em 0;
padding: 0;
}
.newsHeading {
color: rgb(61,92,122);
background-color: transparent;
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 145%;
text-decoration: none;
margin: 0;
padding: 1ex 0 0 0;
display: block;
}
.newsHeading:hover {
color: rgb(117,144,174);
background-color: transparent;
text-decoration: underline;
}
.newsDate {
font-style: italic;
margin: 0 !important;
padding: 0;
}
.newsSummary {
margin: 1.5ex 0 2.5ex 0.75ex !important;
padding: 0;
}
.more {
text-align: right;
margin: 0;
padding: 0.5em 0;
}
.more a {
color: rgb(61,92,122);
background-color: transparent;
font-size: 92%;
text-decoration: underline;
margin: 0;
padding: 0.25ex 0.75ex;
}
.more a:hover {
color: rgb(117,144,174);
text-decoration: none;
}
/* ##### Footer ##### */
#footer {
color: rgb(51,51,102);
background-color: rgb(239,239,239);
font-size: 87%;
text-align: center;
line-height: 1.25em;
margin: 2em 0 0 0;
padding: 1ex 10px;
clear: left;
}
#footer a {
color: rgb(0,68,204);
background-color: transparent;
text-decoration: underline;
}
#footer a:hover {
text-decoration: none;
}

View file

@ -0,0 +1,359 @@
/***************************************
* TITLE: Prosimii Screen Stylesheet *
* URI : prosimii/prosimii-screen.css *
* MODIF: 2004-Apr-28 21:43 +0800 *
***************************************/
/* ##### Common Styles ##### */
body {
font-family: verdana, helvetica, arial, sans-serif;
font-size: 73%; /* Enables font size scaling in MSIE */
margin: 0;
padding: 0;
}
html > body {
font-size: 9pt;
}
acronym, .titleTip {
border-bottom: 1px dotted rgb(61,92,122);
cursor: help;
margin: 0;
padding: 0 0 0.4px 0;
}
a {
color: rgb(61,92,122);
background-color: transparent;
text-decoration: underline;
margin: 0;
padding: 0 1px 2px 1px;
}
a:hover {
color: rgb(117,144,174);
text-decoration: none;
}
ol {
margin: 1em 0 1.5em 0;
padding: 0;
}
ul {
list-style-type: square;
margin: 1em 0 1.5em 0;
padding: 0;
}
dl {
margin: 1em 0 0.5em 0;
padding: 0;
}
ul li {
line-height: 1.5em;
margin: 1.25ex 0 0 1.5em;
padding: 0;
}
ol li {
line-height: 1.5em;
margin: 1.25ex 0 0 2em;
padding: 0;
}
dt {
font-weight: bold;
margin: 0;
padding: 0 0 1ex 0;
}
dd {
line-height: 1.75em;
margin: 0 0 1.5em 1.5em;
padding: 0;
}
.doNotDisplay {
display: none !important;
}
.smallCaps {
font-size: 117%;
font-variant: small-caps;
}
/* ##### Header ##### */
.superHeader {
color: rgb(130,128,154);
background-color: rgb(33,50,66);
text-align: right;
margin: 0;
padding: 0.5ex 10px;
}
.superHeader span {
color: rgb(195,196,210);
background-color: transparent;
font-weight: bold;
text-transform: uppercase;
}
.superHeader a {
color: rgb(195,196,210);
background-color: transparent;
text-decoration: none;
margin: 0;
padding: 0 0.25ex 0 0;
}
.superHeader a:hover {
color: rgb(193,102,90);
background-color: transparent;
text-decoration: none;
}
.midHeader {
color: white;
background-color: rgb(61,92,122);
margin: 0;
padding: 0.26ex 10px;
}
.headerTitle {
font-size: 300%;
margin: 0;
padding: 0;
}
.headerSubTitle {
font-size: 151%;
font-weight: normal;
font-style: italic;
margin: 0 0 1ex 0;
padding: 0;
}
.headerLinks {
text-align: right;
margin: 0;
padding: 0 0 2ex 0;
position: absolute;
right: 1.5em;
top: 3.5em;
}
.headerLinks a {
color: white;
background-color: transparent;
text-decoration: none;
margin: 0;
padding: 0 0 0.5ex 0;
display: block;
}
.headerLinks a:hover {
color: rgb(195,196,210);
background-color: transparent;
text-decoration: underline;
}
.subHeader {
color: white;
background-color: rgb(117,144,174);
margin: 0;
padding: 0.5ex 10px;
}
.subHeader a, .subHeader .highlight {
color: white;
background-color: transparent;
font-size: 110%;
font-weight: bold;
text-decoration: none;
margin: 0;
padding: 0 0.25ex 0 0;
}
.subHeader a:hover, .subHeader .highlight {
color: rgb(255,204,0);
background-color: transparent;
text-decoration: none;
}
/* ##### Main Copy ##### */
#main-copy {
margin: 0;
padding: 0.5em 10px;
clear: left;
}
#main-copy h1 {
color: rgb(117,144,174);
background-color: transparent;
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 200%;
margin: 0;
padding: 0;
}
#main-copy h2 {
color: rgb(61,92,122);
background-color: transparent;
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-weight: normal;
font-size: 151%;
margin: 0;
padding: 1ex 0 0 0;
}
#main-copy p {
line-height: 1.75em;
margin: 1em 0 1.5em 0;
padding: 0;
}
.newsHeading {
color: rgb(61,92,122);
background-color: transparent;
font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif;
font-size: 145%;
text-decoration: none;
margin: 0;
padding: 1ex 0 0 0;
display: block;
}
.newsHeading:hover {
color: rgb(117,144,174);
background-color: transparent;
text-decoration: underline;
}
.newsDate {
font-style: italic;
margin: 0 !important;
padding: 0;
}
.newsSummary {
margin: 1.5ex 0 2.5ex 0.75ex !important;
padding: 0;
}
.more {
text-align: right;
margin: 0;
padding: 0.5em 0;
}
.more a {
color: rgb(61,92,122);
background-color: transparent;
font-size: 92%;
text-decoration: underline;
margin: 0;
padding: 0.25ex 0.75ex;
}
.more a:hover {
color: rgb(117,144,174);
text-decoration: none;
}
.rowOfBoxes {
clear: both;
}
.quarter, .oneThird, .half, .twoThirds, .fullWidth {
margin: 1em 0;
float: left;
border-left: 1px solid rgb(204,204,204);
}
.quarter {
width: 21%;
padding: 0 1.9%;
}
.oneThird {
width: 28%;
padding: 0 1.9%;
}
.half {
text-align: justify;
width: 46%;
padding: 0 1.9%;
}
.twoThirds {
text-align: justify;
width: 63%;
padding: 0 1.9%;
}
.fullWidth {
text-align: justify;
width: 96%;
padding: 0 1.2em;
border-left: none;
}
.filler { /* use with an empty <p> element to add padding to the end of a text box */
border: 1px solid white;
}
.noBorderOnLeft {
border-left: none;
}
.dividingBorderAbove {
border-top: 1px solid rgb(204,204,204);
}
/* More elegant alternatives to .noBorderOnLeft & .dividingBorderAbove
* that don't require the creation of new classes - but which are not
* supported by MSIE - are the following:
*
* .rowOfBoxes > div:first-child {
* border-left: none;
* }
*
* .rowOfBoxes + .rowOfBoxes {
* border-top: 1px solid rgb(204,204,204);
* }
*/
/* ##### Footer ##### */
#footer {
color: rgb(51,51,102);
background-color: rgb(239,239,239);
font-size: 87%;
text-align: center;
line-height: 1.25em;
margin: 2em 0 0 0;
padding: 1ex 10px;
clear: left;
}
#footer a {
color: rgb(0,68,204);
background-color: transparent;
text-decoration: underline;
}
#footer a:hover {
text-decoration: none;
}

View file

@ -0,0 +1,4 @@
The evennia logo (the python snaking a cogwheel-globe) was created in 2009
by Griatch (www.griatch-art.deviantart.com, www.griatch.com) using open-source software (of course).
The logo is released with the same licence as Evennia itself (look in evennia/LICENCE).

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

0
src/web/news/__init__.py Executable file
View file

17
src/web/news/admin.py Normal file
View file

@ -0,0 +1,17 @@
#
# This makes the news model visible in the admin web interface
# so one can add/edit/delete news items etc.
#
from django.contrib import admin
from src.web.news.models import NewsTopic, NewsEntry
class NewsTopicAdmin(admin.ModelAdmin):
list_display = ('name', 'icon')
admin.site.register(NewsTopic, NewsTopicAdmin)
class NewsEntryAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'topic', 'date_posted')
list_filter = ('topic',)
search_fields = ['title']
admin.site.register(NewsEntry, NewsEntryAdmin)

45
src/web/news/models.py Executable file
View file

@ -0,0 +1,45 @@
#
# This module implements a simple news entry system
# for the evennia website. One needs to use the
# admin interface to add/edit/delete entries.
#
from django.db import models
from django.contrib.auth.models import User
class NewsTopic(models.Model):
"""
Represents a news topic.
"""
name = models.CharField(max_length=75, unique=True)
description = models.TextField(blank=True)
icon = models.ImageField(upload_to='newstopic_icons',
default='newstopic_icons/default.png',
blank=True, help_text="Image for the news topic.")
def __str__(self):
try:
return self.name
except:
return "Invalid"
class Meta:
ordering = ['name']
class NewsEntry(models.Model):
"""
An individual news entry.
"""
author = models.ForeignKey(User, related_name='author')
title = models.CharField(max_length=255)
body = models.TextField()
topic = models.ForeignKey(NewsTopic, related_name='newstopic')
date_posted = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ('-date_posted',)
verbose_name_plural = "News entries"

13
src/web/news/urls.py Executable file
View file

@ -0,0 +1,13 @@
"""
This structures the url tree for the news application.
It is imported from the root handler, game.web.urls.py.
"""
from django.conf.urls.defaults import *
urlpatterns = patterns('src.web.news.views',
(r'^show/(?P<entry_id>\d+)/$', 'show_news'),
(r'^archive/$', 'news_archive'),
(r'^search/$', 'search_form'),
(r'^search/results/$', 'search_results'),
)

128
src/web/news/views.py Executable file
View file

@ -0,0 +1,128 @@
"""
This is a very simple news application, with most of the expected features
like news-categories/topics and searchable archives.
"""
import django.views.generic.list_detail as gv_list_detail
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.conf import settings
from django.http import HttpResponseRedirect
from django.contrib.auth.models import User
from django import forms
from django.db.models import Q
from src.web.news.models import NewsTopic, NewsEntry
# The sidebar text to be included as a variable on each page. There's got to
# be a better, cleaner way to include this on every page.
sidebar = """
<p class='doNotDisplay doNotPrint'>This page&rsquo;s menu:</p>
<ul id='side-bar'>
<li><a href='/news/archive'>News Archive</a></li>
<li><a href='/news/search'>Search News</a></li>
</ul>
"""
class SearchForm(forms.Form):
"""
Class to represent a news search form under Django's newforms. This is used
to validate the input on the search_form view, as well as the search_results
view when we're picking the query out of GET. This makes searching safe
via the search form or by directly inputing values via GET key pairs.
"""
search_terms = forms.CharField(max_length=100, min_length=3, required=True)
def show_news(request, entry_id):
"""
Show an individual news entry. Display some basic information along with
the title and content.
"""
news_entry = get_object_or_404(NewsEntry, id=entry_id)
pagevars = {
"page_title": "News Entry",
"news_entry": news_entry,
"sidebar": sidebar
}
context_instance = RequestContext(request)
return render_to_response('news/show_entry.html', pagevars, context_instance)
def news_archive(request):
"""
Shows an archive of news entries.
TODO: Expand this a bit to allow filtering by month/year.
"""
news_entries = NewsEntry.objects.all().order_by('-date_posted')
# TODO: Move this to either settings.py or the SQL configuration.
entries_per_page = 15
pagevars = {
"page_title": "News Archive",
"browse_url": "/news/archive",
"sidebar": sidebar
}
return gv_list_detail.object_list(request, news_entries, template_name='news/archive.html', extra_context=pagevars, paginate_by=entries_per_page)
def search_form(request):
"""
Render the news search form. Don't handle much validation at all. If the
user enters a search term that meets the minimum, send them on their way
to the results page.
"""
if request.method == 'GET':
# A GET request was sent to the search page, load the value and
# validate it.
search_form = SearchForm(request.GET)
if search_form.is_valid():
# If the input is good, send them to the results page with the
# query attached in GET variables.
return HttpResponseRedirect('/news/search/results/?search_terms='+ search_form.cleaned_data['search_terms'])
else:
# Brand new search, nothing has been sent just yet.
search_form = SearchForm()
pagevars = {
"page_title": "Search News",
"search_form": search_form,
"debug": settings.DEBUG,
"sidebar": sidebar
}
context_instance = RequestContext(request)
return render_to_response('news/search_form.html', pagevars, context_instance)
def search_results(request):
"""
Shows an archive of news entries. Use the generic news browsing template.
"""
# TODO: Move this to either settings.py or the SQL configuration.
entries_per_page = 15
# Load the form values from GET to validate against.
search_form = SearchForm(request.GET)
# You have to call is_valid() or cleaned_data won't be populated.
valid_search = search_form.is_valid()
# This is the safe data that we can pass to queries without huge worry of
# badStuff(tm).
cleaned_get = search_form.cleaned_data
# Perform searches that match the title and contents.
# TODO: Allow the user to specify what to match against and in what
# topics/categories.
news_entries = NewsEntry.objects.filter(Q(title__contains=cleaned_get['search_terms']) | Q(body__contains=cleaned_get['search_terms']))
pagevars = {
"game_name": settings.SERVERNAME,
"page_title": "Search Results",
"searchtext": cleaned_get['search_terms'],
"browse_url": "/news/search/results",
"sidebar": sidebar
}
return gv_list_detail.object_list(request, news_entries, template_name='news/archive.html', extra_context=pagevars, paginate_by=entries_per_page)

View file

@ -0,0 +1,11 @@
{% extends "admin/base.html" %}
{% load i18n %}
{% block title %}{{ title }} | {% trans 'Evennia site admin' %}{% endblock %}
{% block branding %}
<h1 id="site-name">{% trans 'Evennia database administration' %}
<a href="/">(Back)</a> </h1>
{% endblock %}
{% block nav-global %}{% endblock %}

View file

@ -0,0 +1,242 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% load adminmedia %}{% admin_media_prefix %}css/dashboard.css" />{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block bodyclass %}dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
<div id="content-main">
{% if app_list %}
{% for app in app_list %}
{% if app.name in evennia_userapps %}
<div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.perms.add %}
<td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.perms.change %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endfor %}
<h1>In-game entities</h1>
{% for app in app_list %}
{% if app.name in evennia_entityapps %}
<div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.perms.add %}
<td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.perms.change %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endfor %}
<h1>Game setups and configs</h1>
{% for app in app_list %}
{% if app.name in evennia_setupapps %}
<div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.perms.add %}
<td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.perms.change %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endfor %}
<h1>Connection protocols</h1>
{% for app in app_list %}
{% if app.name in evennia_connectapps %}
<div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.perms.add %}
<td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.perms.change %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endfor %}
<h1>Website Specific</h1>
{% for app in app_list %}
{% if app.name in evennia_websiteapps %}
<div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
{% for model in app.models %}
<tr>
{% if model.perms.change %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.perms.add %}
<td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.perms.change %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endfor %}
{% else %}
<p>{% trans "You don't have permission to edit anything." %}</p>
{% endif %}
</div>
{% endblock %}
{% block sidebar %}
<div id="content-related">
<div class="module" id="recent-actions-module">
<h2>{% trans 'Recent Actions' %}</h2>
<h3>{% trans 'My Actions' %}</h3>
{% load log %}
{% get_admin_log 10 as admin_log for_user user %}
{% if not admin_log %}
<p>{% trans 'None yet.' %}</p>
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
{% if entry.is_deletion %}
{{ entry.object_repr }}
{% else %}
<a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
{% endif %}
<br/>
{% if entry.content_type %}
<span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span>
{% else %}
<span class="mini quiet">{% trans 'Unknown content' %}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,90 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-AU">
<head>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="author" content="haran" />
<meta name="generator" content="haran" />
{% if sidebar %}
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/prosimii-screen-alt.css" media="screen" title="Prosimii (Sidebar)" />
{% else %}
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/prosimii-screen.css" media="screen" title="Prosimii" />
{% endif %}
<link rel="stylesheet alternative" type="text/css" href="{{MEDIA_URL}}css/prosimii-print.css" media="screen" title="Print Preview" />
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/prosimii-print.css" media="print" />
{% block header_ext %}
{% endblock %}
<title>{{game_name}} - {% if flatpage %}{{flatpage.title}}{% else %}{% block titleblock %}{{page_title}}{% endblock %}{% endif %}</title>
</head>
<body>
<!-- For non-visual user agents: -->
<div id="top"><a href="#main-copy" class="doNotDisplay doNotPrint">Skip to main content.</a></div>
<!-- ##### Header ##### -->
<div id="header">
<div class="superHeader">
<!--span>Sites:</span-->
<a href="http://evennia.com" title="The Python-based MUD server">Evennia.com</a>
</div>
<div class="midHeader">
<img src="/media/images/evennia_logo_small.png" align='left'/> <h1 class="headerTitle" lang="la">{{game_name}}</h1>
<div class="headerSubTitle" title="Slogan">
<!-- Insert a slogan here if you want -->
{{game_slogan}} &nbsp;
</div>
<br class="doNotDisplay doNotPrint" />
<div class="headerLinks">
<span class="doNotDisplay">Tools:</span>
{% if user.is_authenticated %}
<a href="/accounts/logout/">Log Out &laquo;</a>
<span class="doNotDisplay">|</span>
Logged in as {{user.username}} &laquo;
{% else %}
<a href="/accounts/login/">Log In &laquo;</a>
<span class="doNotDisplay">|</span>
<a href="/tbi">Register &laquo;</a>
{% endif %}
</div>
</div>
<div class="subHeader">
<span class="doNotDisplay">Navigation:</span>
<a href="/">Home</a> |
<a href="http://code.evennia.com/">About</a> |
<a href="http://code.google.com/p/evennia/wiki/Index">Documentation</a> |
<a href="/admin/">Admin Interface</a>
</div>
</div>
<!-- ##### Side Menu ##### -->
{% block sidebar %}{% endblock %}
<!-- ##### Main Copy ##### -->
<div id="main-copy">
{% block content %}
{% endblock %}
</div>
<!-- ##### Footer ##### -->
<div id="footer">
<span class="doNotPrint">
Template design by
<a href="http://www.oswd.org/designs/search/designer/id/3013/"
title="Other designs by haran">haran</a>.
Powered by
<a href="http://evennia.com">Evennia.</a>
<br \>
</span>
</div>
</body>
</html>

View file

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block header_ext %}
{% endblock %}
{% block sidebar %}
{% endblock %}
{% block content %}
<h1 id="alt-layout">{{flatpage.title}}</h1>
{{flatpage.content}}
{% endblock %}

View file

@ -0,0 +1,82 @@
{% extends "base.html" %}
{% block sidebar %}
{% endblock %}
{% block header_ext %}
{% endblock %}
{% block content %}
<div class="rowOfBoxes">
<div class="twoThirds noBorderOnLeft">
<h1>Welcome!</h1>
<p>Welcome to your new installation of Evennia, your friendly
neighborhood next-generation MUD server. You are looking at Evennia's web
presence, which can be expanded to a full-fledged site as
needed. Through the <a href="/admin">admin interface</a> you can view and edit the
database without logging into the game. Also take your time to
peruse our extensive online <a href="http://code.google.com/p/evennia/wiki/Index">documentation</a>.
<p>
Should you have any questions, concerns, bug reports, or
if you want to help out, don't hesitate to come join the
<a href="http://evennia.com">Evennia community</a> and get
your voice heard!
</p>
<i>(To edit this file, go to game/web/templates/prosimii/index.html.)</i>
</div>
<div class="oneThird">
<h1>Latest News</h1>
{% for entry in news_entries %}
<a href="/news/show/{{entry.id}}" class="newsHeading">{{entry.topic.name}}: {{entry.title}}</a>
<p class="newsDate">By {{entry.author.username}} on {{entry.date_posted|time}}</p>
<p class="newsSummary">{{entry.body|truncatewords:20}}</p>
{% endfor %}
<div class="more"><a href="/news/archive">More News &raquo;</a></div>
<p class="filler"><!-- Filler para to extend left vertical line --></p>
</div>
</div>
<div class="rowOfBoxes dividingBorderAbove">
<div class="quarter noBorderOnLeft">
<h1>Players</h1>
<p>
There are currently <strong>{{num_players_connected}}</strong> connected,
and a total of <strong>{{num_players_registered}}</strong> registered. Of these, <strong>{{num_players_registered_recent}}</strong> were created this week, and <strong>{{num_players_connected_recent}}</strong> have connected within the last seven days.
</p>
</div>
<div class="quarter">
<h1>Recently Connected</h1>
<ul>
{% for player in players_connected_recent %}
<li>{{player.user.username}} -- <em>{{player.user.last_login|timesince}} ago</em></li>
{% endfor %}
</ul>
<p class="filler"><!-- Filler para to extend left vertical line --></p>
</div>
<div class="quarter">
<h1>Database Stats</h1>
<ul>
<li>{{num_players_registered}} players</li>
<li>{{num_rooms}} rooms ({{num_exits}} exits) </li>
<li>{{num_objects}} objects total</li>
</ul>
</div>
<div class="quarter">
<h1>Evennia</h1>
<p><a href="http://evennia.com">Evennia</a> is MUD server built in
<a href="http://python.org">Python</a>, on top of the
<a href="http://twistedmatrix.com">Twisted</a> and
<a href="http://djangoproject.com">Django</a> frameworks. This
combination of technologies allows for the quick and easy creation
of the game of your dreams - as simple or as complex as you like.</p>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,51 @@
{% extends "base.html" %}
{% block header_ext %}
{% endblock %}
{% block sidebar %}
{{sidebar|safe}}
{% endblock %}
{% block content %}
<h1 id="alt-layout">{{page_title}}</h1>
<strong>Navigation:</strong> <a href="{{browse_url}}/?page=1&search_terms={{searchtext|urlencode}}">First</a> |
{% if has_previous %}
<a href="{{browse_url}}/?page={{previous}}&search_terms={{searchtext|urlencode}}">Prev</a>
{% else %}
Prev
{% endif %}
| <em>{{page}}</em> of <em>{{pages}}</em> pages |
{% if has_next %}
<a href="{{browse_url}}/?page={{next}}&search_terms={{searchtext|urlencode}}">Next</a>
{% else %}
Next
{% endif %}
| <a href="{{browse_url}}/?page={{pages}}&search_terms={{searchtext|urlencode}}">Last</a>
{% for entry in object_list %}
<a href="/news/show/{{entry.id}}" class="newsHeading">{{entry.topic.name}}: {{entry.title}}</a>
<p class="newsDate">By {{entry.author.username}} on {{entry.date_posted|time}}</p>
<p class="newsSummary">{{entry.body|truncatewords:80}}</p>
{% endfor %}
<strong>Navigation:</strong> <a href="{{browse_url}}/?page=1&search_terms={{searchtext|urlencode}}">First</a> |
{% if has_previous %}
<a href="{{browse_url}}/?page={{previous}}&search_terms={{searchtext|urlencode}}">Prev</a>
{% else %}
Prev
{% endif %}
| <em>{{page}}</em> of <em>{{pages}}</em> pages |
{% if has_next %}
<a href="{{browse_url}}/?page={{next}}&search_terms={{searchtext|urlencode}}">Next</a>
{% else %}
Next
{% endif %}
| <a href="{{browse_url}}/?page={{pages}}&search_terms={{searchtext|urlencode}}">Last</a>
{% endblock %}

View file

@ -0,0 +1,19 @@
{% extends "base.html" %}
{% block header_ext %}
{% endblock %}
{% block sidebar %}
{{sidebar|safe}}
{% endblock %}
{% block content %}
<h1 id="alt-layout">Search News</h1>
<p>Enter a search term or phrase to search by. Matches will be made against
news titles and their contents. Searches must be at least three characters
long.</p>
<form method="GET">
{{search_form.search_terms}}
<button type="Submit">Search</button>
</form>
{% endblock %}

View file

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% block header_ext %}
{% endblock %}
{% block sidebar %}
{{sidebar|safe}}
{% endblock %}
{% block content %}
<h1 id="alt-layout">{{news_entry.topic.name}}: {{news_entry.title}}</h1>
<p class="newsDate">By {{news_entry.author.username}} on {{news_entry.date_posted|time}}</p>
<p class="newsSummary">{{news_entry.body}}</p>
{% endblock %}

View file

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block titleblock %}
Logged Out
{% endblock %}
{% block content %}
<h1 id="alt-layout">Logged Out</h1>
<p>You have been logged out.</p>
{% endblock %}

View file

@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block titleblock %}
Login
{% endblock %}
{% block content %}
<h1 id="alt-layout">Login</h1>
{% if user.is_authenticated %}
<p>You are already logged in!</p>
{% else %}
{% if form.has_errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="."{% csrf_token %} >
<table>
<tr>
<td><label for="id_username">Username:</label></td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td><label for="id_password">Password:</label></td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="Login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endif %}
{% endblock %}

View file

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block header_ext %}
{% endblock %}
{% block sidebar %}
{% endblock %}
{% block content %}
<h1 id="alt-layout">To Be Implemented...</h1>
<p>
This feature has yet to be implemented, but rest assured that it will be!
<br />
<br />
<br />
Eventually...
</p>
{% endblock %}

50
src/web/urls.py Executable file
View file

@ -0,0 +1,50 @@
#
# File that determines what each URL points to. This uses _Python_ regular
# expressions, not Perl's.
#
# See:
# http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3
#
from django.conf.urls.defaults import *
from django.conf import settings
from django.contrib import admin
# loop over all settings.INSTALLED_APPS and execute code in
# files named admin.py ine each such app (this will add those
# models to the admin site)
admin.autodiscover()
# Setup the root url tree from /
urlpatterns = patterns('',
# User Authentication
url(r'^accounts/login', 'django.contrib.auth.views.login'),
url(r'^accounts/logout', 'django.contrib.auth.views.logout'),
# Front page
url(r'^', include('src.web.website.urls')),
# News stuff
url(r'^news/', include('src.web.news.urls')),
# Page place-holder for things that aren't implemented yet.
url(r'^tbi/', 'src.web.website.views.to_be_implemented'),
# Admin interface
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
#url(r'^admin/(.*)', admin.site.root, name='admin'),
# favicon
url(r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url':'/media/images/favicon.ico'}),
)
# If you'd like to serve media files via Django (strongly not recommended!),
# open up your settings.py file and set SERVE_MEDIA to True. This is
# appropriate on a developing site, or if you're running Django's built-in
# test server. Normally you want a webserver that is optimized for serving
# static content to handle media files (apache, lighttpd).
if settings.SERVE_MEDIA:
urlpatterns += patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)

View file

View file

@ -0,0 +1,16 @@
import os, sys
# Calculate the path based on the location of the WSGI script.
web_dir = os.path.dirname(os.path.dirname(__file__))
workspace = os.path.dirname(os.path.dirname(web_dir))
sys.path.insert(0, workspace)
os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings'
import django.core.handlers.wsgi
_application = django.core.handlers.wsgi.WSGIHandler()
# This handles apps mounted in places other than the root mount point
def application(environ, start_response):
environ['PATH_INFO'] = environ['SCRIPT_NAME'] + environ['PATH_INFO']
return _application(environ, start_response)

View file

@ -0,0 +1,45 @@
# WARNING: mod_python is no longer the recommended way to run Evennia's
# web front end. This file is no longer actively maintained and may
# no longer work. We suggest using mod_wsgi unless absolutely necessary.
# Add this vhost file to your Apache sites-enabled directory, typically found
# at /etc/apache2/sites-enabled. You'll need to go through and change the
# /home/evennia to point to the correct home directory, and the evennia
# subdir must be under that home directory.
# A NOTE ON IMAGES/CSS: These files must be handled separately from the actual
# dynamic content which is interpreted by Python. You may host these static
# images/css from the same server or a different one. The static media
# is served from /home/evennia/evennia/media. The easiest way to serve
# this stuff is by either hosting them remotely or symlinking
# the media directory into an existing Apache site's directory.
# A NOTE ON ADMIN IMAGES/CSS: You'll need to create a symlink called
# 'amedia' under the media directory if you want to use the admin interface.
# This can be found in the Django package in your Python path. For example,
# the default is: /usr/lib/python2.4/site-packages/django/contrib/admin/media/
# although your location may vary.
<VirtualHost *>
# Set ServerName and ServerAdmin appropriately
ServerName evennia.somewhere.com
ServerAdmin someone@somewhere.com
DocumentRoot /home/evennia/evennia
<Directory "/home/evennia/evennia">
SetHandler python-program
PythonHandler django.core.handlers.modpython
PythonPath "['/home/evennia/evennia'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE settings
PythonDebug On
</Directory>
Alias /media/ "/home/evennia/evennia/media/"
<Directory "/home/evennia/evennia/media/">
SetHandler None
</Directory>
<LocationMatch "\.(jpg|gif|png|css)$">
SetHandler None
</LocationMatch>
</VirtualHost>

View file

@ -0,0 +1,51 @@
<VirtualHost *>
# This is an example mod_wsgi apache2 vhost. There are a number of
# things you'll need to change. They are commented below. Make sure
# you read and understand the stuff below.
# Copy this file to your apache2 vhosts directory before editing.
# This file is merely a template. The vhost directory is usually
# something like /etc/apache2/sites-enabled/.
# You'll want to replace the following with your domain info.
ServerName dev.evennia.com
ServerAlias www.dev.evennia.com
#
## BEGIN EVENNIA WEB CONFIG
#
# evennia_web is just an internal name for mod_wsgi and may be left
# The user and group options are the user and the group that the
# python code will be executed under. This user must have permissions
# to the evennia source.
WSGIDaemonProcess evennia_web user=evennia group=evennia threads=25
WSGIProcessGroup evennia_web
# This needs to be changed to the appropriate path on your django
# install. It serves admin site media.
# For Python 2.6, this is:
# /usr/lib/python2.6/dist-packages/django/contrib/admin/media/
Alias /media/amedia/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/"
<Directory "/usr/lib/python2.5/site-packages/django/contrib/admin/media">
Order allow,deny
Options Indexes
Allow from all
IndexOptions FancyIndexing
</Directory>
# Media Directory. This needs to be set to your equivalent path.
Alias /media/ "/home/evennia/evennia/game/web/media/"
<Directory "/home/evennia/evennia/game/web/media">
Order allow,deny
Options Indexes FollowSymLinks
Allow from all
IndexOptions FancyIndexing
</Directory>
# WSGI Config File. You'll need to update this path as well.
WSGIScriptAlias / /home/evennia/evennia/game/web/utils/apache_wsgi.conf
#
## END EVENNIA WEB CONFIG
#
</VirtualHost>

View file

@ -0,0 +1,46 @@
#
# This file defines global variables that will always be
# available in a view context without having to repeatedly
# include it. For this to work, this file is included in
# the settings file, in the TEMPLATE_CONTEXT_PROCESSORS
# tuple.
#
from django.db import models
from django.conf import settings
from src.utils.utils import get_evennia_version
# Determine the site name and server version
try:
GAME_NAME = settings.SERVERNAME.strip()
except AttributeError:
GAME_NAME = "Evennia"
SERVER_VERSION = get_evennia_version()
# Setup lists of the most relevant apps so
# the adminsite becomes more readable.
USER_RELATED = ['Auth', 'Players']
GAME_ENTITIES = ['Objects', 'Scripts', 'Comms', 'Help']
GAME_SETUP = ['Permissions', 'Config']
CONNECTIONS = ['Irc', 'Imc2']
WEBSITE = ['Flatpages', 'News', 'Sites']
# The main context processor function
def general_context(request):
"""
Returns common Evennia-related context stuff, which
is automatically added to context of all views.
"""
return {
'game_name': GAME_NAME,
'game_slogan': SERVER_VERSION,
'evennia_userapps': USER_RELATED,
'evennia_entityapps': GAME_ENTITIES,
'evennia_setupapps': GAME_SETUP,
'evennia_connectapps': CONNECTIONS,
'evennia_websiteapps':WEBSITE
}

View file

View file

@ -0,0 +1,7 @@
#
# Define database entities for the app.
#
from django.db import models

10
src/web/website/urls.py Normal file
View file

@ -0,0 +1,10 @@
"""
This structures the (simple) structure of the
webpage 'application'.
"""
from django.conf.urls.defaults import *
urlpatterns = patterns('src.web.website.views',
(r'^$', 'page_index'),
)

63
src/web/website/views.py Normal file
View file

@ -0,0 +1,63 @@
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.contrib.auth.models import User
from django.conf import settings
from src.config.models import ConfigValue
from src.objects.models import ObjectDB
from src.typeclasses.models import TypedObject
from src.players.models import PlayerDB
from src.web.news.models import NewsEntry
"""
This file contains the generic, assorted views that don't fall under one of
the other applications.
"""
def page_index(request):
"""
Main root page.
"""
# Some misc. configurable stuff.
# TODO: Move this to either SQL or settings.py based configuration.
fpage_player_limit = 4
fpage_news_entries = 2
# A QuerySet of recent news entries.
news_entries = NewsEntry.objects.all().order_by('-date_posted')[:fpage_news_entries]
# A QuerySet of the most recently connected players.
recent_users = PlayerDB.objects.get_recently_connected_players()[:fpage_player_limit]
exits = ObjectDB.objects.get_objs_with_attr('_destination')
rooms = [room for room in ObjectDB.objects.filter(db_home=None) if room not in exits]
pagevars = {
"page_title": "Front Page",
"news_entries": news_entries,
"players_connected_recent": recent_users,
"num_players_connected": ConfigValue.objects.conf('nr_sessions'),#len(PlayerDB.objects.get_connected_players()),
"num_players_registered": PlayerDB.objects.num_total_players(),
"num_players_connected_recent": len(PlayerDB.objects.get_recently_connected_players()),
"num_players_registered_recent": len(PlayerDB.objects.get_recently_created_players()),
"num_rooms": len(rooms),
"num_exits": len(exits),
"num_objects" : ObjectDB.objects.all().count()
}
context_instance = RequestContext(request)
return render_to_response('index.html', pagevars, context_instance)
def to_be_implemented(request):
"""
A notice letting the user know that this particular feature hasn't been
implemented yet.
"""
pagevars = {
"page_title": "To Be Implemented...",
}
context_instance = RequestContext(request)
return render_to_response('tbi.html', pagevars, context_instance)