1.2 Proposal: django debug toolbar in contrib

24 views
Skip to first unread message

Mat Clayton

unread,
Aug 11, 2009, 8:32:25 AM8/11/09
to django-d...@googlegroups.com
Hey all,

For us of the most useful developments in the django community recently has been the django debug toolbar.

http://github.com/robhudson/django-debug-toolbar/tree/master/debug_toolbar

This seems to be branching and growing very rapidly on github, however lots of branches are appearing and it is getting harder to track which ones contain the best or most complete featureset, Wouldn't it take some sense to combine these into a single toolbar and incorporate it into a contrib package? In development I would argue that most users require very similar features and could benefit from a unified toolbar, and that the use cases are common enough to justify a contrib package. If the original authors are happy for it to be combined? I may have time to help out with this, but time is quickly being absorbed by other projects, but thought now was probably the right time to bounce the suggestion about.

Mat

--
--
Matthew Clayton | Founder/CEO
Wakari Limited

twitter http://www.twitter.com/matclayton

email m...@wakari.co.uk
mobile +44 7872007851

skype matclayton

Russell Keith-Magee

unread,
Aug 11, 2009, 10:01:57 AM8/11/09
to django-d...@googlegroups.com
On Tue, Aug 11, 2009 at 8:32 PM, Mat Clayton<m...@wakari.co.uk> wrote:
> Hey all,
>
> For us of the most useful developments in the django community recently has
> been the django debug toolbar.
>
> http://github.com/robhudson/django-debug-toolbar/tree/master/debug_toolbar
>
> This seems to be branching and growing very rapidly on github, however lots
> of branches are appearing and it is getting harder to track which ones
> contain the best or most complete featureset, Wouldn't it take some sense to
> combine these into a single toolbar and incorporate it into a contrib
> package? In development I would argue that most users require very similar
> features and could benefit from a unified toolbar, and that the use cases
> are common enough to justify a contrib package. If the original authors are
> happy for it to be combined? I may have time to help out with this, but time
> is quickly being absorbed by other projects, but thought now was probably
> the right time to bounce the suggestion about.

In principle, I'm all in favour of this idea. DDT would seem to me to
be a natural fit for our informal defintion of contrib - an optional,
defacto standard of a common pattern.

The optional, common pattern part is, IMHO, a no-brainer. The only
issue is the extent to which DDT is a defacto standard. I completely
agree that there would be value in having a common framework for
debugging tools of this nature. However, the presence of a deeply
fragmented community indicates that a defacto standard has not yet
emerged.

Of the top of my head, I can think of at least four things that would
stand in the way of DDT getting added to django.contrib:

Firstly, there is the simple issue of ownership and copyright.
Obviously, those that have written DDT components that are to be
included need to be onboard with this idea.

Secondly, plugins. As I understand it, DDT is half framework, and half
a collection of debugging plugins, and one of the sources of forking
is people writing their own plugins. I haven't dug into this in
detail, but in order for DDT to get to trunk, we would need to be able
to ship an interface that is conceptually similar to db.backends -
that is, we will advertise a stable interface, and ship a small number
of obvious plugins. The community would then be in a position to
contribute extra plugins - some of which might one day get added to
django.contrib. If there is any disagreement in the interface that a
plugin is expected to implement, this would be a serious impediment to
inclusion in django.contrib.

Thirdly - look & feel. I haven't used DDT for a while, so I don't know
what the state of the art is here. Last time I used DDT, it worked
fine, but I felt that it needed a little UI polish, especially in
providing a way to hide it or preventing the toolbar from obscuring
meaningful parts of the underlying site. I don't know how time and
forking has treated this particular aspect of DDT.

Lastly - time. This needs to be done in a timely fashion. If we're
going to include DDT in Django v1.2, then we're going to need to have
a consensus position - if not a ready-to-commit patch, then at least
agreement on what would be in a ready-to-commit patch - in a little
over a month. It it takes much longer than that to reconcile the
forks, then we may need to consider this a work-in-progress for v1.3.

So - if you (or anyone else) is interested in advocating the addition
of DDT to django.contrib, you're going to need to make sense of the
mess for the core team. The first step in this process is wrangling
the forked community into a single repository that is a candidate for
inclusion.

Yours,
Russ Magee %-)

Alex Gaynor

unread,
Aug 11, 2009, 10:50:35 AM8/11/09
to django-d...@googlegroups.com
Right now django-debug-toolbar has a pretty stable panel interface and
I actually can't recall it changing since release. A possibly more
interesting issue is that some of the debug information it get's is
somewhat of a hack, that is template data is gotten from monkey
patching Template.render, the SQL data is also a monkeypatch.

> Thirdly - look & feel. I haven't used DDT for a while, so I don't know
> what the state of the art is here. Last time I used DDT, it worked
> fine, but I felt that it needed a little UI polish, especially in
> providing a way to hide it or preventing the toolbar from obscuring
> meaningful parts of the underlying site. I don't know how time and
> forking has treated this particular aspect of DDT.
>

This is still true IMO, but there's another issue here. DDT uses
jQuery, and AFAIK the official position is still that we aren't
choosing a JS lib (although clearly Zain's work is rapidly moving us
to the point where a decision has to be made).

> Lastly - time. This needs to be done in a timely fashion. If we're
> going to include DDT in Django v1.2, then we're going to need to have
> a consensus position - if not a ready-to-commit patch, then at least
> agreement on what would be in a ready-to-commit patch - in a little
> over a month. It it takes much longer than that to reconcile the
> forks, then we may need to consider this a work-in-progress for v1.3.
>
> So - if you (or anyone else) is interested in advocating the addition
> of DDT to django.contrib, you're going to need to make sense of the
> mess for the core team. The first step in this process is wrangling
> the forked community into a single repository that is a candidate for
> inclusion.
>
> Yours,
> Russ Magee %-)
>
> >
>

Alex

--
"I disapprove of what you say, but I will defend to the death your
right to say it." -- Voltaire
"The people's good is the highest law." -- Cicero
"Code can always be simpler than you think, but never as simple as you
want" -- Me

Rob Hudson

unread,
Aug 11, 2009, 11:59:12 AM8/11/09
to django-d...@googlegroups.com
On Tue, Aug 11, 2009 at 7:01 AM, Russell
Keith-Magee<freakb...@gmail.com> wrote:
> Firstly, there is the simple issue of ownership and copyright.
> Obviously, those that have written DDT components that are to be
> included need to be onboard with this idea.

On this point I've strived to be pro-active (thanks to Jacob)...
before any new commits from new committers were merged I made sure
they're code was ok to be licensed under BSD and they were listed in
the AUTHORS file. Seeing as the "framework" part hasn't changed a
whole lot in the year or so it's been out, it seems like a worthwhile
consideration to me. And I'd be for it.

> Secondly, plugins. As I understand it, DDT is half framework, and half
> a collection of debugging plugins, and one of the sources of forking
> is people writing their own plugins. I haven't dug into this in
> detail, but in order for DDT to get to trunk, we would need to be able
> to ship an interface that is conceptually similar to db.backends -
> that is, we will advertise a stable interface, and ship a small number
> of obvious plugins. The community would then be in a position to
> contribute extra plugins - some of which might one day get added to
> django.contrib. If there is any disagreement in the interface that a
> plugin is expected to implement, this would be a serious impediment to
> inclusion in django.contrib.

You understand it correctly. I've always meant to advertise a little
more the fact that panels are just classes (subclasses of DebugPanel)
that can be imported from anywhere given the full Python path to the
debug toolbar config. And you are correct that some forks are adding
panels that I wasn't comfortable merging due to the fact that they
might be too specific and made more sense as a custom panel.
Actually, to my knowledge, all the forks are panel specific and are
not changing the core "framework" part of the debug toolbar.

> Thirdly - look & feel. I haven't used DDT for a while, so I don't know
> what the state of the art is here. Last time I used DDT, it worked
> fine, but I felt that it needed a little UI polish, especially in
> providing a way to hide it or preventing the toolbar from obscuring
> meaningful parts of the underlying site. I don't know how time and
> forking has treated this particular aspect of DDT.

Agreed. UI isn't my strong point and I've always hoped a designer
would be inspired to give it a full treatment. There's also the
jQuery aspect of it. I think this probably leads to a bigger
discussion. I have a local branch that makes some big improvements in
this area already.

> Lastly - time. This needs to be done in a timely fashion. If we're
> going to include DDT in Django v1.2, then we're going to need to have
> a consensus position - if not a ready-to-commit patch, then at least
> agreement on what would be in a ready-to-commit patch - in a little
> over a month. It it takes much longer than that to reconcile the
> forks, then we may need to consider this a work-in-progress for v1.3.

Perhaps some discussion at DjangoCon? :)

> So - if you (or anyone else) is interested in advocating the addition
> of DDT to django.contrib, you're going to need to make sense of the
> mess for the core team. The first step in this process is wrangling
> the forked community into a single repository that is a candidate for
> inclusion.

Hopefully I answered some of these questions and made some sense of the mess.

-Rob

Martin Maney

unread,
Aug 11, 2009, 12:38:44 PM8/11/09
to django-d...@googlegroups.com
On Tue, Aug 11, 2009 at 09:50:35AM -0500, Alex Gaynor wrote:
> Right now django-debug-toolbar has a pretty stable panel interface and
> I actually can't recall it changing since release. A possibly more
> interesting issue is that some of the debug information it get's is
> somewhat of a hack, that is template data is gotten from monkey
> patching Template.render, the SQL data is also a monkeypatch.

Caching stats were another area where monkeypatching seemed to be the
only alternative to an altered usage in one's source code. Back when I
spent some time using and extending parts of ddt the situation was as
described here:

http://wiki.github.com/mmaney/django-debug-toolbar/cache-panel-workaround

That predates the discussion I had with Rob Hudson about another fellow's
branch (can't recall whose offhand) which used a monkeypatch to add the
necessary intercept to the cache object. At one point I had hoped to
bend Jacob's ear at PyCon about this, but I got to be too busy with
other work and, in fact, never had time to drop in. Plus I had read
about how everyone was focusing on getting 1.1 out Real Soon Now and
figured it wasn't the best time for it. Months passed...

Ulrich Petri

unread,
Aug 11, 2009, 1:09:59 PM8/11/09
to django-d...@googlegroups.com

Am 11.08.2009 um 16:50 schrieb Alex Gaynor:
>
> This is still true IMO, but there's another issue here. DDT uses
> jQuery, and AFAIK the official position is still that we aren't
> choosing a JS lib (although clearly Zain's work is rapidly moving us
> to the point where a decision has to be made).

This is IMHO the most important part. In our projects I can't use the
DDT once the templates have been put in b/c we are a MooTools shop.
I don't think that the DDT should need to use any JS Framework at all.
The level of DHTML gymnastics it performs are quite doable in plain JS
+DOM without too much pain.

Also this is not necessarily connected to any decision about including
a JS Framework for the admin as the DDT will AFAIK be mostly used in
the frontend.

Ulrich

Mat Clayton

unread,
Aug 11, 2009, 1:27:10 PM8/11/09
to django-d...@googlegroups.com
I thought one of the more recent patches to DDT made it run Jquery in compatability mode, which should resolve these clashes, probably isn't on all branches though.

mat

Russell Keith-Magee

unread,
Aug 12, 2009, 6:29:23 AM8/12/09
to django-d...@googlegroups.com
On Tue, Aug 11, 2009 at 11:59 PM, Rob Hudson<trebor...@gmail.com> wrote:
>
> On Tue, Aug 11, 2009 at 7:01 AM, Russell
> Keith-Magee<freakb...@gmail.com> wrote:
>> Firstly, there is the simple issue of ownership and copyright.
>> Obviously, those that have written DDT components that are to be
>> included need to be onboard with this idea.
>
> On this point I've strived to be pro-active (thanks to Jacob)...
> before any new commits from new committers were merged I made sure
> they're code was ok to be licensed under BSD and they were listed in
> the AUTHORS file.  Seeing as the "framework" part hasn't changed a
> whole lot in the year or so it's been out, it seems like a worthwhile
> consideration to me.  And I'd be for it.

Excellent.

> Actually, to my knowledge, all the forks are panel specific and are
> not changing the core "framework" part of the debug toolbar.

This was my largest technical concern - if the community is using the
same interface, then there is is isn't a problem standardizing on that
interface.

>> Thirdly - look & feel. I haven't used DDT for a while, so I don't know
>> what the state of the art is here. Last time I used DDT, it worked
>> fine, but I felt that it needed a little UI polish, especially in
>> providing a way to hide it or preventing the toolbar from obscuring
>> meaningful parts of the underlying site. I don't know how time and
>> forking has treated this particular aspect of DDT.
>
> Agreed.  UI isn't my strong point and I've always hoped a designer
> would be inspired to give it a full treatment.  There's also the
> jQuery aspect of it.  I think this probably leads to a bigger
> discussion.  I have a local branch that makes some big improvements in
> this area already.

At this point, Jacob has pretty much indicated that JQuery is going to
be Django's toolkit of choice if/when a toolkit is used. However, we
aren't going to impose that choice onto the frontend. Some discussion
is definitely required to establish exactly where the boundary ends.

I'll be sure to take a closer look at your new UI branch.

>> Lastly - time. This needs to be done in a timely fashion. If we're
>> going to include DDT in Django v1.2, then we're going to need to have
>> a consensus position - if not a ready-to-commit patch, then at least
>> agreement on what would be in a ready-to-commit patch - in a little
>> over a month. It it takes much longer than that to reconcile the
>> forks, then we may need to consider this a work-in-progress for v1.3.
>
> Perhaps some discussion at DjangoCon?  :)

Certainly. This sounds like a great topic for a sprint.

Russ %-)

Rob Hudson

unread,
Aug 12, 2009, 5:00:06 PM8/12/09
to Django developers
I'm not sure if this is the place but here are some other issues or
questions I have if this were to happen...

* The jQuery question is a big one. I've taken strides to make the
debug toolbar interoperate with other popular JS frameworks (mootools
and prototype, namely). But if jQuery were decided against, would it
make sense to re-use some of the Javascript libraries that Django has
developed for its admin? Would it use the same admin media handler
trick?

* Which set of plugins are included, and of those that have settings,
what are their defaults. Some defaults currently optimize to general
case and provide more debugging information, but on larger sites
performance may suffer severely. It may make sense to take a
philosophy of best default performance with opt-in added debugging.

* Should there be a place for plugins (panels) that don't make the
cut? Panels consist of some Python and some HTML, so it's not a
single file. They *could* be changed to work similar to form.widgets
with a render method and HTML backed in... but I'm not a huge fan of
that. But it would make it a bit easier for posting on a site like
Django Snippets.

* Should the UI match that of the Django admin (overall theme, colors,
etc)?

* If the debug toolbar is incorporated, should we consider different
integration options? e.g. Currently the debug toolbar injects URLs
into the project in a rather ugly way -- could this be done better if
it were part of Django?

Thanks,
Rob

David Cramer

unread,
Aug 13, 2009, 3:28:10 AM8/13/09
to Django developers
I think it's mostly only my fork (and it's forks) that vary much from
trunk. I never got around to changing the framework to come in line
with the master branch I think because it didn't support everything
that was needed. Not sure if it does now however.

David Cramer

unread,
Aug 13, 2009, 3:30:35 AM8/13/09
to Django developers
Oh, and thats most likely my branch you're referring to Martin. I
implemented a lot of the panels, and went so far as adding crazy
monkey patching in some of them to catch some information I wanted.

http://github.com/dcramer/django-debug-toolbar/tree/master

On Aug 11, 11:38 am, Martin Maney <ma...@two14.net> wrote:
> On Tue, Aug 11, 2009 at 09:50:35AM -0500, Alex Gaynor wrote:
> > Right now django-debug-toolbar has a pretty stable panel interface and
> > I actually can't recall it changing since release.  A possibly more
> > interesting issue is that some of the debug information it get's is
> > somewhat of a hack, that is template data is gotten from monkey
> > patching Template.render, the SQL data is also a monkeypatch.
>
> Caching stats were another area where monkeypatching seemed to be the
> only alternative to an altered usage in one's source code.  Back when I
> spent some time using and extending parts of ddt the situation was as
> described here:
>
> http://wiki.github.com/mmaney/django-debug-toolbar/cache-panel-workar...

Russell Keith-Magee

unread,
Aug 13, 2009, 8:18:28 AM8/13/09
to django-d...@googlegroups.com
On Thu, Aug 13, 2009 at 5:00 AM, Rob Hudson<trebor...@gmail.com> wrote:
>
> I'm not sure if this is the place but here are some other issues or
> questions I have if this were to happen...

This is as good a place as any.

> * The jQuery question is a big one.  I've taken strides to make the
> debug toolbar interoperate with other popular JS frameworks (mootools
> and prototype, namely).

I acknowledge that dumping jQuery would impose a big redevelopment
burden. When I get a spare moment, I'll try and get Jacob to make an
pronouncement regarding our JS toolkit usage.

> But if jQuery were decided against, would it
> make sense to re-use some of the Javascript libraries that Django has
> developed for its admin?

I'm not sure how much potential for reuse exists here. The javascript
in the admin is fairly minimal - the only example of hide+show that I
can think of is in collapsing fieldsets, and that code is both simple
and written to the specific task. All you're really doing is toggling
the class that makes the a particular box visible or hidden. There may
be some common themes in the javascript, but I'm not sure it's
something that can be re-used.

On top of that, there is the possibility that admin will be switched
to use jQuery in the near future, so writing the toolbar to depend on
admin's javascript could be a short-lived strategy.

> * Which set of plugins are included, and of those that have settings,
> what are their defaults.  Some defaults currently optimize to general
> case and provide more debugging information, but on larger sites
> performance may suffer severely.  It may make sense to take a
> philosophy of best default performance with opt-in added debugging.

I'm happy to leave this one to the recommendation of yourself and the
community. Make a recommendation (and explain your reasoning), and
I'll assess it with my Core Dev hat on.

I can tell you that I will expect the 'installed by default' set (i.e.
the panels you get with no special configuration) to work with no
performance hit. More complex panels may be ok if the documentation
can clearly explain any limitations that exist.

Err on the side of caution - remember that whatever tools you choose
will be in Django for the long term, and will be subject to all the
standards of performance, robustness and backwards-compatibility of
the project as a whole. It's easy to add a panel later on. It's not
easy to take one out once it has been added.

> * Should there be a place for plugins (panels) that don't make the
> cut?  Panels consist of some Python and some HTML, so it's not a
> single file.  They *could* be changed to work similar to form.widgets
> with a render method and HTML backed in... but I'm not a huge fan of
> that.  But it would make it a bit easier for posting on a site like
> Django Snippets.

It isn't just an advantage for snippets - it also means that deploying
a panel is just a matter of referencing the python module - you don't
need to do a complex deployment dance with code and templates.

Embedding small HTML snippets in a the Python module for a panel seems
reasonably elegant to me. The Debug 404 page already does this, so
there is precedent in Django, too.

> * Should the UI match that of the Django admin (overall theme, colors,
> etc)?

I'd be inclined to say yes - familiarity would be a good UI device here.

BTW: I had a play with the UI refactor - I really like the sidebar layout.

> * If the debug toolbar is incorporated, should we consider different
> integration options?  e.g. Currently the debug toolbar injects URLs
> into the project in a rather ugly way -- could this be done better if
> it were part of Django?

Did you have a something in mind?

The middleware approach you have implemented strikes me as reasonably
elegant. The only major limitation I can see is that it doesn't allow
new panels to provide their own rest-backed capabilities (e.g.,
imagine if sql_explain was an external panel). One way around this
would be to allow panels to define an urls() method; that method
could be dynamically inserted into the urlpattern that the debug
middleware uses.

And while I have your attention... :-)

The other two pieces that would be required before we added this to
trunk would be documentation and testing.

The installation and configuration notes are good, but we need
documentation for each panel, and the options for those panels.

Tests would also be highly desirable - validating that the REST views
work as advertised, that the middleware will operate as expected, etc.

Yours,
Russ Magee %-)

Idan Gazit

unread,
Aug 17, 2009, 8:21:47 AM8/17/09
to Django developers
I've been working on prettyfication of the DDT. Github:
http://github.com/idangazit/django-debug-toolbar/tree/idan-ui-rf. It's
a reasonably complete reskinning of the existing DDT. There are still
a couple of outstanding issues but the redesign is largely finished.

I didn't use the admin color palette because A) it's fugly and B) I
think making the DDT consistent with an optional-and-completely-
separate-contrib-tool is synthetic and meaningless. End users of the
admin are not the people who will be using DDT, and developers are not
the core audience for the admin. I'd argue that they're separate
enough, but I'm not religious about it.

I also have some ideas for enhancement, but having read this thread
I'm hesitant to develop if they will jeopardize inclusion in contrib.
For example, syntax highlighting of templates (might introduce a
dependency on pygments) and some tasteful animation of panels (would
require jQuery).

I'm keeping tabs on what to work on at http://github.com/idangazit/django-debug-toolbar/issues.
After prettyfication I'll take a look at tests and docs.

Generally, I think an attractive-looking debug toolbar is fodder for a
thousand "django is teh awesum" blog posts. There are few "human-
facing" parts of django that are screenshot-able, we should make the
ones we have look amazing.

Advice on how to proceed appreciated.

-Idan

Idan Gazit

unread,
Aug 17, 2009, 8:23:58 AM8/17/09
to Django developers
Oh, forgot to include the screencast:

http://s3.pixane.com.s3.amazonaws.com/ddt-ui-refresh.mov

-I

Jacob Kaplan-Moss

unread,
Aug 17, 2009, 9:28:34 AM8/17/09
to django-d...@googlegroups.com
Hey Idan --

On Mon, Aug 17, 2009 at 7:21 AM, Idan Gazit<id...@pixane.com> wrote:
> I've been working on prettyfication of the DDT. Github:
> http://github.com/idangazit/django-debug-toolbar/tree/idan-ui-rf. It's
> a reasonably complete reskinning of the existing DDT. There are still
> a couple of outstanding issues but the redesign is largely finished.

Looks nice enough to me!

> I didn't use the admin color palette because A) it's fugly and B) I
> think making the DDT consistent with an optional-and-completely-
> separate-contrib-tool is synthetic and meaningless.

I'd disagree with (a), but, well, taste has no taste. However, I
completely agree with (b) -- in fact, there's precedent for making
developer-facing UI different: see the pretty error pages and the "it
worked!" page, which aren't Django branded in any way. The reasoning
was that we wanted the error pages to be somewhat framework-agnostic;
we didn't want to impose our branding onto parts of *your* site. I'd
say a similar ethos should be expressed in the debug toolbar branding.
If you wanted to be extra special, some UI similarity between the
error pages and the debug toolbar would probably be a good idea.

Jacob

Idan Gazit

unread,
Aug 17, 2009, 2:55:20 PM8/17/09
to Django developers
On Aug 17, 4:28 pm, Jacob Kaplan-Moss <ja...@jacobian.org> wrote:
> I'd say a similar ethos should be expressed in the debug toolbar branding.
> If you wanted to be extra special, some UI similarity between the
> error pages and the debug toolbar would probably be a good idea.

Fair 'nuff. I'll squash the last remaining bugs and take a peek at the
debug page CSS.

-I

Dave Jeffery

unread,
Aug 17, 2009, 5:35:27 PM8/17/09
to django-d...@googlegroups.com
On Mon, Aug 17, 2009 at 2:28 PM, Jacob Kaplan-Moss <ja...@jacobian.org> wrote:

The reasoning was that we wanted the error pages to be somewhat framework-agnostic;
we didn't want to impose our branding onto parts of *your* site. I'd
say a similar ethos should be expressed in the debug toolbar branding.
If you wanted to be extra special, some UI similarity between the
error pages and the debug toolbar would probably be a good idea.

I like Jacob's idea of taking design hints from the debug page when styling the toolbar. The information presentation on the debug page is very clear; the sans-serif font and generous padding make it easy to read and scan through; and the pastel colours make the page light.

(Sticking my nose in where it isn't wanted...) The toolbar looks really great but it feels a bit over-designed and too heavy for a functional interface which will sit atop of existing websites. I'm especially referring to the typography, the uppercase serif lettering seems inappropriate for this type of interface. Just my opinion, obviously discard it at will.

Dave

Idan Gazit

unread,
Aug 17, 2009, 6:48:33 PM8/17/09
to Django developers
On Aug 18, 12:35 am, Dave Jeffery <djeff...@gmail.com> wrote:
> (Sticking my nose in where it isn't wanted...) The toolbar looks really
> great but it feels a bit over-designed and too heavy for a functional
> interface which will sit atop of existing websites. I'm especially referring
> to the typography, the uppercase serif lettering seems inappropriate for
> this type of interface.

Point well taken. I just get tired of being tuned into the "All
Helvetica... all the time" channel and wanted something different.
Serif is the new black. :)

But if we're aiming to match existing styling then Helvetica or its
bastard stepchildren are indeed appropriate.

-I


Reply all
Reply to author
Forward
0 new messages