More admin cleanup and doc writing
This commit is contained in:
parent
b95ec69d66
commit
b1b26bf489
7 changed files with 245 additions and 53 deletions
9
docs/source/Components/Web-Admin.md
Normal file
9
docs/source/Components/Web-Admin.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# The Web Admin
|
||||||
|
|
||||||
|
The Evennia _Web admin_ is a customized [Django admin site](https://docs.djangoproject.com/en/3.2/ref/contrib/admin/)
|
||||||
|
and is used for manipulating the game database using a graphical interface.
|
||||||
|
|
||||||
|
All actions done in the admin can also be done in-game by use of Admin- or
|
||||||
|
Builder-commands. The only exception is the assigning of `staff` flags for
|
||||||
|
allowing users access to the admin itself.
|
||||||
|
|
||||||
|
|
@ -4,7 +4,7 @@ When Evennia starts it also spins up its own Twisted-based web server. The
|
||||||
webserver is responsible for serving the html pages of the game's website. It
|
webserver is responsible for serving the html pages of the game's website. It
|
||||||
can also serve static resources like images and music.
|
can also serve static resources like images and music.
|
||||||
|
|
||||||
The webclient runs as part of the [Server](Portal-And-Server) process of
|
The webclient runs as part of the [Server](./Portal-And-Server) process of
|
||||||
Evennia. This means that it can directly access cached objects modified
|
Evennia. This means that it can directly access cached objects modified
|
||||||
in-game, and there is no risk of working with objects that are temporarily
|
in-game, and there is no risk of working with objects that are temporarily
|
||||||
out-of-sync in the database.
|
out-of-sync in the database.
|
||||||
|
|
@ -12,15 +12,15 @@ out-of-sync in the database.
|
||||||
The webserver runs on Twisted and is meant to be used in a production
|
The webserver runs on Twisted and is meant to be used in a production
|
||||||
environment. It leverages the Django web framework and provides:
|
environment. It leverages the Django web framework and provides:
|
||||||
|
|
||||||
- A [Game Website](Website) - this is what you see when you go to
|
- A [Game Website](./Website) - this is what you see when you go to
|
||||||
- `localhost:4001`. The look of the website is meant to be customized to your
|
`localhost:4001`. The look of the website is meant to be customized to your
|
||||||
- game. Users logged into the website will be auto-logged into the game if they
|
game. Users logged into the website will be auto-logged into the game if they
|
||||||
- do so with the webclient since they share the same login credentials (there
|
do so with the webclient since they share the same login credentials (there
|
||||||
- is no way to safely do auto-login with telnet clients).
|
is no way to safely do auto-login with telnet clients).
|
||||||
- The [Web Admin](Web-Admin) is based on the Django web admin and allows you to
|
- The [Web Admin](Web-Admin) is based on the Django web admin and allows you to
|
||||||
- edit the game database in a graphical interface.
|
edit the game database in a graphical interface.
|
||||||
- The [Webclient](Webclient) page is served by the webserver, but the actual
|
- The [Webclient](./Webclient) page is served by the webserver, but the actual
|
||||||
- game communication (sending/receiving data) is done by the javascript client
|
game communication (sending/receiving data) is done by the javascript client
|
||||||
on the page opening a websocket connection directly to Evennia's Portal.
|
on the page opening a websocket connection directly to Evennia's Portal.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ it operates independently from Evennia. Small snippets of javascript can be
|
||||||
used on a page to have buttons react, make small animations etc that doesn't
|
used on a page to have buttons react, make small animations etc that doesn't
|
||||||
require the server.
|
require the server.
|
||||||
|
|
||||||
In the case of the [Webclient](Webclient), Evennia will load the Webclient page
|
In the case of the [Webclient](./Webclient), Evennia will load the Webclient page
|
||||||
as above, but the page then initiates Javascript code (a lot of it) responsible
|
as above, but the page then initiates Javascript code (a lot of it) responsible
|
||||||
for actually displaying the client GUI, allows you to resize windows etc.
|
for actually displaying the client GUI, allows you to resize windows etc.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
# Game Website
|
# Game Website
|
||||||
|
|
||||||
When Evennia starts it will also start a [Webserver](Webserver) as part of the
|
When Evennia starts it will also start a [Webserver](./Webserver) as part of the
|
||||||
[Server](Portal-And-Server) process. This uses Django to serve a simple but
|
[Server](./Portal-And-Server) process. This uses [Django](https://docs.djangoproject.com)
|
||||||
functional default game website. With the default setup, open your browser to
|
to present a simple but functional default game website. With the default setup,
|
||||||
`localhost:4001` or `127.0.0.1:4001` to see it.
|
open your browser to `localhost:4001` or `127.0.0.1:4001` to see it.
|
||||||
|
|
||||||
The website allows existing players to log in using an account-name and
|
The website allows existing players to log in using an account-name and
|
||||||
password they previously used to register with the game. If a user logs in with
|
password they previously used to register with the game. If a user logs in with
|
||||||
the [Webclient](Webclient) they will also log into the website and vice-versa.
|
the [Webclient](./Webclient) they will also log into the website and vice-versa.
|
||||||
So if you are logged into the website, opening the webclient will automatically
|
So if you are logged into the website, opening the webclient will automatically
|
||||||
log you into the game as that account.
|
log you into the game as that account.
|
||||||
|
|
||||||
|
|
@ -27,12 +27,11 @@ In the top menu you can find
|
||||||
show a list of all channels available to you and allow you to view the latest
|
show a list of all channels available to you and allow you to view the latest
|
||||||
discussions. Most channels require logging in, but the `Public` channel can
|
discussions. Most channels require logging in, but the `Public` channel can
|
||||||
also be viewed by non-loggedin users.
|
also be viewed by non-loggedin users.
|
||||||
- Help - This ties the in-game [Help system](Help-System) to the website. All
|
- Help - This ties the in-game [Help system](./Help-System) to the website. All
|
||||||
database-based help entries that are publicly available or accessible to your
|
database-based help entries that are publicly available or accessible to your
|
||||||
account can be read. This is a good way to present a body of help for people
|
account can be read. This is a good way to present a body of help for people
|
||||||
to read outside of the game.
|
to read outside of the game.
|
||||||
- Play Online - This opens the [Webclient](Webclient) in the browser.
|
- Play Online - This opens the [Webclient](./Webclient) in the browser.
|
||||||
|
|
||||||
|
|
||||||
## Modifying the default Website
|
## Modifying the default Website
|
||||||
|
|
||||||
|
|
@ -41,7 +40,13 @@ You'll mostly be doing so in your settings file
|
||||||
(`mygame/server/conf/settings.py` and in the gamedir's `web/folder`
|
(`mygame/server/conf/settings.py` and in the gamedir's `web/folder`
|
||||||
(`mygame/web/` if your game folder is `mygame/`).
|
(`mygame/web/` if your game folder is `mygame/`).
|
||||||
|
|
||||||
As explained on the [Webserver](Webserver) page, the process for getting a web
|
> When testing your modifications, it's a good idea to add `DEBUG = True` to
|
||||||
|
> your settings file. This will give you nice informative tracebacks directly
|
||||||
|
> in your browser instead of generic 404 or 500 error pages. Just remember that
|
||||||
|
> DEBUG mode leaks memory (for retaining debug info) and is *not* safe to use
|
||||||
|
> for a production game!
|
||||||
|
|
||||||
|
As explained on the [Webserver](./Webserver) page, the process for getting a web
|
||||||
page is
|
page is
|
||||||
|
|
||||||
1. Web browser sends HTTP request to server with an URL
|
1. Web browser sends HTTP request to server with an URL
|
||||||
|
|
@ -74,7 +79,7 @@ structure (leaving out stuff not relevant to the website):
|
||||||
website/
|
website/
|
||||||
urls.py
|
urls.py
|
||||||
views/
|
views/
|
||||||
(all python files related to website)
|
(python files related to website)
|
||||||
|
|
||||||
urls.py
|
urls.py
|
||||||
|
|
||||||
|
|
@ -126,28 +131,40 @@ Overridden views (Python modules) also need an additional tweak to the
|
||||||
`website/urls.py` file - you must make sure to repoint the url to the new
|
`website/urls.py` file - you must make sure to repoint the url to the new
|
||||||
version rather than it using the original.
|
version rather than it using the original.
|
||||||
|
|
||||||
### Title and blurb
|
## Examples of commom web changes
|
||||||
|
|
||||||
|
```important::
|
||||||
|
|
||||||
|
Django is a very mature web-design framework. There are endless
|
||||||
|
internet-tutorials, courses and books available to explain how to use Django.
|
||||||
|
So these examples only serve as a first primer to get you started.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Change Title and blurb
|
||||||
|
|
||||||
The website's title and blurb are simply changed by tweaking
|
The website's title and blurb are simply changed by tweaking
|
||||||
`settings.SERVERNAME` and `settings.GAME_SLOGAN`. Your settings file is in
|
`settings.SERVERNAME` and `settings.GAME_SLOGAN`. Your settings file is in
|
||||||
`mygame/server/conf/settings.py`, just change `SERVERNAME = "My Awesome Game"`
|
`mygame/server/conf/settings.py`, just set/add
|
||||||
and add `GAME_SLOGAN = "The best game in the world"` or something.
|
|
||||||
|
|
||||||
### Logo
|
SERVERNAME = "My Awesome Game"
|
||||||
|
GAME_SLOGAN = "The best game in the world"
|
||||||
|
|
||||||
|
### Change the Logo
|
||||||
|
|
||||||
The Evennia googly-eyed snake logo is probably not what you want for your game.
|
The Evennia googly-eyed snake logo is probably not what you want for your game.
|
||||||
The template looks for a file `web/static/website/images/evennia_logo.png`. Just
|
The template looks for a file `web/static/website/images/evennia_logo.png`. Just
|
||||||
plop your own PNG logo (64x64 pixels large) in there and name it the same.
|
plop your own PNG logo (64x64 pixels large) in there and name it the same.
|
||||||
|
|
||||||
### Index page
|
|
||||||
|
|
||||||
This is the front page of the website (the 'index' in HTML parlance).
|
### Change front page HTML
|
||||||
|
|
||||||
#### Index HTML template
|
The front page of the website is usually referred to as the 'index' in HTML
|
||||||
|
parlance.
|
||||||
|
|
||||||
The frontpage template is found in
|
The frontpage template is found in `evennia/web/templates/website/index.html`.
|
||||||
`evennia/web/templates/website/index.html`. Just copy this to the equivalent place in
|
Just copy this to the equivalent place in `mygame/web/`. Modify it there and
|
||||||
`mygame/web/`. Modify it there and reload the server to see your changes.
|
reload the server to see your changes.
|
||||||
|
|
||||||
Django templates has a few special features that separate them from normal HTML
|
Django templates has a few special features that separate them from normal HTML
|
||||||
documents - they contain a special templating language marked with `{% ... %}` and
|
documents - they contain a special templating language marked with `{% ... %}` and
|
||||||
|
|
@ -176,18 +193,50 @@ Some important things to know:
|
||||||
that as `{{ stats.hp }}` to display `10` at that location to display `10` at
|
that as `{{ stats.hp }}` to display `10` at that location to display `10` at
|
||||||
that location.
|
that location.
|
||||||
|
|
||||||
|
|
||||||
This allows for template inheritance (making it easier to make all
|
This allows for template inheritance (making it easier to make all
|
||||||
pages look the same without rewriting the same thing over and over)
|
pages look the same without rewriting the same thing over and over)
|
||||||
|
|
||||||
There's a lot more information to be found in the [Django template language documentation](https://docs.djangoproject.com/en/3.2/ref/templates/language/).
|
There's a lot more information to be found in the [Django template language documentation](https://docs.djangoproject.com/en/3.2/ref/templates/language/).
|
||||||
|
|
||||||
#### Index View
|
#### Change front page functionality
|
||||||
|
|
||||||
To find where the index view is found, we look in `evennia/web/website/urls.py`. Here
|
The logic is all in the view. To find where the index-page view is found, we
|
||||||
we find the following line:
|
look in `evennia/web/website/urls.py`. Here we find the following line:
|
||||||
|
|
||||||
This is found in `evennia/web/website/views/index.py`. If you don't know
|
```python
|
||||||
|
# in evennia/web/website/urls.py
|
||||||
|
|
||||||
|
...
|
||||||
|
# website front page
|
||||||
|
path("", index.EvenniaIndexView.as_view(), name="index"),
|
||||||
|
...
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The first `""` is the empty url - root - what you get if you just enter `localhost:4001/`
|
||||||
|
with no extra path. As expected, this leads to the index page. By looking at the imports
|
||||||
|
we find the view is in in `evennia/web/website/views/index.py`.
|
||||||
|
|
||||||
|
Copy this file to the corresponding location in `mygame/web`. Then tweak your `mygame/web/website/urls.py`
|
||||||
|
file to point to the new file:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# in mygame/web/website/urls.py
|
||||||
|
|
||||||
|
# ...
|
||||||
|
|
||||||
|
from web.website.views import index
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", index.EvenniaIndexView.as_view(), name="index")
|
||||||
|
|
||||||
|
]
|
||||||
|
# ...
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
So we just import `index` from the new location and point to it. After a reload
|
||||||
|
the front page will now redirect to use your copy rather than the original.
|
||||||
|
|
||||||
The frontpage view is a class `EvenniaIndexView`. This is a [Django class-based view](https://docs.djangoproject.com/en/3.2/topics/class-based-views/).
|
The frontpage view is a class `EvenniaIndexView`. This is a [Django class-based view](https://docs.djangoproject.com/en/3.2/topics/class-based-views/).
|
||||||
It's a little less visible what happens in a class-based view than in a function (since
|
It's a little less visible what happens in a class-based view than in a function (since
|
||||||
|
|
@ -203,7 +252,111 @@ template. In the index-page's case we want the game stats (number of recent
|
||||||
players etc). These are then made available to use in `{{ ... }}` slots in the
|
players etc). These are then made available to use in `{{ ... }}` slots in the
|
||||||
template as described in the previous section.
|
template as described in the previous section.
|
||||||
|
|
||||||
### Other website pages
|
### Change other website pages
|
||||||
|
|
||||||
The other sub pages are handled in the same way - copy the template or static
|
The other sub pages are handled in the same way - copy the template or static
|
||||||
resource to the right place
|
resource to the right place, or copy the view and repoint your `website/urls.py` to
|
||||||
|
your copy. Just remember to reload.
|
||||||
|
|
||||||
|
## Adding a new web page
|
||||||
|
|
||||||
|
### Using Flat Pages
|
||||||
|
|
||||||
|
The absolutely simplest way to add a new web page is to use the `Flat Pages`
|
||||||
|
app available in the [Web Admin](Web-Admin). The page will appear with the same
|
||||||
|
styling as the rest of the site.
|
||||||
|
|
||||||
|
For the `Flat pages` module to work you must first set up a _Site_ (or
|
||||||
|
domain) to use. You only need to this once.
|
||||||
|
|
||||||
|
- Go to the Web admin and select `Sites`. If your
|
||||||
|
game is at `mygreatgame.com`, that's the domain you need to add. For local
|
||||||
|
experimentation, add the domain `localhost:4001`. Note the `id` of the domain
|
||||||
|
(look at the url when you click on the new domain, if it's for example
|
||||||
|
`http://localhost:4001/admin/sites/site/2/change/`, then the id is `2`).
|
||||||
|
- Now add the line `SITE_ID = <id>` to your settings file.
|
||||||
|
|
||||||
|
Next you create new pages easily.
|
||||||
|
|
||||||
|
- Go the `Flat Pages` web admin and choose to add a new flat page.
|
||||||
|
- Set the url. If you want the page to appear as e.g. `localhost:4001/test/`, then
|
||||||
|
add `/test/` here. You need to add both leading and trailing slashes.
|
||||||
|
- Set `Title` to the name of the page.
|
||||||
|
- The `Content` is the HTML content of the body of the page. Go wild!
|
||||||
|
- Finally pick the `Site` you made before, and save.
|
||||||
|
- (in the advanced section you can make it so that you have to login to see the page etc).
|
||||||
|
|
||||||
|
You can now go to `localhost:4001/test/` and see your new page!
|
||||||
|
|
||||||
|
### Add Custom new page
|
||||||
|
|
||||||
|
The `Flat Pages` page doesn't allow for (much) dynamic content and customization. For
|
||||||
|
this you need to add the needed components yourself.
|
||||||
|
|
||||||
|
Let's see how to make a `/test/` page from scratch.
|
||||||
|
|
||||||
|
- Add a new `test.html` file under `mygame/web/templates/website/`. Easiest is to base
|
||||||
|
this off an existing file. Make sure to `{% extend base.html %}` if you want to
|
||||||
|
get the same styling as the rest of your site.
|
||||||
|
- Add a new view `testview.py` under `mygame/web/website/views/` (don't name it `test.py` or
|
||||||
|
Django/Evennia will think it contains unit tests). Add a view there to process
|
||||||
|
your page. This is a minimal view to start from (read much more [in the Django docs](https://docs.djangoproject.com/en/3.2/topics/class-based-views/)):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# mygame/web/website/views/testview.py
|
||||||
|
|
||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
class MyTestView(TemplateView):
|
||||||
|
template_name = "website/test.html"
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- Finally, point to your view from the `mygame/web/website/urls.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# in mygame/web/website/urls.py
|
||||||
|
|
||||||
|
# ...
|
||||||
|
from web.website.views import testview
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# ...
|
||||||
|
# we can skip the initial / here
|
||||||
|
path("test/", testview.MyTestView.as_view())
|
||||||
|
]
|
||||||
|
|
||||||
|
```
|
||||||
|
- Reload the server and your new page is available. You can now continue to add
|
||||||
|
all sorts of advanced dynamic content through your view and template!
|
||||||
|
|
||||||
|
|
||||||
|
## User forms
|
||||||
|
|
||||||
|
All the pages created so far deal with _presenting_ information to the user.
|
||||||
|
It's also possible for the user to _input_ data on the page through _forms_. An
|
||||||
|
example would be a page of fields and sliders you fill in to create a
|
||||||
|
character, with a big 'Submit' button at the bottom.
|
||||||
|
|
||||||
|
Firstly, this must be represented in HTML. The `<form> ... </form>` is a
|
||||||
|
standard HTML element you need to add to your template. It also has some other
|
||||||
|
requirements, such as `<input>` and often Javascript components as well (but
|
||||||
|
usually Django will help with this). If you are unfamiliar with how HTML forms
|
||||||
|
work, [read about them here](https://docs.djangoproject.com/en/3.2/topics/forms/#html-forms).
|
||||||
|
|
||||||
|
The basic gist of it is that when you click to 'submit' the form, a POST HTML
|
||||||
|
request will be sent to the server containing the data the user entered. It's
|
||||||
|
now up to the server to make sure the data makes sense (validation) and then
|
||||||
|
process the input somehow (like creating a new character).
|
||||||
|
|
||||||
|
On the backend side, we need to specify the logic for validating and processing
|
||||||
|
the form data. This is done by the `Form` [Django class](https://docs.djangoproject.com/en/3.2/topics/forms/#forms-in-django).
|
||||||
|
This specifies _fields_ on itself that define how to validate that piece of data.
|
||||||
|
|
||||||
|
The form is then linked into the view-class by adding `form_class = MyFormClass` to
|
||||||
|
the view (next to `template_name`).
|
||||||
|
|
||||||
|
There are several example forms in `evennia/web/website/forms.py`. It's also a good
|
||||||
|
idea to read [Building a form in Django](https://docs.djangoproject.com/en/3.2/topics/forms/#building-a-form-in-django)
|
||||||
|
on the Django website - it covers all you need.
|
||||||
|
|
|
||||||
|
|
@ -340,7 +340,8 @@ div.code-block-caption {
|
||||||
}
|
}
|
||||||
|
|
||||||
.versionchanged {
|
.versionchanged {
|
||||||
background-color: #f7f7f7;
|
background-color: #b7e6e8;
|
||||||
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.deprecated {
|
.deprecated {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Toc
|
# Toc
|
||||||
- [API root](api/evennia-api.rst)
|
|
||||||
- [Coding/Coding Introduction](Coding/Coding-Introduction)
|
- [Coding/Coding Introduction](Coding/Coding-Introduction)
|
||||||
- [Coding/Coding Overview](Coding/Coding-Overview)
|
- [Coding/Coding Overview](Coding/Coding-Overview)
|
||||||
- [Coding/Continuous Integration](Coding/Continuous-Integration)
|
- [Coding/Continuous Integration](Coding/Continuous-Integration)
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
- [Components/Typeclasses](Components/Typeclasses)
|
- [Components/Typeclasses](Components/Typeclasses)
|
||||||
- [Components/Webclient](Components/Webclient)
|
- [Components/Webclient](Components/Webclient)
|
||||||
- [Components/Webserver](Components/Webserver)
|
- [Components/Webserver](Components/Webserver)
|
||||||
|
- [Components/Website](Components/Website)
|
||||||
- [Concepts/Async Process](Concepts/Async-Process)
|
- [Concepts/Async Process](Concepts/Async-Process)
|
||||||
- [Concepts/Banning](Concepts/Banning)
|
- [Concepts/Banning](Concepts/Banning)
|
||||||
- [Concepts/Bootstrap & Evennia](Concepts/Bootstrap-&-Evennia)
|
- [Concepts/Bootstrap & Evennia](Concepts/Bootstrap-&-Evennia)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
# in the web admin interface.
|
# in the web admin interface.
|
||||||
#
|
#
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
from django.contrib.admin.options import IS_POPUP_VAR
|
from django.contrib.admin.options import IS_POPUP_VAR
|
||||||
|
|
@ -76,6 +77,16 @@ class AccountChangeForm(UserChangeForm):
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# is_superuser = forms.BooleanField(
|
||||||
|
# label = "Superuser status",
|
||||||
|
# required=False,
|
||||||
|
# help_text="Superusers bypass all in-game locks and has all "
|
||||||
|
# "permissions without explicitly assigning them. Usually "
|
||||||
|
# "only one superuser (user #1) is needed, new superusers "
|
||||||
|
# "can be created by setting the `is_superuser` flag in code "
|
||||||
|
# "or by the `evennia createsuperuser` CLI command."
|
||||||
|
# )
|
||||||
|
|
||||||
def clean_username(self):
|
def clean_username(self):
|
||||||
"""
|
"""
|
||||||
Clean the username and check its existence.
|
Clean the username and check its existence.
|
||||||
|
|
@ -209,8 +220,8 @@ class AccountAdmin(BaseUserAdmin):
|
||||||
search_fields = ["=id", "^username", "db_typeclass_path"]
|
search_fields = ["=id", "^username", "db_typeclass_path"]
|
||||||
ordering = ["-db_date_created", "id"]
|
ordering = ["-db_date_created", "id"]
|
||||||
list_filter = ["is_superuser", "is_staff", "db_typeclass_path"]
|
list_filter = ["is_superuser", "is_staff", "db_typeclass_path"]
|
||||||
inlines = [AccountTagInline, AccountAttributeInline, ObjectPuppetInline]
|
inlines = [AccountTagInline, AccountAttributeInline]
|
||||||
readonly_fields = ["db_date_created", "serialized_string"]
|
readonly_fields = ["db_date_created", "serialized_string", "puppeted_objects"]
|
||||||
view_on_site = False
|
view_on_site = False
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(
|
(
|
||||||
|
|
@ -223,6 +234,7 @@ class AccountAdmin(BaseUserAdmin):
|
||||||
"db_date_created",
|
"db_date_created",
|
||||||
"db_lock_storage",
|
"db_lock_storage",
|
||||||
"db_cmdset_storage",
|
"db_cmdset_storage",
|
||||||
|
"puppeted_objects",
|
||||||
"serialized_string",
|
"serialized_string",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -265,11 +277,31 @@ class AccountAdmin(BaseUserAdmin):
|
||||||
from evennia.utils import dbserialize
|
from evennia.utils import dbserialize
|
||||||
|
|
||||||
return str(dbserialize.pack_dbobj(obj))
|
return str(dbserialize.pack_dbobj(obj))
|
||||||
|
|
||||||
serialized_string.help_text = (
|
serialized_string.help_text = (
|
||||||
"Copy & paste this string into an Attribute's `value` field to store it there."
|
"Copy & paste this string into an Attribute's `value` field to store it there."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def puppeted_objects(self, obj):
|
||||||
|
"""
|
||||||
|
Get any currently puppeted objects (read only list)
|
||||||
|
|
||||||
|
"""
|
||||||
|
return mark_safe(
|
||||||
|
", ".join(
|
||||||
|
'<a href="{url}">{name}</a>'.format(
|
||||||
|
url=reverse("admin:objects_objectdb_change", args=[obj.id]),
|
||||||
|
name=obj.db_key)
|
||||||
|
for obj in ObjectDB.objects.filter(db_account=obj)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
puppeted_objects.help_text = (
|
||||||
|
"Objects currently puppeted by this Account. "
|
||||||
|
"Link new ones from the `Objects` admin page.<BR>"
|
||||||
|
"Note that these will disappear when a user unpuppets or goes offline - "
|
||||||
|
"this is normal."
|
||||||
|
)
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Overrides help texts.
|
Overrides help texts.
|
||||||
|
|
@ -277,7 +309,9 @@ class AccountAdmin(BaseUserAdmin):
|
||||||
"""
|
"""
|
||||||
help_texts = kwargs.get("help_texts", {})
|
help_texts = kwargs.get("help_texts", {})
|
||||||
help_texts["serialized_string"] = self.serialized_string.help_text
|
help_texts["serialized_string"] = self.serialized_string.help_text
|
||||||
|
help_texts["puppeted_objects"] = self.puppeted_objects.help_text
|
||||||
kwargs["help_texts"] = help_texts
|
kwargs["help_texts"] = help_texts
|
||||||
|
|
||||||
return super().get_form(request, obj, **kwargs)
|
return super().get_form(request, obj, **kwargs)
|
||||||
|
|
||||||
@sensitive_post_parameters_m
|
@sensitive_post_parameters_m
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
"""
|
"""
|
||||||
This structures the website.
|
This redirects to website sub-pages.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from django import views as django_views
|
from .views import (
|
||||||
from .views import (index, errors, accounts, help as helpviews, channels,
|
index, errors, accounts, help as helpviews, channels, characters)
|
||||||
characters)
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# website front page
|
# website front page
|
||||||
#url(r"^$", index.EvenniaIndexView.as_view(), name="index"),
|
|
||||||
path("", index.EvenniaIndexView.as_view(), name="index"),
|
path("", index.EvenniaIndexView.as_view(), name="index"),
|
||||||
|
|
||||||
# errors
|
# errors
|
||||||
|
|
@ -23,18 +22,12 @@ urlpatterns = [
|
||||||
|
|
||||||
# Help Topics
|
# Help Topics
|
||||||
path("help/", helpviews.HelpListView.as_view(), name="help"),
|
path("help/", helpviews.HelpListView.as_view(), name="help"),
|
||||||
# url(r"^help/(?P<category>[\w\d\-]+)/(?P<topic>[\w\d\-]+)/$",
|
|
||||||
# helpviews.HelpDetailView.as_view(),
|
|
||||||
# name="help-entry-detail"),
|
|
||||||
path(r"help/<str:category>/<str:topic>/",
|
path(r"help/<str:category>/<str:topic>/",
|
||||||
helpviews.HelpDetailView.as_view(),
|
helpviews.HelpDetailView.as_view(),
|
||||||
name="help-entry-detail"),
|
name="help-entry-detail"),
|
||||||
|
|
||||||
# Channels
|
# Channels
|
||||||
path("channels/", channels.ChannelListView.as_view(), name="channels"),
|
path("channels/", channels.ChannelListView.as_view(), name="channels"),
|
||||||
# url(r"^channels/(?P<slug>[\w\d\-]+)/$",
|
|
||||||
# channels.ChannelDetailView.as_view(),
|
|
||||||
# name="channel-detail"),
|
|
||||||
path("channels/<str:slug>/",
|
path("channels/<str:slug>/",
|
||||||
channels.ChannelDetailView.as_view(),
|
channels.ChannelDetailView.as_view(),
|
||||||
name="channel-detail"),
|
name="channel-detail"),
|
||||||
|
|
@ -65,6 +58,7 @@ urlpatterns = [
|
||||||
# This sets up the server if the user want to run the Django test server (this
|
# This sets up the server if the user want to run the Django test server (this
|
||||||
# is not recommended and is usually unnecessary).
|
# is not recommended and is usually unnecessary).
|
||||||
if settings.SERVE_MEDIA:
|
if settings.SERVE_MEDIA:
|
||||||
|
from django import views as django_views
|
||||||
urlpatterns.extend(
|
urlpatterns.extend(
|
||||||
[
|
[
|
||||||
path("media/<str:path>",
|
path("media/<str:path>",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue