├── blog ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0003_activate_existing_entries.py │ ├── 0002_auto__add_field_entry_is_active.py │ ├── 0005_copy_entry_summary_and_body_to_html.py │ ├── 0007_existing_entries_are_raw_html.py │ ├── 0008_auto__del_field_entry_use_raw_html.py │ ├── 0006_auto__add_field_entry_use_raw_html.py │ ├── 0009_auto__add_field_entry_content_format.py │ ├── 0001_initial.py │ └── 0004_auto__add_field_entry_summary_html__add_field_entry_body_html.py ├── templatetags │ ├── __init__.py │ └── weblog.py ├── sitemaps.py ├── feeds.py ├── admin.py ├── urls.py ├── views.py └── models.py ├── cla ├── __init__.py ├── migrations │ └── __init__.py └── admin.py ├── contact ├── models.py ├── __init__.py ├── views.py ├── urls.py ├── tests.py └── forms.py ├── docs ├── __init__.py ├── management │ ├── __init__.py │ └── commands │ │ └── __init__.py ├── migrations │ ├── __init__.py │ ├── 0003_fix_document_model.py │ ├── 0001_initial.py │ ├── 0002_add_document_model.py │ ├── 0004_add_git_support.py │ └── 0005_add_unicity_constaints.py ├── templatetags │ ├── __init__.py │ └── docs.py ├── search_sites.py ├── context_processors.py ├── admin.py ├── templates │ └── docs │ │ ├── index.html │ │ ├── search_form.html │ │ ├── py-modindex.html │ │ ├── genindex.html │ │ └── search.html ├── sitemaps.py ├── utils.py ├── search_indexes.py ├── urls.py ├── tests.py ├── forms.py ├── fixtures │ ├── doc_test_fixtures.json │ └── doc_releases.json └── models.py ├── legacy ├── __init__.py ├── models.py ├── fixtures │ ├── redirects-downloads.json.gz │ ├── flatpages-0.9x-documentation.json.gz │ └── redirects-0.9x-documentation.json.gz ├── views.py ├── tests.py └── urls.py ├── svntogit ├── models.py ├── __init__.py ├── urls.py ├── views.py └── tests.py ├── tracdb ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0001_initial.py │ └── 0002_bouncing_tickets_view.py ├── urls.py ├── db_router.py ├── views.py └── stats.py ├── accounts ├── __init__.py ├── migrations │ └── __init__.py ├── models.py ├── profile_urls.py ├── urls.py ├── forms.py └── views.py ├── aggregator ├── __init__.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── update_subscriptions.py │ │ └── send_pending_approval_email.py ├── migrations │ ├── __init__.py │ └── 0002_rename_tables.py ├── utils.py ├── forms.py ├── urls.py ├── admin.py ├── feeds.py ├── tests.py └── views.py ├── django_docs ├── __init__.py ├── wsgi.py ├── urls.py └── settings.py ├── django_www ├── __init__.py ├── wsgi.py └── urls.py ├── releases ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0002_auto__chg_field_release_date.py │ ├── 0001_initial.py │ ├── 0004_auto__add_field_release_is_lts.py │ └── 0003_auto__add_fields_release_tuple.py ├── context_processors.py ├── urls.py ├── admin.py ├── tests.py └── views.py ├── static ├── css │ ├── weblog.css │ ├── community.css │ ├── download.css │ ├── homepage.css │ ├── documentation.css │ ├── print.css │ ├── docs │ │ ├── docs.css │ │ └── index.css │ └── pygments.css ├── robots.txt ├── favicon.ico └── img │ ├── site │ ├── mt.png │ ├── bbd_bg.gif │ ├── bbd_code.gif │ ├── bbdsm_bg.gif │ ├── hdr_logo.gif │ ├── nav_bg.gif │ ├── bbd_weblog.gif │ ├── bbdsm_bg.gif.1 │ ├── invisible.gif │ ├── bbd_blogroll.gif │ ├── bbd_community.gif │ ├── bbd_download.gif │ ├── bbd_homepage.gif │ ├── bbd_overview.gif │ ├── somerights20.png │ ├── arrow-head-left.gif │ ├── djangoapi-logo.gif │ ├── hdr_meetdjango.gif │ ├── screencast-back.gif │ ├── screencast-next.gif │ ├── bbd_documentation.gif │ ├── download_bg-left.gif │ └── download_bg-right.gif │ ├── badges │ ├── djangomade124x25.gif │ ├── djangosite100x25.gif │ ├── djangosite124x25.gif │ ├── djangosite80x15.gif │ ├── djangowish126x70.gif │ ├── djangojoint107x25.gif │ ├── djangodonated126x54.gif │ ├── djangomade124x25_grey.gif │ ├── djangopowered126x54.gif │ ├── djangoproject120x24.gif │ ├── djangoproject120x25.gif │ ├── djangosite100x25_grey.gif │ ├── djangosite80x15_grey.gif │ ├── djangosponsor113x25.gif │ ├── djangowish126x70_grey.gif │ ├── djangojoint107x25_grey.gif │ ├── djangodonated126x54_grey.png │ ├── djangopowered126x54_grey.gif │ ├── djangoproject120x25_grey.gif │ └── djangosponsor113x25_grey.gif │ ├── desktops │ ├── desktop-43_t.jpg │ ├── desktop-wide_t.jpg │ ├── djangodesktop-800x600.jpg │ ├── djangodesktop-1024x768.jpg │ ├── djangodesktop-1152x864.jpg │ ├── djangodesktop-1280x1024.jpg │ ├── djangodesktop-1600x1200.jpg │ └── djangodesktop-1680x1050.jpg │ ├── doc │ └── icons │ │ ├── docicons-note.gif │ │ ├── docicons-warning.png │ │ ├── docicons-philosophy.gif │ │ └── docicons-behindscenes.gif │ └── logos │ ├── django-logo-negative.png │ ├── django-logo-positive.png │ ├── django-logo-positive.svg │ └── django-logo-negative.svg ├── templates ├── feeds │ ├── community_description.html │ └── community_title.html ├── registration │ ├── activation_email_subject.txt │ ├── base.html │ ├── activation_complete.html │ ├── logout.html │ ├── registration_complete.html │ ├── activate.html │ ├── activation_email.txt │ ├── password_reset_email.html │ ├── login.html │ └── registration_form.html ├── flatfiles │ ├── default.html │ └── overview.html ├── flatpages │ ├── code.html │ ├── default.html │ ├── community.html │ ├── snakesandrubies.html │ └── foundation.html ├── aggregator │ ├── denied.html │ ├── delete-confirm.html │ ├── my-feeds.html │ ├── edit-feed.html │ ├── feeditem_list.html │ └── index.html ├── blog │ ├── month_links_snippet.html │ ├── entry_snippet.html │ ├── entry_detail.html │ ├── entry_archive_year.html │ ├── entry_archive.html │ ├── entry_archive_day.html │ └── entry_archive_month.html ├── base_blogroll.html ├── contact │ ├── coc.html │ ├── sent.html │ ├── coc_form.html │ └── foundation.html ├── base_docs.html ├── base_code.html ├── base_2col.html ├── 500.html ├── 404.html ├── log_changelog.cs ├── 410.html ├── base_3col.html ├── base_weblog.html ├── tracdb │ └── bouncing_tickets.html ├── conduct │ ├── base.html │ └── changes.html ├── accounts │ ├── edit_profile.html │ └── user_profile.html ├── donate_thanks.html ├── query_rss.cs ├── base_foundation.html ├── base_community.html └── base.html ├── django_ux ├── bg.png ├── idan.jpg ├── julien.jpg ├── djangoux.png ├── index.html └── base.css ├── local-requirements.txt ├── .gitignore ├── TODO ├── manage.py ├── deploy-requirements.txt ├── README.txt └── fabfile.py /blog/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cla/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contact/models.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /legacy/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /legacy/models.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /svntogit/models.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tracdb/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aggregator/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contact/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_docs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_www/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /releases/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /svntogit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cla/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aggregator/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aggregator/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /releases/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tracdb/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aggregator/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/css/weblog.css: -------------------------------------------------------------------------------- 1 | @import url(base.css); -------------------------------------------------------------------------------- /static/css/community.css: -------------------------------------------------------------------------------- 1 | @import url(base.css); -------------------------------------------------------------------------------- /static/css/download.css: -------------------------------------------------------------------------------- 1 | @import url(base.css); -------------------------------------------------------------------------------- /docs/search_sites.py: -------------------------------------------------------------------------------- 1 | import haystack; haystack.autodiscover() -------------------------------------------------------------------------------- /static/robots.txt: -------------------------------------------------------------------------------- 1 | user-agent: AhrefsBot 2 | disallow: / 3 | -------------------------------------------------------------------------------- /templates/feeds/community_description.html: -------------------------------------------------------------------------------- 1 | {{ obj.summary|safe }} -------------------------------------------------------------------------------- /templates/feeds/community_title.html: -------------------------------------------------------------------------------- 1 | {{ obj.feed.title }}: {{ obj.title }} -------------------------------------------------------------------------------- /django_ux/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/django_ux/bg.png -------------------------------------------------------------------------------- /django_ux/idan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/django_ux/idan.jpg -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/favicon.ico -------------------------------------------------------------------------------- /templates/registration/activation_email_subject.txt: -------------------------------------------------------------------------------- 1 | Activate your djangoproject.com account 2 | -------------------------------------------------------------------------------- /django_ux/julien.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/django_ux/julien.jpg -------------------------------------------------------------------------------- /django_ux/djangoux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/django_ux/djangoux.png -------------------------------------------------------------------------------- /static/img/site/mt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/mt.png -------------------------------------------------------------------------------- /static/img/site/bbd_bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_bg.gif -------------------------------------------------------------------------------- /static/img/site/bbd_code.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_code.gif -------------------------------------------------------------------------------- /static/img/site/bbdsm_bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbdsm_bg.gif -------------------------------------------------------------------------------- /static/img/site/hdr_logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/hdr_logo.gif -------------------------------------------------------------------------------- /static/img/site/nav_bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/nav_bg.gif -------------------------------------------------------------------------------- /static/img/site/bbd_weblog.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_weblog.gif -------------------------------------------------------------------------------- /static/img/site/bbdsm_bg.gif.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbdsm_bg.gif.1 -------------------------------------------------------------------------------- /static/img/site/invisible.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/invisible.gif -------------------------------------------------------------------------------- /static/img/site/bbd_blogroll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_blogroll.gif -------------------------------------------------------------------------------- /static/img/site/bbd_community.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_community.gif -------------------------------------------------------------------------------- /static/img/site/bbd_download.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_download.gif -------------------------------------------------------------------------------- /static/img/site/bbd_homepage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_homepage.gif -------------------------------------------------------------------------------- /static/img/site/bbd_overview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_overview.gif -------------------------------------------------------------------------------- /static/img/site/somerights20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/somerights20.png -------------------------------------------------------------------------------- /static/img/site/arrow-head-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/arrow-head-left.gif -------------------------------------------------------------------------------- /static/img/site/djangoapi-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/djangoapi-logo.gif -------------------------------------------------------------------------------- /static/img/site/hdr_meetdjango.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/hdr_meetdjango.gif -------------------------------------------------------------------------------- /static/img/site/screencast-back.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/screencast-back.gif -------------------------------------------------------------------------------- /static/img/site/screencast-next.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/screencast-next.gif -------------------------------------------------------------------------------- /local-requirements.txt: -------------------------------------------------------------------------------- 1 | # Requirements to manage the site locally and run the fabfile. 2 | 3 | Unipath 4 | Fabric 5 | whoosh < 2.5 6 | -------------------------------------------------------------------------------- /static/img/badges/djangomade124x25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangomade124x25.gif -------------------------------------------------------------------------------- /static/img/badges/djangosite100x25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosite100x25.gif -------------------------------------------------------------------------------- /static/img/badges/djangosite124x25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosite124x25.gif -------------------------------------------------------------------------------- /static/img/badges/djangosite80x15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosite80x15.gif -------------------------------------------------------------------------------- /static/img/badges/djangowish126x70.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangowish126x70.gif -------------------------------------------------------------------------------- /static/img/desktops/desktop-43_t.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/desktop-43_t.jpg -------------------------------------------------------------------------------- /static/img/desktops/desktop-wide_t.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/desktop-wide_t.jpg -------------------------------------------------------------------------------- /static/img/doc/icons/docicons-note.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/doc/icons/docicons-note.gif -------------------------------------------------------------------------------- /static/img/site/bbd_documentation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/bbd_documentation.gif -------------------------------------------------------------------------------- /static/img/site/download_bg-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/download_bg-left.gif -------------------------------------------------------------------------------- /static/img/site/download_bg-right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/site/download_bg-right.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.db 3 | local_settings.py 4 | djangodocs 5 | static_root 6 | djangodocs.index 7 | docs/locale/*/LC_MESSAGES/django.mo 8 | -------------------------------------------------------------------------------- /static/img/badges/djangojoint107x25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangojoint107x25.gif -------------------------------------------------------------------------------- /legacy/fixtures/redirects-downloads.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/legacy/fixtures/redirects-downloads.json.gz -------------------------------------------------------------------------------- /static/img/badges/djangodonated126x54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangodonated126x54.gif -------------------------------------------------------------------------------- /static/img/badges/djangomade124x25_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangomade124x25_grey.gif -------------------------------------------------------------------------------- /static/img/badges/djangopowered126x54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangopowered126x54.gif -------------------------------------------------------------------------------- /static/img/badges/djangoproject120x24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangoproject120x24.gif -------------------------------------------------------------------------------- /static/img/badges/djangoproject120x25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangoproject120x25.gif -------------------------------------------------------------------------------- /static/img/badges/djangosite100x25_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosite100x25_grey.gif -------------------------------------------------------------------------------- /static/img/badges/djangosite80x15_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosite80x15_grey.gif -------------------------------------------------------------------------------- /static/img/badges/djangosponsor113x25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosponsor113x25.gif -------------------------------------------------------------------------------- /static/img/badges/djangowish126x70_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangowish126x70_grey.gif -------------------------------------------------------------------------------- /static/img/doc/icons/docicons-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/doc/icons/docicons-warning.png -------------------------------------------------------------------------------- /static/img/logos/django-logo-negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/logos/django-logo-negative.png -------------------------------------------------------------------------------- /static/img/logos/django-logo-positive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/logos/django-logo-positive.png -------------------------------------------------------------------------------- /static/img/badges/djangojoint107x25_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangojoint107x25_grey.gif -------------------------------------------------------------------------------- /static/img/desktops/djangodesktop-800x600.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/djangodesktop-800x600.jpg -------------------------------------------------------------------------------- /static/img/doc/icons/docicons-philosophy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/doc/icons/docicons-philosophy.gif -------------------------------------------------------------------------------- /static/img/badges/djangodonated126x54_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangodonated126x54_grey.png -------------------------------------------------------------------------------- /static/img/badges/djangopowered126x54_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangopowered126x54_grey.gif -------------------------------------------------------------------------------- /static/img/badges/djangoproject120x25_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangoproject120x25_grey.gif -------------------------------------------------------------------------------- /static/img/badges/djangosponsor113x25_grey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/badges/djangosponsor113x25_grey.gif -------------------------------------------------------------------------------- /static/img/desktops/djangodesktop-1024x768.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/djangodesktop-1024x768.jpg -------------------------------------------------------------------------------- /static/img/desktops/djangodesktop-1152x864.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/djangodesktop-1152x864.jpg -------------------------------------------------------------------------------- /static/img/desktops/djangodesktop-1280x1024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/djangodesktop-1280x1024.jpg -------------------------------------------------------------------------------- /static/img/desktops/djangodesktop-1600x1200.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/djangodesktop-1600x1200.jpg -------------------------------------------------------------------------------- /static/img/desktops/djangodesktop-1680x1050.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/desktops/djangodesktop-1680x1050.jpg -------------------------------------------------------------------------------- /static/img/doc/icons/docicons-behindscenes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/static/img/doc/icons/docicons-behindscenes.gif -------------------------------------------------------------------------------- /legacy/fixtures/flatpages-0.9x-documentation.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/legacy/fixtures/flatpages-0.9x-documentation.json.gz -------------------------------------------------------------------------------- /legacy/fixtures/redirects-0.9x-documentation.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiro/djangoproject.com/master/legacy/fixtures/redirects-0.9x-documentation.json.gz -------------------------------------------------------------------------------- /templates/registration/base.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | {% block sectionid %}community{% endblock %} 3 | {% block billboard %}

Accounts

{% endblock %} -------------------------------------------------------------------------------- /releases/context_processors.py: -------------------------------------------------------------------------------- 1 | from releases.models import Release 2 | 3 | def django_version(request): 4 | return {'DJANGO_VERSION': Release.objects.current_version()} 5 | -------------------------------------------------------------------------------- /templates/flatfiles/default.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

{{ flatpage.title }}

5 | 6 | {{ flatpage.content }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /templates/flatpages/code.html: -------------------------------------------------------------------------------- 1 | {% extends "base_code.html" %} 2 | 3 | {% block content %} 4 |

{{ flatpage.title }}

5 | 6 | {{ flatpage.content }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /templates/flatpages/default.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |

{{ flatpage.title }}

5 | 6 | {{ flatpage.content }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /docs/context_processors.py: -------------------------------------------------------------------------------- 1 | from docs.models import DocumentRelease 2 | 3 | def docs_version(request): 4 | return {'DOCS_VERSION': DocumentRelease.objects.current_version()} 5 | -------------------------------------------------------------------------------- /templates/aggregator/denied.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content %} 4 |

Community

5 | 6 |

Sorry, you can't do that.

7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /templates/flatfiles/overview.html: -------------------------------------------------------------------------------- 1 | {% extends "base_overview.html" %} 2 | 3 | {% block content %} 4 |

{{ flatpage.title }}

5 | 6 | {{ flatpage.content }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /templates/flatpages/community.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content %} 4 |

{{ flatpage.title }}

5 | 6 | {{ flatpage.content }} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /templates/blog/month_links_snippet.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /legacy/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | def gone(request, *args, **kwargs): 4 | """ 5 | Display a nice 410 gone page. 6 | """ 7 | return render(request, '410.html', status=410) 8 | -------------------------------------------------------------------------------- /templates/base_blogroll.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col" %} 2 | 3 | {% block sectionid %}blogroll{% endblock %} 4 | 5 | {% block title %}Blogroll{% endblock %} 6 | 7 | {% block billboard %}

Blogroll

{% endblock %} -------------------------------------------------------------------------------- /templates/flatpages/snakesandrubies.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}{{ flatpage.title }}{% endblock %} 4 | 5 | {% block content %} 6 |

{{ flatpage.title }}

7 | {{ flatpage.content }} 8 | {% endblock %} -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * allow users to "claim" legacy feeds (might do this by hand.) 2 | * investigate the status of django-contact-form 3 | * some apps don't have tests 4 | * allow update_docs to build only some versions, and build 5 | old versions less often. 6 | -------------------------------------------------------------------------------- /tracdb/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url 2 | from . import views 3 | 4 | urlpatterns = patterns('', 5 | url( 6 | r'^bouncing/$', 7 | views.bouncing_tickets, 8 | name='bouncing_tickets', 9 | ), 10 | ) 11 | -------------------------------------------------------------------------------- /templates/contact/coc.html: -------------------------------------------------------------------------------- 1 | {% extends "base_3col.html" %} 2 | 3 | {% block title %}Django Code of Conduct Feedback{% endblock %} 4 | 5 | {% block content %} 6 |

Django Code of Conduct Feedback

7 | {% include "contact/coc_form.html" %} 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /templates/base_docs.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | 3 | {% block sectionid %}documentation{% endblock %} 4 | 5 | {% block title %}Documentation{% endblock %} 6 | 7 | {% block billboard %}

Django documentation

{% endblock %} 8 | 9 | -------------------------------------------------------------------------------- /aggregator/utils.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | def push_credentials(hub_url): 4 | """ 5 | Callback for django_push to get a hub's credentials. 6 | 7 | We always use superfeedr so this is easy. 8 | """ 9 | return tuple(settings.SUPERFEEDR_CREDS) 10 | -------------------------------------------------------------------------------- /docs/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.contrib import admin 4 | from .models import DocumentRelease 5 | 6 | admin.site.register(DocumentRelease, 7 | list_display = ['version', 'lang', 'scm_url', 'is_default'], 8 | list_editable = ['is_default'], 9 | ) -------------------------------------------------------------------------------- /svntogit/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | Legacy URLs for changesets. 3 | """ 4 | 5 | from __future__ import absolute_import 6 | 7 | from django.conf.urls import patterns 8 | 9 | from .views import redirect_to_github 10 | 11 | urlpatterns = patterns('', 12 | (r'^(\d+)/?$', redirect_to_github), 13 | ) 14 | -------------------------------------------------------------------------------- /templates/registration/activation_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Account activated{% endblock %} 4 | 5 | {% block content %} 6 |

Account activated.

7 |

Thanks for signing up! Now you can log in.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /docs/templates/docs/index.html: -------------------------------------------------------------------------------- 1 | {% extends "docs/doc.html" %} 2 | {% load staticfiles %} 3 | 4 | {% block extrahead %} 5 | {{ block.super }} 6 | 7 | {% endblock %} 8 | 9 | {% block toc-wrapper %}{% endblock %} 10 | -------------------------------------------------------------------------------- /templates/registration/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

You've been logged out.

7 |

Thanks for stopping by; when you come back, don't forget to log in again.

8 | {% endblock %} -------------------------------------------------------------------------------- /static/css/homepage.css: -------------------------------------------------------------------------------- 1 | @import url(base.css); 2 | 3 | .button-download { display:block; background:url(../img/site/download_bg-left.gif) no-repeat; } 4 | .button-download a { height:18px; color:white; display:block; white-space:nowrap; background:url(../img/site/download_bg-right.gif) top right no-repeat; padding:6px 12px; } 5 | -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import User 3 | 4 | class Profile(models.Model): 5 | user = models.OneToOneField(User) 6 | name = models.CharField(max_length=200, blank=True) 7 | 8 | def __unicode__(self): 9 | return self.name or unicode(self.user) 10 | -------------------------------------------------------------------------------- /legacy/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | class LegacyTests(TestCase): 4 | urls = 'legacy.urls' 5 | 6 | # Just a smoke test to ensure the URLconf works 7 | 8 | def test_gone(self): 9 | response = self.client.get('/comments/') 10 | self.assertEquals(response.status_code, 410) 11 | -------------------------------------------------------------------------------- /templates/base_code.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | {% load staticfiles %} 3 | 4 | {% block sectionid %}code{% endblock %} 5 | 6 | {% block title %}Code{% endblock %} 7 | 8 | {% block billboard %}

Django source code

{% endblock %} 9 | -------------------------------------------------------------------------------- /legacy/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | Legacy URLs for documentation pages. 3 | """ 4 | 5 | from __future__ import absolute_import 6 | 7 | from django.conf.urls import patterns 8 | 9 | from .views import gone 10 | 11 | urlpatterns = patterns('', 12 | (r'^comments/', gone), 13 | (r'^rss/comments/$', gone), 14 | (r'^documentation', gone), 15 | ) 16 | -------------------------------------------------------------------------------- /templates/blog/entry_snippet.html: -------------------------------------------------------------------------------- 1 | {% for e in entries %} 2 |

{{ e.headline }}

3 |

by {{ e.author }} on {{ e.pub_date|date:"M. j, Y" }}

4 | {{ e.summary_html|safe }} 5 |

Read more

6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /templates/registration/registration_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Registration complete{% endblock %} 4 | 5 | {% block content %} 6 |

Check your email

7 |

An activation link has been sent to the email address you supplied, along with instructions for activating your account.

8 | {% endblock %} -------------------------------------------------------------------------------- /accounts/profile_urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URLs for the profile pages (under ~) 3 | """ 4 | 5 | from __future__ import absolute_import 6 | from django.conf.urls import patterns, url, include 7 | from . import views as account_views 8 | 9 | urlpatterns = patterns('', 10 | r'^(?P[\w-]+)/$', account_views.user_profile, name='user_profile'), 11 | ) 12 | -------------------------------------------------------------------------------- /releases/urls.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | 3 | from django.conf.urls import patterns, url 4 | 5 | from .views import index, redirect 6 | 7 | urlpatterns = patterns('', 8 | url(r'^$', index, name='download'), 9 | url(r'^([0-9a-z_.-]+)/(tarball|checksum|egg)/$', redirect, name='download-redirect'), 10 | ) 11 | -------------------------------------------------------------------------------- /templates/blog/entry_detail.html: -------------------------------------------------------------------------------- 1 | {% extends "base_weblog.html" %} 2 | 3 | {% block title %}{{ object.headline|escape }} | Weblog{% endblock %} 4 | 5 | {% block content %} 6 |

{{ object.headline|safe }}

7 | {{ object.body_html|safe }} 8 |

Posted by {{ object.author }} on {{ object.pub_date|date:"F j, Y" }}

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /templates/base_2col.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block columnwrap %} 4 |
5 | {% block content %} 6 | {% endblock %} 7 |
8 | 9 | 13 | 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /static/css/documentation.css: -------------------------------------------------------------------------------- 1 | @import url(base.css); 2 | 3 | /*** p-links ***/ 4 | a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; visibility: hidden; } 5 | h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink { visibility: visible; } 6 | -------------------------------------------------------------------------------- /templates/blog/entry_archive_year.html: -------------------------------------------------------------------------------- 1 | {% extends "base_weblog.html" %} 2 | 3 | {% block title %}{{ year }} | Weblog{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

{{ year }} archive

8 | 9 | 14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /contact/views.py: -------------------------------------------------------------------------------- 1 | from django.core import urlresolvers 2 | from contact_form.views import ContactFormView 3 | from .forms import FoundationContactForm 4 | 5 | class ContactFoundation(ContactFormView): 6 | form_class = FoundationContactForm 7 | template_name = 'contact/foundation.html' 8 | 9 | def get_success_url(self): 10 | return urlresolvers.reverse('contact_form_sent') 11 | -------------------------------------------------------------------------------- /blog/sitemaps.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.contrib.sitemaps import Sitemap 4 | 5 | from .models import Entry 6 | 7 | class WeblogSitemap(Sitemap): 8 | changefreq = 'never' 9 | priority = 0.4 10 | 11 | def items(self): 12 | return Entry.objects.published() 13 | 14 | # lastmod wasn't implemented, because weblog pages used to contain comments. 15 | 16 | -------------------------------------------------------------------------------- /templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | 3 | {% block title %}Page unavailable{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

Page unavailable

8 | 9 |

We're sorry, but the requested page is currently unavailable.

10 | 11 |

We're messing around with things internally, and the server had a bit of a hiccup.

12 | 13 |

Please try again later.

14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | 3 | {% block title %}Page not found{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

Page not found

8 | 9 |

Looks like you followed a bad link. If you think it's our fault, please let us know.

10 | 11 |

Here's a link to the homepage. You know, just in case.

12 | 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /contact/urls.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.conf.urls import patterns, url 4 | from django.views.generic import TemplateView 5 | 6 | from .views import ContactFoundation 7 | 8 | urlpatterns = patterns('', 9 | url(r'^foundation/$', ContactFoundation.as_view(), name='contact_foundation'), 10 | url(r'^sent/$', TemplateView.as_view(template_name='contact/sent.html'), name='contact_form_sent'), 11 | ) 12 | -------------------------------------------------------------------------------- /templates/blog/entry_archive.html: -------------------------------------------------------------------------------- 1 | {% extends "base_weblog.html" %} 2 | 3 | {% block content %} 4 | 5 |

Latest entries

6 | 7 | {% for object in latest %} 8 |

{{ object.headline|safe }}

9 | {{ object.body_html|safe }} 10 |

Posted by {{ object.author }} on {{ object.pub_date|date:"F j, Y" }}

11 | {% endfor %} 12 | 13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /django_docs/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for django_docs project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_docs.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | -------------------------------------------------------------------------------- /docs/templates/docs/search_form.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | if '--docs' in sys.argv: 7 | settings_module = 'django_docs.settings' 8 | sys.argv.remove('--docs') 9 | else: 10 | settings_module = 'django_www.settings' 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module) 12 | 13 | from django.core.management import execute_from_command_line 14 | execute_from_command_line(sys.argv) 15 | -------------------------------------------------------------------------------- /templates/blog/entry_archive_day.html: -------------------------------------------------------------------------------- 1 | {% extends "base_weblog.html" %} 2 | 3 | {% block title %}{{ day|date:"F j" }} | Weblog{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

{{ day|date:"F j" }} archive

8 | 9 | {% for object in object_list %} 10 |

{{ object.headline|safe }}

11 |

{{ object.pub_date|date:"F j, Y" }}

12 | {{ object.body_html|safe }} 13 | 14 | {% endfor %} 15 | 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /templates/blog/entry_archive_month.html: -------------------------------------------------------------------------------- 1 | {% extends "base_weblog.html" %} 2 | 3 | {% block title %}{{ month|date:"F" }} | Weblog{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

{{ month|date:"F" }} archive

8 | 9 | {% for object in object_list %} 10 |

{{ object.headline|safe }}

11 |

{{ object.pub_date|date:"F j, Y" }}

12 | {{ object.body_html|safe }} 13 | 14 | {% endfor %} 15 | 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /templates/log_changelog.cs: -------------------------------------------------------------------------------- 1 | # 2 | # ChangeLog for 3 | # 4 | # Generated by Trac 5 | # 6 | # 7 | 8 | [] 10 | 11 | * : 13 | 14 | 15 | -------------------------------------------------------------------------------- /templates/registration/activate.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Account activation failed{% endblock %} 4 | 5 | {% block content %} 6 |

Account activation failed.

7 | {% load humanize %} 8 |

Sorry, it didn't work. Either your activation link was incorrect, or 9 | the activation key for your account has expired; activation keys are 10 | only valid for {{ expiration_days|apnumber }} days after 11 | registration.

12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /templates/410.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | 3 | {% block title %}Page removed{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

Page removed.

8 | 9 |

Sorry, we've removed some of parts of the site that were completely out 10 | of date. In most cases, that content has been moved into 11 | the new documentation site.

12 | 13 |

Here's a link to the homepage. You know, just in case.

14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /templates/aggregator/delete-confirm.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content %} 4 |

Community

5 | 6 |

Really delete {{ feed }}?

7 | 8 |

9 | All items in the aggregator will be deleted, too. Because Jacob's 10 | lazy, there's no "undo"! 11 |

12 | 13 |
14 | {% csrf_token %} 15 |

16 |
17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /django_docs/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url, include 2 | from django.http import HttpResponse 3 | 4 | from docs.sitemaps import DocsSitemap 5 | from docs.urls import urlpatterns as docs_urlpatterns 6 | 7 | sitemaps = {'docs': DocsSitemap} 8 | 9 | urlpatterns = docs_urlpatterns + patterns('', 10 | url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}), 11 | url(r'^google79eabba6bf6fd6d3\.html$', lambda req: HttpResponse('google-site-verification: google79eabba6bf6fd6d3.html')), 12 | ) 13 | -------------------------------------------------------------------------------- /django_www/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for django_www project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_www.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | 16 | from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user 17 | -------------------------------------------------------------------------------- /svntogit/views.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.http import HttpResponsePermanentRedirect, Http404 4 | from .mapping import svn_to_git 5 | 6 | def redirect_to_github(request, svn_revision): 7 | try: 8 | git_changeset = svn_to_git[int(svn_revision)] 9 | except IndexError: 10 | git_changeset = None 11 | if git_changeset is None: 12 | raise Http404 13 | github_url = 'https://github.com/django/django/commit/%s' % git_changeset 14 | return HttpResponsePermanentRedirect(github_url) 15 | 16 | -------------------------------------------------------------------------------- /templates/registration/activation_email.txt: -------------------------------------------------------------------------------- 1 | {% load humanize %} 2 | Someone, hopefully you, signed up for a new account at djangoproject.com using this email address. If it was you, and you'd like to activate and use your account, click the link below or copy and paste it into your web browser's address bar: 3 | 4 | http://www.djangoproject.com/accounts/activate/{{ activation_key }}/ 5 | 6 | If you didn't request this, you don't need to do anything; you won't receive any more email from us, and the account will expire automatically in {{ expiration_days|apnumber }} days. 7 | -------------------------------------------------------------------------------- /templates/base_3col.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block columnwrap %} 4 |
5 |
6 | {% block content %}{% endblock %} 7 |
8 | 9 | 12 | 13 |
14 | 15 | 18 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /blog/templatetags/weblog.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django import template 4 | from ..models import Entry 5 | 6 | register = template.Library() 7 | 8 | @register.inclusion_tag('blog/entry_snippet.html') 9 | def render_latest_blog_entries(num): 10 | entries = Entry.objects.published()[:num] 11 | return { 12 | 'entries': entries, 13 | } 14 | 15 | @register.inclusion_tag('blog/month_links_snippet.html') 16 | def render_month_links(): 17 | return { 18 | 'dates': Entry.objects.published().dates('pub_date', 'month'), 19 | } 20 | -------------------------------------------------------------------------------- /blog/feeds.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.contrib.syndication.views import Feed 4 | from .models import Entry 5 | 6 | 7 | class WeblogEntryFeed(Feed): 8 | title = "The Django weblog" 9 | link = "https://www.djangoproject.com/weblog/" 10 | description = "Latest news about Django, the Python Web framework." 11 | 12 | def items(self): 13 | return Entry.objects.published()[:10] 14 | 15 | def item_pubdate(self, item): 16 | return item.pub_date 17 | 18 | def item_author_name(self, item): 19 | return item.author 20 | 21 | def item_description(self, item): 22 | return item.body_html 23 | -------------------------------------------------------------------------------- /templates/contact/sent.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Message sent{% endblock %} 4 | 5 | {% block content %} 6 |

Message sent

7 |

Your message has been sent; thanks!

8 |

9 | Your mail will be read by a real, live human being. We can't 10 | guarantee when or whether you'll get a reply, but your message 11 | will be read, generally within the next couple of days. 12 |

13 |

14 | If you're expecting a reply and don't get one, please feel free 15 | to send a reminder. Please wait a few days, however, unless 16 | it's an emergency. 17 |

18 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% autoescape off %} 2 | {% trans "You're receiving this e-mail because you requested a password reset" %} 3 | {% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}. 4 | 5 | {% trans "Please go to the following page and choose a new password:" %} 6 | {% block reset_link %} 7 | {{ protocol }}://{{ domain }}{% url 'auth_password_reset_confirm' uidb36=uid token=token %} 8 | {% endblock %} 9 | {% trans "Your username, in case you've forgotten:" %} {{ user.username }} 10 | 11 | {% trans "Thanks for using our site!" %} 12 | 13 | {% blocktrans %}The {{ site_name }} team{% endblocktrans %} 14 | 15 | {% endautoescape %} 16 | -------------------------------------------------------------------------------- /contact/tests.py: -------------------------------------------------------------------------------- 1 | from django.core import mail 2 | from django.test import TestCase 3 | from django.test.utils import override_settings 4 | 5 | @override_settings(AKISMET_API_KEY='') # Disable Akismet in tests 6 | class ContactFormTests(TestCase): 7 | def test_foundation_contact(self): 8 | data = { 9 | 'name': 'A. Random Hacker', 10 | 'email': 'a.random@example.com', 11 | 'message_subject': 'Hello', 12 | 'body': 'Hello, World!' 13 | } 14 | resp = self.client.post('/contact/foundation/', data) 15 | self.assertRedirects(resp, '/contact/sent/') 16 | self.assertEqual(mail.outbox[-1].subject, '[Contact form] Hello') 17 | -------------------------------------------------------------------------------- /aggregator/forms.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django import forms 4 | from .models import Feed 5 | 6 | class FeedModelForm(forms.ModelForm): 7 | title = forms.CharField(max_length=250, 8 | help_text="title of the resource / blog.") 9 | feed_url = forms.URLField(label='Feed URL', 10 | help_text="link to the RSS/Atom feed. Please only use Django-specific feeds.") 11 | public_url = forms.URLField(label='Public URL', 12 | help_text="link to main page (i.e. blog homepage)") 13 | 14 | class Meta: 15 | model = Feed 16 | exclude = ('feed_type', 'owner', 'approval_status') 17 | -------------------------------------------------------------------------------- /cla/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from django.contrib import admin 3 | from .models import ICLA, CCLA, CCLADesignee 4 | 5 | class ICLAAdmin(admin.ModelAdmin): 6 | list_display = ['__unicode__', 'user', 'date_signed'] 7 | raw_id_fields = ['user'] 8 | ordering = ['-date_signed'] 9 | 10 | class DesigneeInline(admin.StackedInline): 11 | model = CCLADesignee 12 | raw_id_fields = ['user'] 13 | 14 | class CCLAAdmin(admin.ModelAdmin): 15 | list_display = ['company_name', 'contact_name', 'contact_email', 'date_signed'] 16 | ordering = ['-date_signed'] 17 | inlines = [DesigneeInline] 18 | 19 | admin.site.register(ICLA, ICLAAdmin) 20 | admin.site.register(CCLA, CCLAAdmin) 21 | -------------------------------------------------------------------------------- /blog/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.contrib import admin 4 | 5 | from .models import Entry 6 | 7 | class EntryAdmin(admin.ModelAdmin): 8 | list_display = ('headline', 'pub_date', 'is_active', 'is_published', 'author') 9 | list_filter = ('is_active',) 10 | exclude = ('summary_html', 'body_html') 11 | prepopulated_fields = {"slug": ("headline",)} 12 | 13 | def formfield_for_dbfield(self, db_field, **kwargs): 14 | formfield = super(EntryAdmin, self).formfield_for_dbfield(db_field, **kwargs) 15 | if db_field.name == 'body': 16 | formfield.widget.attrs['rows'] = 25 17 | return formfield 18 | 19 | admin.site.register(Entry, EntryAdmin) 20 | -------------------------------------------------------------------------------- /svntogit/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | class SvnToGitTests(TestCase): 4 | urls = 'svntogit.urls' 5 | 6 | def test_redirect(self): 7 | response = self.client.get('/1/', follow=False) 8 | target = 'https://github.com/django/django/commit/d6ded0e91b' 9 | self.assertEquals(response.status_code, 301) 10 | self.assertEquals(response['Location'], target) 11 | 12 | def test_redirect_empty_changeset(self): 13 | response = self.client.get('/7/') 14 | self.assertEquals(response.status_code, 404) 15 | 16 | def test_redirect_non_existing_changeset(self): 17 | response = self.client.get('/20000/') 18 | self.assertEquals(response.status_code, 404) 19 | -------------------------------------------------------------------------------- /templates/flatpages/foundation.html: -------------------------------------------------------------------------------- 1 | {% extends "base_foundation.html" %} 2 | 3 | {% block extrahead %} 4 | 16 | {% endblock %} 17 | 18 | {% block title %}{{ flatpage.title }}{% endblock %} 19 | 20 | {% block content %} 21 |

{{ flatpage.title }}

22 | {{ flatpage.content }} 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /deploy-requirements.txt: -------------------------------------------------------------------------------- 1 | # Requirements to deploy this code. 2 | 3 | akismet == 0.2.0 4 | Django == 1.5.4 5 | django-contact-form == 1.0 6 | django-haystack == 1.2.7 7 | django-push == 0.6 8 | django-registration==1.0 9 | django-secure == 1.0 10 | docutils == 0.10 11 | feedparser == 5.1.3 12 | Jinja2 == 2.6 13 | psycopg2 == 2.5 14 | python-memcached == 1.48 15 | raven == 1.4.6 16 | requests == 1.2.3 17 | South == 0.7.6 18 | Sphinx == 1.2 19 | Unipath == 1.0 20 | # xapian-haystack has a bug in 1.1.5beta fixed in trunk. 21 | -e git://github.com/notanumber/xapian-haystack.git@dc11c14542c0137831e5#egg=xapian-haystack 22 | 23 | # In production, xapian is installed with the python-xapian system package. 24 | # The virtualenv must have access to the global site-packages dir. 25 | -------------------------------------------------------------------------------- /static/css/print.css: -------------------------------------------------------------------------------- 1 | @import url(base.css); 2 | 3 | @page { 4 | size: US-Letter; 5 | margin: .75in .5in .75in 1in; 6 | } 7 | 8 | body { font-size:10pt; background: white; color: black; } 9 | 10 | /* Hide unneccessary content */ 11 | #header, #billboard, #content-extra, 12 | #documentation #content-secondary, #documentation #content-related, #doc-versions, 13 | h2.deck { display:none; } 14 | 15 | /* Fix widths */ 16 | #container { width:7in; } 17 | #subwrap, #content-main { width:7in; float:none; } 18 | 19 | /* Formatting and display fixes */ 20 | #content { border-top:none; } 21 | .literal-block { overflow:visible; } 22 | 23 | /* Typographic adjustments */ 24 | #content-main p, #content-main h2, #content-main h3, #content-main h4 { margin-bottom:1em; } 25 | -------------------------------------------------------------------------------- /blog/urls.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.conf.urls import patterns, url 4 | 5 | from . import views 6 | 7 | urlpatterns = patterns('', 8 | url(r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[\w-]+)/$', 9 | views.BlogDateDetailView.as_view() 10 | ), 11 | url(r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/$', 12 | views.BlogDayArchiveView.as_view() 13 | ), 14 | url(r'^(?P\d{4})/(?P[a-z]{3})/$', 15 | views.BlogMonthArchiveView.as_view() 16 | ), 17 | url(r'^(?P\d{4})/$', 18 | views.BlogYearArchiveView.as_view() 19 | ), 20 | url(r'^/?$', 21 | views.BlogArchiveIndexView.as_view(), 22 | name="blog-index" 23 | ), 24 | ) 25 | -------------------------------------------------------------------------------- /docs/sitemaps.py: -------------------------------------------------------------------------------- 1 | from django.contrib.sitemaps import Sitemap 2 | 3 | from .models import Document 4 | 5 | 6 | class DocsSitemap(Sitemap): 7 | 8 | def items(self): 9 | return (Document.objects 10 | .order_by('release__lang', '-release__version', 'path') 11 | .select_related('release')) 12 | 13 | def changefreq(self, obj): 14 | if obj.release.is_dev: 15 | return 'daily' 16 | elif obj.release.is_default: 17 | return 'monthly' 18 | else: 19 | return 'yearly' 20 | 21 | def priority(self, obj): 22 | if obj.release.is_dev: 23 | return 0.5 24 | elif obj.release.is_default: 25 | return 1 26 | else: 27 | return 0.1 28 | -------------------------------------------------------------------------------- /tracdb/db_router.py: -------------------------------------------------------------------------------- 1 | """ 2 | DB router for Trac. Very simple: just makes sure that all Trac tables are 3 | queries against the "trac" DB alias. 4 | 5 | It's very simplistic, leaving off allow_relation and allow_syncdb since all 6 | the Trac apps are unmanaged. 7 | """ 8 | 9 | from unipath import FSPath as Path 10 | 11 | THIS_APP = Path(__file__).parent.name 12 | 13 | class TracRouter(object): 14 | def db_for_read(self, model, **hints): 15 | return 'trac' if app_label(model) == THIS_APP else None 16 | 17 | def db_for_write(self, model, **hints): 18 | return 'trac' if app_label(model) == THIS_APP else None 19 | 20 | def allow_syncdb(self, db, model): 21 | return False if db == 'trac' else None 22 | 23 | def app_label(model): 24 | return model._meta.app_label 25 | -------------------------------------------------------------------------------- /templates/base_weblog.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | 3 | {% block extrahead %} 4 | 5 | {% endblock %} 6 | 7 | {% block sectionid %}weblog{% endblock %} 8 | 9 | {% block title %}Weblog{% endblock %} 10 | 11 | {% block billboard %}

Weblog

{% endblock %} 12 | 13 | {% block content-related %} 14 |

Archives

15 | {% load weblog %}{% render_month_links %} 16 | 17 |

RSS feeds

18 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /templates/aggregator/my-feeds.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content %} 4 |

Community

5 | 6 |

Manage your community aggregator feeds:

7 | 8 |
    9 | {% for feed in feeds %} 10 |
  • 11 | {{ feed }} ({{ feed.feed_url }}{{ feed.get_approval_status_display }}) — 12 | edit | 13 | delete 14 |
  • 15 | {% endfor %} 16 |
  • Add a new feed: 17 | {% for t in feed_types %} 18 | {{ t }} 19 | {% if not forloop.last %}|{% endif %} 20 | {% endfor %} 21 |
  • 22 | {#
  • Claim a feed already in the system.
  • #} 23 |
24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /releases/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.contrib import admin 4 | 5 | from .models import Release 6 | 7 | 8 | class ReleaseAdmin(admin.ModelAdmin): 9 | list_display = ('version', 'date', 'major', 'minor', 'micro', 'show_status', 'iteration') 10 | ordering = ('-major', '-minor', '-micro', '-status', '-iteration') 11 | 12 | def show_status(self, obj): 13 | return obj.get_status_display() 14 | show_status.admin_order_field = 'status' 15 | show_status.short_description = 'status' 16 | 17 | # Hack -- disable logging because it crashes on the non-integer pk 18 | def log_addition(self, request, object): pass 19 | def log_change(self, request, object, message): pass 20 | def log_deletion(self, request, object, object_repr): pass 21 | 22 | admin.site.register(Release, ReleaseAdmin) 23 | -------------------------------------------------------------------------------- /static/css/docs/docs.css: -------------------------------------------------------------------------------- 1 | /* A few fixups */ 2 | 3 | #content-main .jump_links { font-size: 1.2em; margin-left: 0px; } 4 | .synopsis { padding-left: 10px; color: #222;} 5 | 6 | /* Search form - sidebar */ 7 | #sidebar_search #id_sidebar_search_q { width: 100%; } 8 | 9 | /* Search form - search page */ 10 | #page_search { font-size: 150%; margin-top: 1.4em; margin-bottom: 1em; color: #092E20; } 11 | #page_search .submit { float: right; font-size: 150%; } 12 | 13 | /* Search results */ 14 | #search-results span.highlighted { background-color: #ffe761; font-weight: bold; } 15 | 16 | div.snippet-filename { 17 | color: white; background-color: #234F32; margin: 0; padding: 2px 5px; 18 | font-family: monospace; font-size: small; line-height: 1.3em; 19 | } 20 | div.snippet-filename + div.highlight > pre { margin-top: 0; } 21 | div.snippet-filename + pre { margin-top: 0; } 22 | -------------------------------------------------------------------------------- /static/css/docs/index.css: -------------------------------------------------------------------------------- 1 | 2 | p.rubric { font-size:150%; font-weight:normal; margin-bottom:.2em; color:#487858; } 3 | div.section dt { font-weight: normal; } 4 | 5 | #s-getting-help { float: right; width: 40%; background: #E1ECE2; padding: 1em; margin: 2em 0 2em 2em; } 6 | #s-getting-help h2 { margin: 0; } 7 | 8 | #s-django-documentation div.section div.section h3 { margin: 0; } 9 | #s-django-documentation div.section div.section { background: #E1ECE2; padding: 1em; margin: 2em 0 2em 57%; } 10 | #s-django-documentation div.section div.section a.reference { white-space: nowrap; } 11 | 12 | #s-using-django dl, 13 | #s-add-on-contrib-applications dl, 14 | #s-solving-specific-problems dl, 15 | #s-reference dl 16 | { float: left; width: 57%; } 17 | 18 | #s-add-on-contrib-applications, 19 | #s-solving-specific-problems, 20 | #s-reference, 21 | #s-and-all-the-rest 22 | { clear: left; } -------------------------------------------------------------------------------- /templates/tracdb/bouncing_tickets.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content-related %}{% endblock %} 4 | 5 | {% block title %}Bouncing Tickets{% endblock %} 6 | 7 | {% block content %} 8 | 9 |

Bouncing Tickets

10 | 11 |

Tickets that have been repeatedly reopened.

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for t in tickets %} 23 | 24 | 25 | 26 | 27 | 28 | {% endfor %} 29 | 30 |
TicketTimes reopenedLast reopened
#{{ t.id }}: {{ t.summary|truncatewords:10 }}{{ t.times_reopened }}{{ t.last_reopen_time|date:"F j, Y" }}
31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /templates/aggregator/edit-feed.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content %} 4 |

Community

5 | 6 | {% if adding %} 7 |

Add a {{ feed_type }} feed:

8 | {% else %} 9 |

Edit {{ feed }}:

10 | {% endif %} 11 | 12 |
13 | {% csrf_token %} 14 | {% for field in form %} 15 |

16 | 17 | {% if field.errors %} 18 |

{{ field.errors.as_text }}

19 | {% endif %} 20 | {{ field }} 21 |

22 | {% endfor %} 23 | {% if adding %} 24 |

25 | {% else %} 26 |

27 | {% endif %} 28 |
29 | 30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /blog/views.py: -------------------------------------------------------------------------------- 1 | from django.views.generic.dates import (ArchiveIndexView, YearArchiveView, 2 | MonthArchiveView, DayArchiveView, DateDetailView) 3 | 4 | from .models import Entry 5 | 6 | class BlogViewMixin(object): 7 | 8 | date_field = 'pub_date' 9 | 10 | def get_allow_future(self): 11 | return self.request.user.is_staff 12 | 13 | def get_queryset(self): 14 | if self.request.user.is_staff: 15 | return Entry.objects.all() 16 | else: 17 | return Entry.objects.published() 18 | 19 | class BlogArchiveIndexView(BlogViewMixin, ArchiveIndexView): 20 | pass 21 | 22 | class BlogYearArchiveView(BlogViewMixin, YearArchiveView): 23 | pass 24 | 25 | class BlogMonthArchiveView(BlogViewMixin, MonthArchiveView): 26 | pass 27 | 28 | class BlogDayArchiveView(BlogViewMixin, DayArchiveView): 29 | pass 30 | 31 | class BlogDateDetailView(BlogViewMixin, DateDetailView): 32 | pass 33 | -------------------------------------------------------------------------------- /aggregator/urls.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.conf.urls import patterns, url 4 | 5 | from . import views 6 | 7 | urlpatterns = patterns('', 8 | url(r'^$', 9 | views.index, 10 | name='community-index' 11 | ), 12 | url(r'^mine/$', 13 | views.my_feeds, 14 | name='community-my-feeds' 15 | ), 16 | url( 17 | r'^(?P[-\w]+)/$', 18 | views.FeedListView.as_view(), 19 | name='community-feed-list' 20 | ), 21 | url( 22 | r'^add/(?P[-\w]+)/$', 23 | views.add_feed, 24 | name='community-add-feed' 25 | ), 26 | url( 27 | r'^edit/(?P\d+)/$', 28 | views.edit_feed, 29 | name='community-edit-feed' 30 | ), 31 | url( 32 | r'^delete/(?P\d+)/$', 33 | views.delete_feed, 34 | name='community-delete-feed' 35 | ), 36 | ) 37 | 38 | -------------------------------------------------------------------------------- /tracdb/views.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from django.shortcuts import render 3 | from django import db 4 | from django.utils.tzinfo import FixedOffset 5 | 6 | def bouncing_tickets(request): 7 | c = db.connections['trac'].cursor() 8 | c.execute("""SELECT * FROM bouncing_tickets 9 | WHERE times_reopened >= 3 10 | ORDER BY last_reopen_time DESC""") 11 | tickets = dictfetchall(c) 12 | 13 | # Fix timestamps. LOLTrac. 14 | for t in tickets: 15 | t['last_reopen_time'] = ts2dt(t['last_reopen_time']) 16 | 17 | return render(request, 18 | 'tracdb/bouncing_tickets.html', 19 | {'tickets': tickets} 20 | ) 21 | 22 | def ts2dt(ts): 23 | epoc = datetime.datetime(1970, 1, 1, tzinfo=FixedOffset(0)) 24 | return epoc + datetime.timedelta(microseconds=ts) 25 | 26 | def dictfetchall(cursor): 27 | desc = cursor.description 28 | return [ 29 | dict(zip([col[0] for col in desc], row)) 30 | for row in cursor.fetchall() 31 | ] 32 | -------------------------------------------------------------------------------- /docs/utils.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.http import Http404 3 | from unipath import FSPath as Path 4 | 5 | def get_doc_root(lang, version): 6 | return Path(settings.DOCS_BUILD_ROOT).child(lang, version, "_built", "json") 7 | 8 | def get_doc_root_or_404(lang, version): 9 | docroot = get_doc_root(lang, version) 10 | if not docroot.exists(): 11 | raise Http404(docroot) 12 | return docroot 13 | 14 | def get_doc_path(docroot, subpath): 15 | # First look for /index.fjson, then for .fjson 16 | bits = subpath.strip('/').split('/') + ['index.fjson'] 17 | doc = docroot.child(*bits) 18 | if doc.exists(): 19 | return doc 20 | 21 | bits = bits[:-2] + ['%s.fjson' % bits[-2]] 22 | doc = docroot.child(*bits) 23 | if doc.exists(): 24 | return doc 25 | 26 | return None 27 | 28 | def get_doc_path_or_404(docroot, subpath): 29 | doc = get_doc_path(docroot, subpath) 30 | if doc is None: 31 | raise Http404(doc) 32 | return doc 33 | -------------------------------------------------------------------------------- /releases/migrations/0002_auto__chg_field_release_date.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | 12 | # Changing field 'Release.date' 13 | db.alter_column(u'releases_release', 'date', self.gf('django.db.models.fields.DateField')()) 14 | 15 | def backwards(self, orm): 16 | 17 | # Changing field 'Release.date' 18 | db.alter_column(u'releases_release', 'date', self.gf('django.db.models.fields.DateField')(null=True)) 19 | 20 | models = { 21 | u'releases.release': { 22 | 'Meta': {'object_name': 'Release'}, 23 | 'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}), 24 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '16', 'primary_key': 'True'}) 25 | } 26 | } 27 | 28 | complete_apps = ['releases'] 29 | -------------------------------------------------------------------------------- /releases/tests.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | 3 | from django.contrib.redirects.models import Redirect 4 | from django.test import TestCase 5 | 6 | from .models import create_releases_up_to_1_5 7 | 8 | 9 | class LegacyURLsTests(TestCase): 10 | 11 | fixtures = ['redirects-downloads'] # provided by the legacy app 12 | 13 | def test_legacy_redirects(self): 14 | # Save list of redirects, then wipe them 15 | redirects = list(Redirect.objects.values_list('old_path', 'new_path')) 16 | Redirect.objects.all().delete() 17 | # Ensure the releases app faithfully reproduces the redirects 18 | create_releases_up_to_1_5() 19 | for old_path, new_path in redirects: 20 | response = self.client.get(old_path, follow=False) 21 | location = response.get('Location', '') 22 | if location.startswith('http://testserver'): 23 | location = location[17:] 24 | self.assertEquals(location, new_path) 25 | self.assertEquals(response.status_code, 301) 26 | -------------------------------------------------------------------------------- /templates/contact/coc_form.html: -------------------------------------------------------------------------------- 1 |
2 | {% csrf_token %} 3 | 4 | {# hardcoding inputs because they'll be included on the CoC page itself #} 5 |

6 | 7 | {% if form.name.errors %}

{{ form.name.errors.as_text }}

{% endif %} 8 | 9 |

10 |

11 | 12 | {% if form.email.errors %}

{{ form.email.errors.as_text }}

{% endif %} 13 | 14 |

15 |

16 | 17 | {% if form.body.errors %}

{{ form.body.errors.as_text }}

{% endif %} 18 | 19 |

20 |

21 | 22 |
23 | -------------------------------------------------------------------------------- /docs/search_indexes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import json 4 | from django.utils.html import strip_tags 5 | import haystack 6 | import haystack.indexes 7 | from . import utils 8 | from .models import Document 9 | 10 | class DocumentIndex(haystack.indexes.SearchIndex): 11 | text = haystack.indexes.CharField(document=True) 12 | lang = haystack.indexes.CharField(model_attr='release__lang', faceted=True) 13 | version = haystack.indexes.CharField(model_attr='release__version', faceted=True) 14 | path = haystack.indexes.CharField(model_attr='path') 15 | title = haystack.indexes.CharField(model_attr='title') 16 | 17 | def get_queryset(self): 18 | return Document.objects.all().select_related('release') 19 | 20 | def prepare_text(self, obj): 21 | root = utils.get_doc_root(obj.release.lang, obj.release.version) 22 | docpath = utils.get_doc_path(root, obj.path) 23 | with open(docpath) as fp: 24 | doc = json.load(fp) 25 | return strip_tags(doc['body']).replace(u'¶', '') 26 | 27 | haystack.site.register(Document, DocumentIndex) 28 | -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.conf.urls import patterns, url, include 4 | from django.contrib.auth import views as auth_views 5 | 6 | from registration.forms import RegistrationFormUniqueEmail 7 | from registration.backends.default.views import RegistrationView 8 | 9 | from . import views as account_views 10 | 11 | urlpatterns = patterns('', 12 | url( 13 | r'^register/$', 14 | RegistrationView.as_view(form_class=RegistrationFormUniqueEmail), 15 | name='registration_register', 16 | ), 17 | url( 18 | r'^edit/$', 19 | account_views.edit_profile, 20 | name='edit_profile', 21 | ), 22 | url( 23 | r'^reset/(?P[0-9A-Za-z]+)-(?P.+)/$', 24 | auth_views.password_reset_confirm, 25 | name='auth_password_reset_confim', 26 | ), 27 | url( 28 | r'^reset/done/$', 29 | auth_views.password_reset_complete, 30 | ), 31 | url(r'^_trac/userinfo/$', account_views.json_user_info), 32 | url(r'', include('registration.backends.default.urls')), 33 | ) 34 | -------------------------------------------------------------------------------- /tracdb/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from south.db import dbs 3 | from south.v2 import SchemaMigration 4 | 5 | # 6 | # Trac uses composite primary keys, which Django doesn't understand. 7 | # These views fix that, for certain values of "fix." 8 | # 9 | 10 | class Migration(SchemaMigration): 11 | def forwards(self, orm): 12 | db = dbs['trac'] 13 | db.execute('''CREATE VIEW "attachment_django_view" AS 14 | SELECT "type" || '.' || "id" || '.' || "filename" AS "django_id", * 15 | FROM attachment;''') 16 | db.execute('''CREATE VIEW "wiki_django_view" AS 17 | SELECT "name" || '.' || "version" AS "django_id", * 18 | FROM wiki;''') 19 | 20 | # Work around a limitation of South's support for multiple databases. 21 | # See http://south.aeracode.org/ticket/924. 22 | db.execute('COMMIT') 23 | 24 | def backwards(self, orm): 25 | db = dbs['trac'] 26 | db.execute('DROP VIEW "attachment_django_view";') 27 | db.execute('DROP VIEW "wiki_django_view";') 28 | db.execute('COMMMIT') 29 | -------------------------------------------------------------------------------- /releases/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding model 'Release' 12 | db.create_table(u'releases_release', ( 13 | ('version', self.gf('django.db.models.fields.CharField')(max_length=16, primary_key=True)), 14 | ('date', self.gf('django.db.models.fields.DateField')(null=True)), 15 | )) 16 | db.send_create_signal(u'releases', ['Release']) 17 | 18 | 19 | def backwards(self, orm): 20 | # Deleting model 'Release' 21 | db.delete_table(u'releases_release') 22 | 23 | 24 | models = { 25 | u'releases.release': { 26 | 'Meta': {'object_name': 'Release'}, 27 | 'date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 28 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '16', 'primary_key': 'True'}) 29 | } 30 | } 31 | 32 | complete_apps = ['releases'] 33 | -------------------------------------------------------------------------------- /docs/templates/docs/py-modindex.html: -------------------------------------------------------------------------------- 1 | {% extends "docs/doc.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %}{% trans "Module Index | Django Documentation" %}{% endblock %} 5 | {% block toc-wrapper %}{% endblock %} 6 | {% block current-page-title %}{% trans "Module Index" %}{% endblock %} 7 | 8 | {% block body %} 9 |

{% trans "Module Index" %}

10 | 11 | 16 | 17 | {% for letter, objects in doc.content %} 18 |

{{ letter|upper }}

19 |
    20 | {% for module_name, subtype, docname, path, platforms, qualifier, synopsis in objects %} 21 | {% if docname %} 22 |
  • 23 | {{ module_name }} 24 | {% if synopsis %} 25 |
    {{ synopsis }}
    26 | {% endif %} 27 |
  • 28 | {% endif %} 29 | 30 | {% endfor %} 31 |
32 | {% endfor %} 33 | 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Log in{% endblock %} 4 | 5 | {% block content %} 6 | 7 |

Log in

8 | 9 | {% if form.errors %} 10 |

Please correct the errors below:

11 | {% endif %} 12 | 13 |
14 | {% csrf_token %} 15 | 16 |
17 |
{% if form.username.errors %} {{ form.username.errors|join:", " }}{% endif %}
18 |
{{ form.username }}
19 |
{% if form.password.errors %} {{ form.password.errors|join:", " }}{% endif %}
20 |
{{ form.password }}
21 |
22 |
23 |
24 | {% endblock %} 25 | 26 | {% block content-related %} 27 |

If you don't have an account, you can sign 28 | up for one.

29 |

If you forgot your password, you can reset it.

30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /tracdb/migrations/0002_bouncing_tickets_view.py: -------------------------------------------------------------------------------- 1 | from south.db import dbs 2 | from south.v2 import SchemaMigration 3 | 4 | # 5 | # Create a database view for "bouncing" tickets - tickets that change their 6 | # state from closed back to open, possibly a number of times. 7 | # 8 | 9 | class Migration(SchemaMigration): 10 | viewname = "bouncing_tickets" 11 | viewquery = """ 12 | SELECT 13 | ticket.id, 14 | ticket.summary, 15 | COUNT(*) AS times_reopened, 16 | MAX(change.time) AS last_reopen_time 17 | FROM ticket_change AS change 18 | JOIN ticket ON change.ticket = ticket.id 19 | WHERE 20 | change.field = 'status' 21 | AND change.oldvalue = 'closed' 22 | AND change.newvalue != 'closed' 23 | AND ticket.resolution = 'wontfix' 24 | GROUP BY ticket.id, ticket.summary; 25 | """ 26 | 27 | def forwards(self, orm): 28 | db = dbs['trac'] 29 | db.execute("CREATE VIEW %s AS %s" % (self.viewname, self.viewquery)) 30 | db.execute('COMMIT') 31 | 32 | def backwards(self, orm): 33 | db = dbs['trac'] 34 | db.execute("DROP VIEW %s" % self.viewname) 35 | db.execute('COMMIT') 36 | -------------------------------------------------------------------------------- /templates/contact/foundation.html: -------------------------------------------------------------------------------- 1 | {% extends "base_foundation.html" %} 2 | 3 | {% block title %}Contact the Django Software Foundation{% endblock %} 4 | 5 | {% block content %} 6 |

Contact the Django Software Foundation

7 |
8 | {% csrf_token %} 9 |

10 | 11 | {% if form.name.errors %}

{{ form.name.errors.as_text }}

{% endif %} 12 | {{ form.name }} 13 |

14 |

15 | 16 | {% if form.email.errors %}

{{ form.email.errors.as_text }}

{% endif %} 17 | {{ form.email }} 18 |

19 |

20 | 21 | {% if form.message_subject.errors %}

{{ form.message_subject.errors.as_text }}

{% endif %} 22 | {{ form.message_subject }} 23 |

24 |

25 | 26 | {% if form.body.errors %}

{{ form.body.errors.as_text }}

{% endif %} 27 | {{ form.body }} 28 |

29 |

30 |
31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /templates/conduct/base.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content-related %} 4 |

Django Community Code of Conduct

5 | 6 | 13 | 14 |

License

15 |

16 | All content on this page is licensed under a 17 | Creative Commons 18 | Attribution license. 19 |

20 |

21 | 22 | CC-by 23 | 24 |

25 | {% endblock %} 26 | 27 | {% block title %}Django Code of Conduct{% endblock %} 28 | 29 | {% block extrahead %} 30 | {{ block.super }} 31 | 39 | {% endblock extrahead %} 40 | -------------------------------------------------------------------------------- /blog/migrations/0003_activate_existing_entries.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import DataMigration 5 | from django.db import models 6 | 7 | class Migration(DataMigration): 8 | 9 | def forwards(self, orm): 10 | orm['blog.Entry'].objects.update(is_active=True) 11 | 12 | def backwards(self, orm): 13 | "Write your backwards methods here." 14 | 15 | 16 | models = { 17 | 'blog.entry': { 18 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 19 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 20 | 'body': ('django.db.models.fields.TextField', [], {}), 21 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 22 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 23 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 24 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 25 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 26 | 'summary': ('django.db.models.fields.TextField', [], {}) 27 | } 28 | } 29 | 30 | complete_apps = ['blog'] 31 | -------------------------------------------------------------------------------- /templates/aggregator/feeditem_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content %} 4 |

Django community: {{ feed_type.name }} 5 | RSS

6 |

7 | This page, updated regularly, aggregates {{ feed_type.name }} 8 | from the Django community. 9 |

10 | 11 | {% for item in object_list %} 12 |

{{ item.title }}

13 |

Posted on {{ item.date_modified|date:"F j, Y" }} at {{ item.date_modified|date:"g:i A" }} by {{ item.feed.title }} RSS

14 |
15 | {{ item.summary|striptags|truncatewords:"200" }} 16 |
17 |

Read this post in context »

18 | {% endfor %} 19 | 20 | {% if is_paginated %} 21 | 30 | {% endif %} 31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /accounts/forms.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from django import forms 3 | from registration.forms import RegistrationFormUniqueEmail 4 | from .models import Profile 5 | 6 | class RegistrationForm(RegistrationFormUniqueEmail): 7 | def __init__(self, *args, **kwargs): 8 | super(RegistrationForm, self).__init__(*args, **kwargs) 9 | del self.fields["tos"] 10 | 11 | class ProfileForm(forms.ModelForm): 12 | """ 13 | A form for editing user profiles. 14 | 15 | Assumes that the Profile instance passed in has an associated User 16 | object. The view (see views.py) takes care of tha 17 | """ 18 | class Meta(object): 19 | model = Profile 20 | fields = ['name'] 21 | email = forms.EmailField(required=False) 22 | 23 | def __init__(self, *args, **kwargs): 24 | instance = kwargs.get('instance', None) 25 | if instance: 26 | kwargs.setdefault('initial', {}).update({'email': instance.user.email}) 27 | super(ProfileForm, self).__init__(*args, **kwargs) 28 | 29 | def save(self, commit=True): 30 | instance = super(ProfileForm, self).save(commit=commit) 31 | if 'email' in self.cleaned_data: 32 | instance.user.email = self.cleaned_data['email'] 33 | if commit: 34 | instance.user.save() 35 | return instance 36 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | To run locally, do the usual:: 2 | 3 | 1. Create a virtualenv 4 | 5 | 2. Install dependencies:: 6 | 7 | pip install -r deploy-requirements.txt 8 | pip install -r local-requirements.txt 9 | 10 | If you only need to deploy, and don't need to test any changes, 11 | you can use local-requirements.txt only. 12 | 13 | 3. Create a 'secrets.json' file in the directory above the checkout, containing 14 | something like:: 15 | 16 | { "secret_key": "xyz", 17 | "superfeedr_creds": ["any@email.com", "some_string"] } 18 | 19 | 4. Create databases:: 20 | 21 | createuser -d djangoproject 22 | createdb -O djangoproject djangoproject 23 | createuser code.djangoproject 24 | createdb -O code.djangoproject code.djangoproject 25 | 26 | 5. Create tables:: 27 | 28 | psql -d code.djangoproject < tracdb/trac.sql 29 | 30 | ./manage.py syncdb 31 | ./manage.py migrate 32 | 33 | and:: 34 | 35 | ./manage.py syncdb --docs 36 | ./manage.py migrate --docs 37 | 38 | if you want to run docs site. 39 | 40 | 6. For docs:: 41 | 42 | ./manage.py loaddata doc_releases.json --docs 43 | ./manage.py update_docs --docs 44 | 45 | Finally:: 46 | 47 | ./manage.py runserver 48 | 49 | This runs as ``www.djangoproject.com``. To run locally as 50 | ``docs.djangoproject.com``, use:: 51 | 52 | ./manage.py runserver --docs 53 | -------------------------------------------------------------------------------- /aggregator/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.contrib import admin 4 | from .models import Feed, FeedItem, FeedType, APPROVED_FEED, DENIED_FEED 5 | 6 | 7 | def mark_approved(modeladmin, request, queryset): 8 | for item in queryset.iterator(): 9 | item.approval_status = APPROVED_FEED 10 | item.save() 11 | mark_approved.short_description = "Mark selected feeds as approved." 12 | 13 | 14 | def mark_denied(modeladmin, request, queryset): 15 | for item in queryset.iterator(): 16 | item.approval_status = DENIED_FEED 17 | item.save() 18 | mark_denied.short_description = "Mark selected feeds as denied." 19 | 20 | 21 | admin.site.register(Feed, 22 | list_display=["title", "feed_type", "public_url", "approval_status"], 23 | list_filter=["feed_type", "approval_status"], 24 | ordering=["title"], 25 | search_fields=["title", "public_url"], 26 | raw_id_fields=['owner'], 27 | list_editable=["approval_status"], 28 | list_per_page=500, 29 | actions=[mark_approved, mark_denied], 30 | ) 31 | 32 | admin.site.register(FeedItem, 33 | list_display=['title', 'feed', 'date_modified'], 34 | list_filter=['feed'], 35 | search_fields=['feed__title', 'feed__public_url', 'title'], 36 | date_heirarchy=['date_modified'], 37 | ) 38 | 39 | admin.site.register(FeedType, 40 | prepopulated_fields={'slug': ('name',)}, 41 | ) 42 | -------------------------------------------------------------------------------- /docs/templates/docs/genindex.html: -------------------------------------------------------------------------------- 1 | {% extends "docs/doc.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %}{% trans "General Index | Django Documentation" %}{% endblock %} 5 | {% block toc-wrapper %}{% endblock %} 6 | {% block current-page-title %}{% trans "General Index" %}{% endblock %} 7 | 8 | {% block body %} 9 |

{% trans "General Index" %}

10 | 11 |

12 | {% for letter, _ in doc.genindexentries %} 13 | {{ letter }} {% if not forloop.last %} |{% endif %} 14 | {% endfor %} 15 |

16 | 17 | 18 | {% for letter, entries in doc.genindexentries %} 19 |

20 | 21 |

{{ letter }}

22 | 23 |
24 | {% for name, contents in entries %} 25 |
26 | {# contents.0 is a list of links for the item #} 27 | {% if contents.0 %} 28 | {{ name }} 29 | {% else %} 30 | {{ name }} 31 | {% endif %} 32 |
33 | 34 | {# contents.1 is a list of subitems #} 35 | {% if contents.1 %} 36 | {% for subname, sublinks in contents.1 %} 37 |
38 | {{ subname }} 39 | {% for link in sublinks|slice:"1:" %}, {% trans "[Link]" %}{% endfor %} 40 |
41 | {% endfor %} 42 | {% endif %} 43 | {% endfor %} 44 |
45 | {% endfor %} 46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /blog/migrations/0002_auto__add_field_entry_is_active.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Entry.is_active' 12 | db.add_column('blog_entries', 'is_active', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Entry.is_active' 18 | db.delete_column('blog_entries', 'is_active') 19 | 20 | 21 | models = { 22 | 'blog.entry': { 23 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 24 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 25 | 'body': ('django.db.models.fields.TextField', [], {}), 26 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 27 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 28 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 29 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 30 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 31 | 'summary': ('django.db.models.fields.TextField', [], {}) 32 | } 33 | } 34 | 35 | complete_apps = ['blog'] 36 | -------------------------------------------------------------------------------- /templates/accounts/edit_profile.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Edit your profile{% endblock %} 4 | 5 | {% block content %} 6 | 7 | {% if form.errors %} 8 |

Please correct the errors below: {{ form.non_field_errors }}

9 | {% endif %} 10 | 11 |

Edit your profile

12 | 13 |
14 | {% csrf_token %} 15 |

16 | 17 | {% if form.name.errors %} 18 |

{{ form.name.errors.as_text }}

19 | {% endif %} 20 | {{ form.name }} 21 |

22 |

23 | 24 | {% if form.email.errors %} 25 |

{{ form.email.errors.as_text }}

26 | {% endif %} 27 | {{ form.email }} 28 |

29 |

30 | {% endblock %} 31 | 32 | {% block content-related %} 33 |

Help

34 |

Use this form to edit your profile.

35 | 36 |

Use whatever name you'd like to be identified with on djangoproject.com. If 37 | you leave it blank, we'll identify you as {{ user.username }}, your 38 | username.

39 | 40 |

We hate spam as much as you do. We'll only use it to send you password reset 41 | emails. We'll also use this email to try to fetch a Gravatar. You can change the image for this 43 | email at Gravatar.

44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /templates/donate_thanks.html: -------------------------------------------------------------------------------- 1 | {% extends "flatpages/foundation.html" %} 2 | 3 | {% block title %}Thanks for your support!{% endblock %} 4 | 5 | {% block content %} 6 |

Thanks for your support!

7 |

Thank you for supporting Django. If you like, you can use one of the badges below to show your support and help us bring in other donors.

8 | 9 |

Copy and paste the source below each image to link to our donation page.

10 | 11 |

I donated to Django

12 | 13 |


126x54 I donated to Django (green)

14 | 15 |

I donated to Django

16 | 17 |


126x54 I donated to Django (grey)

18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /releases/migrations/0004_auto__add_field_release_is_lts.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding field 'Release.is_lts' 12 | db.add_column(u'releases_release', 'is_lts', 13 | self.gf('django.db.models.fields.BooleanField')(default=False), 14 | keep_default=False) 15 | 16 | 17 | def backwards(self, orm): 18 | # Deleting field 'Release.is_lts' 19 | db.delete_column(u'releases_release', 'is_lts') 20 | 21 | 22 | models = { 23 | u'releases.release': { 24 | 'Meta': {'object_name': 'Release'}, 25 | 'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}), 26 | 'is_lts': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 27 | 'iteration': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 28 | 'major': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 29 | 'micro': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 30 | 'minor': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 31 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), 32 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '16', 'primary_key': 'True'}) 33 | } 34 | } 35 | 36 | complete_apps = ['releases'] -------------------------------------------------------------------------------- /blog/migrations/0005_copy_entry_summary_and_body_to_html.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import DataMigration 5 | from django.db import models 6 | 7 | class Migration(DataMigration): 8 | 9 | def forwards(self, orm): 10 | for entry in orm['blog.Entry'].objects.all(): 11 | entry.summary_html = entry.summary 12 | entry.body_html = entry.body 13 | entry.save() 14 | 15 | def backwards(self, orm): 16 | "Write your backwards methods here." 17 | 18 | 19 | models = { 20 | 'blog.entry': { 21 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 22 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 23 | 'body': ('django.db.models.fields.TextField', [], {}), 24 | 'body_html': ('django.db.models.fields.TextField', [], {}), 25 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 26 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 27 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 28 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 29 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 30 | 'summary': ('django.db.models.fields.TextField', [], {}), 31 | 'summary_html': ('django.db.models.fields.TextField', [], {}) 32 | } 33 | } 34 | 35 | complete_apps = ['blog'] 36 | -------------------------------------------------------------------------------- /templates/aggregator/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block extrahead %} 4 | {{ block.super }} 5 | 12 | {% endblock %} 13 | 14 | {% block content %} 15 |

Community

16 |

This page, updated regularly, aggregates what's going on in the community.

17 | 18 | {% if messages %} 19 |
    20 | {% for message in messages %} 21 | {{ message }} 22 | {% endfor %} 23 |
24 | {% endif %} 25 | 26 | {% for feedtype, latest_feeds in feedtype_list %} 27 |
28 |

29 | {{ feedtype.name }} 30 | RSS 31 |

32 | {% for item in latest_feeds %} 33 |
{{ item.title }}
34 |

{{ item.date_modified|date:"N jS, Y \a\t P" }} by {{ item.feed.title }}

35 | {% endfor %} 36 |

37 | {% if latest_feeds %} 38 | View more 39 | {% endif %} 40 | {% if latest_feeds and feedtype.can_self_add %} 41 | or 42 | {% endif %} 43 | {% if feedtype.can_self_add %} 44 | Add your feed 45 | {% endif %}

46 |
47 | {% endfor %} 48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /docs/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url 2 | 3 | from haystack.views import search_view_factory 4 | 5 | from . import views 6 | 7 | urlpatterns = patterns('', 8 | url( 9 | r'^$', 10 | views.index, 11 | ), 12 | url( 13 | r'^search/$', 14 | search_view_factory(view_class=views.DocSearchView), 15 | name='document-search' 16 | ), 17 | url( 18 | r'^(?P[a-z-]+)/$', 19 | views.language, 20 | ), 21 | url( 22 | r'^(?P[a-z-]+)/(?Pstable)/(?P.*)$', 23 | views.stable, 24 | ), 25 | url( 26 | r'^(?P[a-z-]+)/(?P[\w.-]+)/$', 27 | views.document, 28 | {'url': ''}, 29 | name='document-index', 30 | ), 31 | url( 32 | r'^(?P[a-z-]+)/(?P[\w.-]+)/_objects/$', 33 | views.objects_inventory, 34 | name='objects-inv', 35 | ), 36 | url( 37 | r'^(?P[a-z-]+)/(?P[\w.-]+)/_images/(?P.*)$', 38 | views.SphinxStatic('_images'), 39 | ), 40 | url( 41 | r'^(?P[a-z-]+)/(?P[\w.-]+)/_source/(?P.*)$', 42 | views.SphinxStatic('_sources'), 43 | ), 44 | url( 45 | r'^(?P[a-z-]+)/(?P[\w.-]+)/_downloads/(?P.*)$', 46 | views.SphinxStatic('_downloads'), 47 | ), 48 | url( 49 | r'^(.*)/index/$', 50 | views.redirect_index, 51 | ), 52 | url( 53 | r'^(?P[a-z-]+)/(?P[\w.-]+)/(?P[\w./-]*)/$', 54 | views.document, 55 | name='document-detail', 56 | ), 57 | ) 58 | -------------------------------------------------------------------------------- /blog/migrations/0007_existing_entries_are_raw_html.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import DataMigration 5 | from django.db import models 6 | 7 | class Migration(DataMigration): 8 | 9 | def forwards(self, orm): 10 | for entry in orm['blog.Entry'].objects.all(): 11 | entry.use_raw_html = True 12 | entry.save() 13 | 14 | def backwards(self, orm): 15 | "Write your backwards methods here." 16 | 17 | 18 | models = { 19 | 'blog.entry': { 20 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 21 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 22 | 'body': ('django.db.models.fields.TextField', [], {}), 23 | 'body_html': ('django.db.models.fields.TextField', [], {}), 24 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 25 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 26 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 27 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 28 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 29 | 'summary': ('django.db.models.fields.TextField', [], {}), 30 | 'summary_html': ('django.db.models.fields.TextField', [], {}), 31 | 'use_raw_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 32 | } 33 | } 34 | 35 | complete_apps = ['blog'] 36 | -------------------------------------------------------------------------------- /templates/query_rss.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | <?cs var:project.name.encoded ?>: Ticket Query 7 | Ticket Query 9 | 11 | 13 | en-us 14 | 15 | <?cs var:project.name.encoded ?> 16 | 20 | 22 | 25 | 27 | 28 | Trac v 30 | 31 | 32 | 33 | <?cs var:'#' + result.id + ': ' + result.summary ?> 35 | 38 | 40 | 41 | Tickets 42 | #changelog 43 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /aggregator/management/commands/update_subscriptions.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from datetime import timedelta 4 | 5 | from django.conf import settings 6 | from django.core.management.base import NoArgsCommand 7 | from django.utils import timezone 8 | from django_push.subscriber.models import Subscription 9 | 10 | from ...models import Feed, APPROVED_FEED 11 | 12 | 13 | logger = logging.getLogger(__name__) 14 | 15 | 16 | class Command(NoArgsCommand): 17 | def handle_noargs(self, **kwargs): 18 | feed_urls = set(Feed.objects.filter( 19 | approval_status=APPROVED_FEED 20 | ).values_list('feed_url', flat=True)) 21 | 22 | subscribed_urls = set(Subscription.objects.values_list('topic', 23 | flat=True)) 24 | 25 | missing_feeds = feed_urls - subscribed_urls 26 | extra_feeds = subscribed_urls - feed_urls 27 | 28 | for url in missing_feeds: 29 | logger.info(u'Subscribing to {0}'.format(url)) 30 | Subscription.objects.subscribe(url, settings.PUSH_HUB) 31 | 32 | for subscription in Subscription.objects.filter(topic__in=extra_feeds): 33 | logger.info(u'Unsubscribing from {0} ({1})'.format( 34 | subscription.pk, subscription.topic)) 35 | subscription.unsubscribe() 36 | 37 | limit = timezone.now() + timedelta(days=2) 38 | for subscription in Subscription.objects.exclude( 39 | topic__in=extra_feeds).filter(lease_expiration__lte=limit): 40 | logger.info(u'Renewing subscription for {0} ({1})'.format( 41 | subscription.topic, subscription.pk)) 42 | subscription.subscribe() 43 | -------------------------------------------------------------------------------- /blog/migrations/0008_auto__del_field_entry_use_raw_html.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Deleting field 'Entry.use_raw_html' 12 | db.delete_column('blog_entries', 'use_raw_html') 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Adding field 'Entry.use_raw_html' 18 | db.add_column('blog_entries', 'use_raw_html', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) 19 | 20 | 21 | models = { 22 | 'blog.entry': { 23 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 24 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 25 | 'body': ('django.db.models.fields.TextField', [], {}), 26 | 'body_html': ('django.db.models.fields.TextField', [], {}), 27 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 30 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 31 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 32 | 'summary': ('django.db.models.fields.TextField', [], {}), 33 | 'summary_html': ('django.db.models.fields.TextField', [], {}) 34 | } 35 | } 36 | 37 | complete_apps = ['blog'] 38 | -------------------------------------------------------------------------------- /django_ux/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Django User Experience Team 4 | 5 | 6 | 7 | 8 |
9 |

DjangoUX

10 |

Django User Experience Team

11 |
12 |
13 |

We make Django delightful to use.

14 |

We are designers of every stripe: user experience, interaction, visual. We are information architects and content strategists. We don't always know how to write code. We want the entire Django ecosystem to benefit from our talents.

15 |

Sound like something you'd like to be involved in? Don't be shy.

16 |

Join the mailing list!

17 |
18 |
19 |
20 |

Chaired by

21 |
22 | 27 | 32 | 33 |
34 | 35 | -------------------------------------------------------------------------------- /blog/migrations/0006_auto__add_field_entry_use_raw_html.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Entry.use_raw_html' 12 | db.add_column('blog_entries', 'use_raw_html', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Entry.use_raw_html' 18 | db.delete_column('blog_entries', 'use_raw_html') 19 | 20 | 21 | models = { 22 | 'blog.entry': { 23 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 24 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 25 | 'body': ('django.db.models.fields.TextField', [], {}), 26 | 'body_html': ('django.db.models.fields.TextField', [], {}), 27 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 30 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 31 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 32 | 'summary': ('django.db.models.fields.TextField', [], {}), 33 | 'summary_html': ('django.db.models.fields.TextField', [], {}), 34 | 'use_raw_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) 35 | } 36 | } 37 | 38 | complete_apps = ['blog'] 39 | -------------------------------------------------------------------------------- /blog/migrations/0009_auto__add_field_entry_content_format.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Entry.content_format' 12 | db.add_column('blog_entries', 'content_format', self.gf('django.db.models.fields.CharField')(default='html', max_length=50), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Entry.content_format' 18 | db.delete_column('blog_entries', 'content_format') 19 | 20 | 21 | models = { 22 | 'blog.entry': { 23 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 24 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 25 | 'body': ('django.db.models.fields.TextField', [], {}), 26 | 'body_html': ('django.db.models.fields.TextField', [], {}), 27 | 'content_format': ('django.db.models.fields.CharField', [], {'max_length': '50'}), 28 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 29 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 30 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 31 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 32 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 33 | 'summary': ('django.db.models.fields.TextField', [], {}), 34 | 'summary_html': ('django.db.models.fields.TextField', [], {}) 35 | } 36 | } 37 | 38 | complete_apps = ['blog'] 39 | -------------------------------------------------------------------------------- /docs/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from .forms import DocSearchForm 4 | from .models import DocumentRelease 5 | 6 | 7 | class SearchFormTestCase(TestCase): 8 | fixtures = ['doc_test_fixtures'] 9 | 10 | def test_unbound_form(self): 11 | """ 12 | An unbound form should have the default release selected. 13 | """ 14 | release = DocumentRelease.objects.get(pk=1) 15 | f = DocSearchForm(default_release=release) 16 | 17 | self.assertIn(' 22 | 23 | 24 | {% if query %} 25 | {% load highlight %} 26 |

{% trans "Results" %}

27 |
28 | {% for result in page.object_list %} 29 |

30 | {{ result.title }} 31 |

32 |

{% highlight result.text with query max_length 200 %}

33 | {% empty %} 34 |

{% trans "No results found." %}

35 | {% endfor %} 36 |
37 | 38 | {% if page.has_previous or page.has_next %} 39 |
40 | {% if page.has_previous %} 41 | 42 | {% endif %} 43 | « {% trans "Previous" %} 44 | {% if page.has_previous %}{% endif %} 45 | | 46 | {% if page.has_next %} 47 | 48 | {% endif %} 49 | {% trans "Next" %} » 50 | {% if page.has_next %}{% endif %} 51 |
52 | {% endif %} 53 | {% endif %} 54 | {% endblock %} 55 | -------------------------------------------------------------------------------- /aggregator/feeds.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.core import urlresolvers 4 | from django.contrib.syndication.views import Feed 5 | from django.shortcuts import get_object_or_404 6 | from .models import FeedType, FeedItem 7 | 8 | class BaseCommunityAggregatorFeed(Feed): 9 | def item_title(self, item): 10 | return item.title 11 | 12 | def item_description(self, item): 13 | return item.summary 14 | 15 | def item_guid(self, item): 16 | return item.guid 17 | 18 | def item_link(self, item): 19 | return item.link 20 | 21 | def item_author_name(self, item): 22 | return item.feed.title 23 | 24 | def item_author_link(self, item): 25 | return item.feed.public_url 26 | 27 | def item_pubdate(self, item): 28 | return item.date_modified 29 | 30 | class CommunityAggregatorFeed(BaseCommunityAggregatorFeed): 31 | def get_object(self, request, slug=None): 32 | return get_object_or_404(FeedType, slug=slug) 33 | 34 | def items(self, obj): 35 | qs = FeedItem.objects.filter(feed__feed_type=obj) 36 | qs = qs.order_by('-date_modified') 37 | qs = qs.select_related('feed', 'feed__feed_type') 38 | return qs[:25] 39 | 40 | def title(self, obj): 41 | return "Django community aggregator: %s" % obj.name 42 | 43 | def link(self, obj): 44 | return urlresolvers.reverse('aggregator-feed', args=[obj.slug]) 45 | 46 | def description(self, obj): 47 | return self.title(obj) 48 | 49 | class CommunityAggregatorFirehoseFeed(BaseCommunityAggregatorFeed): 50 | title = 'Django community aggregator firehose' 51 | description = 'All activity from the Django community aggregator' 52 | 53 | def link(self): 54 | return urlresolvers.reverse('aggregator-firehose-feed') 55 | 56 | def items(self): 57 | qs = FeedItem.objects.order_by('-date_modified').select_related('feed') 58 | return qs[:50] -------------------------------------------------------------------------------- /blog/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Entry' 12 | db.create_table('blog_entries', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('pub_date', self.gf('django.db.models.fields.DateTimeField')()), 15 | ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50, db_index=True)), 16 | ('headline', self.gf('django.db.models.fields.CharField')(max_length=200)), 17 | ('summary', self.gf('django.db.models.fields.TextField')()), 18 | ('body', self.gf('django.db.models.fields.TextField')()), 19 | ('author', self.gf('django.db.models.fields.CharField')(max_length=100)), 20 | )) 21 | db.send_create_signal('blog', ['Entry']) 22 | 23 | 24 | def backwards(self, orm): 25 | 26 | # Deleting model 'Entry' 27 | db.delete_table('blog_entries') 28 | 29 | 30 | models = { 31 | 'blog.entry': { 32 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 33 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 34 | 'body': ('django.db.models.fields.TextField', [], {}), 35 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 36 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 37 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 38 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 39 | 'summary': ('django.db.models.fields.TextField', [], {}) 40 | } 41 | } 42 | 43 | complete_apps = ['blog'] 44 | -------------------------------------------------------------------------------- /docs/forms.py: -------------------------------------------------------------------------------- 1 | import haystack.forms 2 | from django import forms 3 | from .models import DocumentRelease 4 | 5 | 6 | class DocumentReleaseChoiceField(forms.ModelChoiceField): 7 | def __init__(self, *args, **kwargs): 8 | kwargs.setdefault('required', False) 9 | kwargs.setdefault('empty_label', None) 10 | kwargs.setdefault('queryset', DocumentRelease.objects.order_by('version')) 11 | super(DocumentReleaseChoiceField, self).__init__(*args, **kwargs) 12 | 13 | def label_from_instance(self, obj): 14 | return obj.human_version 15 | 16 | def bound_data(self, data, initial): 17 | """ 18 | If no data is given, return the initial data. 19 | This allows for a default release to always be selected, even if none 20 | was provided in the URL. 21 | """ 22 | return data or initial 23 | 24 | 25 | class DocSearchForm(haystack.forms.SearchForm): 26 | release = DocumentReleaseChoiceField() 27 | 28 | def __init__(self, data=None, **kwargs): 29 | self.default_release = kwargs.pop('default_release') 30 | super(DocSearchForm, self).__init__(data=data, **kwargs) 31 | self.fields['q'].widget = forms.TextInput(attrs={'type': 'search'}) 32 | self.fields['release'].queryset = self.fields['release'].queryset.filter(lang=self.default_release.lang) 33 | self.fields['release'].initial = self.default_release 34 | 35 | def search(self): 36 | results = super(DocSearchForm, self).search() 37 | assert self.cleaned_data # SearchForm.search() calls is_valid() 38 | release = self.cleaned_data['release'] 39 | results = results.filter(lang=release.lang, version=release.version) 40 | return results 41 | 42 | def clean_release(self): 43 | """If no release is provided we fall back to the default release.""" 44 | release = self.cleaned_data.get('release') 45 | return release if release else self.default_release 46 | -------------------------------------------------------------------------------- /aggregator/management/commands/send_pending_approval_email.py: -------------------------------------------------------------------------------- 1 | """ 2 | Send an email to settings.FEED_APPROVERS with the feeds that need to 3 | be manually approved. 4 | """ 5 | from __future__ import absolute_import 6 | 7 | from django.conf import settings 8 | from django.contrib.auth.models import User 9 | from django.core import mail 10 | from django.core.management.base import NoArgsCommand 11 | from django.template import Context, Template 12 | from ...models import Feed, PENDING_FEED 13 | 14 | class Command(NoArgsCommand): 15 | 16 | def handle_noargs(self, **kwargs): 17 | try: 18 | verbosity = int(kwargs['verbosity']) 19 | except (KeyError, TypeError, ValueError): 20 | verbosity = 1 21 | 22 | feeds = Feed.objects.filter(approval_status=PENDING_FEED) 23 | to_email = [x.email for x in User.objects.filter(groups__name=settings.FEED_APPROVERS_GROUP_NAME)] 24 | 25 | if len(feeds) == 0: 26 | if verbosity >= 1: 27 | print "There are no pending feeds. Skipping the email." 28 | return 29 | 30 | email = """The following feeds are pending approval: 31 | {% regroup feeds by feed_type as feed_grouping %}{% for group in feed_grouping %} 32 | {{ group.grouper }} {% for feed in group.list %} 33 | - {{ feed.title }} ( {{ feed.feed_url }} ) {% endfor %} 34 | {% endfor %} 35 | 36 | To approve them, visit: https://djangoproject.com{% url 'admin:aggregator_feed_changelist' %} 37 | """ 38 | 39 | message = Template(email).render(Context({'feeds': feeds})) 40 | if verbosity >= 2: 41 | print "Pending approval email:\n" 42 | print message 43 | 44 | mail.send_mail("django community feeds pending approval", message, 45 | 'nobody@djangoproject.com', to_email, 46 | fail_silently=False) 47 | 48 | if verbosity >= 1: 49 | print "Sent pending approval email to: %s" % (', '.join(to_email)) 50 | -------------------------------------------------------------------------------- /contact/forms.py: -------------------------------------------------------------------------------- 1 | from akismet import Akismet 2 | from django import forms 3 | from django.conf import settings 4 | from django.contrib.sites.models import Site 5 | from django.utils.encoding import force_bytes 6 | from contact_form.forms import ContactForm 7 | 8 | attrs = {'class': 'required'} 9 | 10 | class BaseContactForm(ContactForm): 11 | message_subject = forms.CharField(max_length=100, widget=forms.TextInput(attrs=attrs), label=u'Message subject') 12 | 13 | def subject(self): 14 | return "[Contact form] " + self.cleaned_data["message_subject"] 15 | 16 | def message(self): 17 | return u"From: {name} <{email}>\n\n{body}".format(**self.cleaned_data) 18 | 19 | def clean_body(self): 20 | """ 21 | Check spam against Akismet. 22 | 23 | Backported from django-contact-form pre-1.0; 1.0 dropped built-in 24 | Akismet support. 25 | """ 26 | if 'body' in self.cleaned_data and hasattr(settings, 'AKISMET_API_KEY') and settings.AKISMET_API_KEY: 27 | akismet_api = Akismet(key=settings.AKISMET_API_KEY, 28 | blog_url='http://%s/' % Site.objects.get_current().domain) 29 | if akismet_api.verify_key(): 30 | akismet_data = {'comment_type': 'comment', 31 | 'referer': self.request.META.get('HTTP_REFERER', ''), 32 | 'user_ip': self.request.META.get('REMOTE_ADDR', ''), 33 | 'user_agent': self.request.META.get('HTTP_USER_AGENT', '')} 34 | comment = force_bytes(self.cleaned_data['body']) # workaround for #21444 35 | if akismet_api.comment_check(comment, data=akismet_data, build_data=True): 36 | raise forms.ValidationError(u"Akismet thinks this message is spam") 37 | return self.cleaned_data['body'] 38 | 39 | class FoundationContactForm(BaseContactForm): 40 | recipient_list = ["dsf-board@googlegroups.com"] 41 | -------------------------------------------------------------------------------- /blog/migrations/0004_auto__add_field_entry_summary_html__add_field_entry_body_html.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Entry.summary_html' 12 | db.add_column('blog_entries', 'summary_html', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False) 13 | 14 | # Adding field 'Entry.body_html' 15 | db.add_column('blog_entries', 'body_html', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False) 16 | 17 | 18 | def backwards(self, orm): 19 | 20 | # Deleting field 'Entry.summary_html' 21 | db.delete_column('blog_entries', 'summary_html') 22 | 23 | # Deleting field 'Entry.body_html' 24 | db.delete_column('blog_entries', 'body_html') 25 | 26 | 27 | models = { 28 | 'blog.entry': { 29 | 'Meta': {'ordering': "('-pub_date',)", 'object_name': 'Entry', 'db_table': "'blog_entries'"}, 30 | 'author': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 31 | 'body': ('django.db.models.fields.TextField', [], {}), 32 | 'body_html': ('django.db.models.fields.TextField', [], {}), 33 | 'headline': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 34 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 35 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 36 | 'pub_date': ('django.db.models.fields.DateTimeField', [], {}), 37 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), 38 | 'summary': ('django.db.models.fields.TextField', [], {}), 39 | 'summary_html': ('django.db.models.fields.TextField', [], {}) 40 | } 41 | } 42 | 43 | complete_apps = ['blog'] 44 | -------------------------------------------------------------------------------- /releases/views.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | 3 | from django.http import HttpResponsePermanentRedirect, Http404 4 | from django.shortcuts import get_object_or_404, render 5 | 6 | from .models import Release 7 | 8 | 9 | def index(request): 10 | # Build a dictionary of x => latest 1.x.y release 11 | releases = {} 12 | for release in Release.objects.final().order_by('minor', 'micro'): 13 | releases[release.minor] = release 14 | releases = [releases[minor] for minor in sorted(releases)] 15 | current = releases.pop() 16 | previous = releases.pop() 17 | # Handle preview releases 18 | try: 19 | preview = (Release.objects.preview() 20 | .filter(minor__gt=current.minor) 21 | .order_by('-minor', '-micro', '-status', '-iteration'))[0] 22 | except IndexError: 23 | preview_version = None 24 | preview_kind = None 25 | else: 26 | preview_version = preview.version 27 | preview_kind = { 28 | 'a': 'alpha', 29 | 'b': 'beta', 30 | 'c': 'release candidate', 31 | }[preview.status] 32 | 33 | # Look for an LTS release, if there is one. 34 | try: 35 | lts = Release.objects.lts() 36 | except IndexError: 37 | lts = None 38 | if lts == previous: 39 | lts = None 40 | 41 | context = { 42 | 'current_version': current.version, 43 | 'previous_version': previous.version, 44 | 'lts_version': lts.version if lts else None, 45 | 'earlier_versions': [release.version for release in reversed(releases) if release != lts], 46 | 'preview_version': preview_version, 47 | 'preview_kind': preview_kind, 48 | } 49 | return render(request, 'releases/download.html', context) 50 | 51 | 52 | def redirect(request, version, kind): 53 | release = get_object_or_404(Release, version=version) 54 | try: 55 | redirect_url = release.get_redirect_url(kind) 56 | except ValueError: 57 | raise Http404 58 | return HttpResponsePermanentRedirect(redirect_url) 59 | -------------------------------------------------------------------------------- /templates/conduct/changes.html: -------------------------------------------------------------------------------- 1 | {% extends "conduct/base.html" %} 2 | 3 | {% block title %}Django Code of Conduct - Changes{% endblock %} 4 | 5 | {% block content %} 6 |

Django Code of Conduct - Changes

7 | 8 |

Change control process

9 | 10 |

We're (mostly) programmers, so we'll track changes to the code of conduct and 11 | associated documents the same way we track changes to code. All changes will 12 | proposed via a pull request to the 13 | djangoproject.com repository 14 | on Github. Changes will be reviewed by the conduct committee first, and then 15 | sent to the the DSF, the Django core team, and the Django community for comment. 16 | We'll hold a comment period of at least one week, and then each group will vote 17 | on the change using its normal process (a board for the DSF, 18 | 19 | a core dev vote for the core team). 20 | Approved changes will be merged, published, and noted below.

21 | 22 |

This only applies to material changes; changes that don't effect the intent 23 | (typo fixes, re-wordings, etc.) can be made immediately.

24 | 25 |

A complete list of changes can always be found 26 | on Github; 27 | major changes and releases are summarized below.

28 | 29 |

Changelog

30 | 31 |
32 | 33 |
July 31, 2013
34 |
Documents approved and officially published.
35 | 36 |
July 15, 2013
37 |
38 | Added the reporting guide and enforcement manual. Final draft presented 39 | to the board and core membership for vote.
40 | 41 |
April 1, 2013
42 |
43 | Initial "beta" release and public call for comments.
44 | 45 |
46 | 47 | {% endblock %} 48 | -------------------------------------------------------------------------------- /templates/registration/registration_form.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base.html" %} 2 | 3 | {% block title %}Sign up{% endblock %} 4 | 5 | {% block content %} 6 | 7 | {% if form.errors %} 8 |

Please correct the errors below: {{ form.non_field_errors }}

9 | {% endif %} 10 | 11 |

Create an account

12 | 13 |
14 | {% csrf_token %} 15 |

16 | 17 | {% if form.username.errors %} 18 |

{{ form.username.errors.as_text }}

19 | {% endif %} 20 | {{ form.username }} 21 |

22 |

23 | 24 | {% if form.email.errors %} 25 |

{{ form.email.errors.as_text }}

26 | {% endif %} 27 | {{ form.email }} 28 |

29 |

30 | 31 | {% if form.password1.errors %} 32 |

{{ form.password1.errors.as_text }}

33 | {% endif %} 34 | {{ form.password1 }} 35 |

36 |

37 | 38 | {% if form.password2.errors %} 39 |

{{ form.password2.errors.as_text }}

40 | {% endif %} 41 | {{ form.password2 }} 42 |

43 |

44 |
45 | 46 | {% endblock %} 47 | 48 | {% block content-related %} 49 |

Fill out the form to the left (all fields are required), and your 50 | account will be created; you'll be sent an email with instructions on how 51 | to finish your registration.

52 | 53 |

We'll only use your email to send you signup instructions. We hate spam 54 | as much as you do.

55 | 56 |

This account will let you log into the ticket tracker, claim tickets, 57 | and be exempt from spam filtering.

58 | 59 |

Your username can only consist of alphanumeric characters and 60 | underscores and may be up to 30 characters long.

61 | {% endblock %} 62 | -------------------------------------------------------------------------------- /tracdb/stats.py: -------------------------------------------------------------------------------- 1 | """ 2 | Various queries for grabbing interesting user stats from Trac. 3 | """ 4 | 5 | from __future__ import absolute_import 6 | import operator 7 | import django.db 8 | from django.utils.datastructures import SortedDict 9 | from .models import Revision, Ticket, TicketChange, Attachment 10 | 11 | _statfuncs = [] 12 | 13 | def stat(title): 14 | """ 15 | Register a function as a "stat" 16 | 17 | The function should take a username and return a number. 18 | """ 19 | 20 | def _inner(f): 21 | _statfuncs.append(f) 22 | f.title = title 23 | return f 24 | return _inner 25 | 26 | def get_user_stats(username): 27 | stats = SortedDict() 28 | for func in sorted(_statfuncs, key=operator.attrgetter('title')): 29 | stats[func.title] = func(username) 30 | return stats 31 | 32 | @stat('Commits') 33 | def commit_count(username): 34 | return Revision.objects.filter(author=username).count() 35 | 36 | @stat('Tickets closed') 37 | def tickets_closed(username): 38 | # Raw query so that we can do COUNT(DISTINCT ticket). 39 | q = """SELECT COUNT(DISTINCT ticket) FROM ticket_change 40 | WHERE author = %s AND field = 'status' AND newvalue = 'closed';""" 41 | return run_single_value_query(q, username) 42 | 43 | @stat('Tickets opened') 44 | def tickets_opened(username): 45 | return Ticket.objects.filter(reporter=username).count() 46 | 47 | @stat('New tickets reviewed') 48 | def new_tickets_reviewed(username): 49 | # We don't want to de-dup as for tickets_closed: multiple reviews of the 50 | # same ticket should "count" as a review. 51 | qs = TicketChange.objects.filter(author=username, field='stage', oldvalue='Unreviewed') 52 | qs = qs.exclude(newvalue='Unreviewed') 53 | return qs.count() 54 | 55 | @stat('Patches submitted') 56 | def patches_submitted(username): 57 | return Attachment.objects.filter(author=username).count() 58 | 59 | def run_single_value_query(query, *params): 60 | """ 61 | Helper: run a query returning a single value (e.g. a COUNT) and return the value. 62 | """ 63 | c = django.db.connections['trac'].cursor() 64 | c.execute(query, params) 65 | return c.fetchone()[0] 66 | -------------------------------------------------------------------------------- /templates/base_foundation.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block content-related %} 4 |

Support Django

5 |

6 |

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 |

24 | 25 |

Read more about donating to the DSF. 26 | 27 |

Licensing & Trademarks

28 | 31 | 32 |

About the foundation

33 | 38 | 39 |

Mailing lists

40 | 41 |

dsf-volunteers: The list for volunteering to help with the foundation.

42 |

dsf-members: For members of the foundation.

43 | 44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /docs/templatetags/docs.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django import template 4 | from ..forms import DocSearchForm 5 | from ..models import DocumentRelease 6 | from ..utils import get_doc_root, get_doc_path 7 | 8 | register = template.Library() 9 | 10 | @register.inclusion_tag('docs/search_form.html', takes_context=True) 11 | def search_form(context, search_form_id='sidebar_search'): 12 | request = context['request'] 13 | auto_id = 'id_%s_%%s' % search_form_id 14 | release = DocumentRelease.objects.get(version=context['version'], lang=context['lang']) 15 | return { 16 | 'form': DocSearchForm(request.GET, auto_id=auto_id, default_release=release), 17 | 'search_form_id': search_form_id, 18 | } 19 | 20 | @register.tag 21 | def get_all_doc_versions(parser, token): 22 | """ 23 | Get a list of all versions of this document to link to. 24 | 25 | Usage: {% get_all_doc_versions as "varname" %} 26 | """ 27 | return AllDocVersionsTag.handle(parser, token) 28 | 29 | class AllDocVersionsTag(template.Node): 30 | @classmethod 31 | def handle(cls, parser, token): 32 | try: 33 | tagname, docurl, as_, asvar = token.split_contents() 34 | except ValueError: 35 | raise template.TemplateSyntaxError("Usage: {% get_all_doc_versions as %}") 36 | return cls(docurl, asvar) 37 | 38 | def __init__(self, docurl, asvar): 39 | self.docurl = template.Variable(docurl) 40 | self.asvar = asvar 41 | 42 | def render(self, context): 43 | try: 44 | url = self.docurl.resolve(context) 45 | except template.VariableDoesNotExist: 46 | return '' 47 | 48 | versions = [] 49 | lang = context.get('lang', 'en') 50 | 51 | # Look for each version of the docs. 52 | for release in DocumentRelease.objects.filter(lang=lang): 53 | version_root = get_doc_root(release.lang, release.version) 54 | if version_root.exists(): 55 | doc_path = get_doc_path(version_root, url) 56 | if doc_path: 57 | versions.append(release.version) 58 | 59 | # Save the versions into the context 60 | context[self.asvar] = sorted(versions) 61 | 62 | return '' 63 | -------------------------------------------------------------------------------- /docs/migrations/0002_add_document_model.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Document' 12 | db.create_table('docs_document', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('release', self.gf('django.db.models.fields.related.ForeignKey')(related_name='documents', to=orm['docs.DocumentRelease'])), 15 | ('path', self.gf('django.db.models.fields.CharField')(max_length=500)), 16 | ('title', self.gf('django.db.models.fields.CharField')(max_length=500)), 17 | ('content', self.gf('django.db.models.fields.TextField')()), 18 | )) 19 | db.send_create_signal('docs', ['Document']) 20 | 21 | 22 | def backwards(self, orm): 23 | 24 | # Deleting model 'Document' 25 | db.delete_table('docs_document') 26 | 27 | 28 | models = { 29 | 'docs.document': { 30 | 'Meta': {'object_name': 'Document'}, 31 | 'content': ('django.db.models.fields.TextField', [], {}), 32 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 33 | 'path': ('django.db.models.fields.CharField', [], {'max_length': '500'}), 34 | 'release': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': "orm['docs.DocumentRelease']"}), 35 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '500'}) 36 | }, 37 | 'docs.documentrelease': { 38 | 'Meta': {'object_name': 'DocumentRelease'}, 39 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 40 | 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 41 | 'lang': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), 42 | 'scm': ('django.db.models.fields.CharField', [], {'max_length': '10'}), 43 | 'scm_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), 44 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '20'}) 45 | } 46 | } 47 | 48 | complete_apps = ['docs'] 49 | -------------------------------------------------------------------------------- /django_ux/base.css: -------------------------------------------------------------------------------- 1 | html { 2 | /* background by subtlepatterns.com */ 3 | background: url(bg.png) repeat left top; 4 | } 5 | 6 | body { 7 | font-family: 'Open Sans', sans-serif; 8 | font-size: 100%; 9 | width: 600px; 10 | margin: 20px auto; 11 | padding: 50px 20px 20px; 12 | } 13 | 14 | #masthead>h1 { 15 | height: 63px; 16 | text-indent: -9999px; 17 | background: url(djangoux.png) no-repeat left center; 18 | margin: 0; 19 | font-weight: 800; 20 | } 21 | 22 | #masthead>h2 { 23 | font-family: "News Cycle", sans-serif; 24 | text-transform: uppercase; 25 | font-size: 1.8em; 26 | color: white; 27 | margin: 0.25em 0 0.5em; 28 | font-weight: 400; 29 | letter-spacing: 1px; 30 | } 31 | 32 | #content { 33 | margin-bottom: 2em; 34 | } 35 | 36 | #mailinglist { 37 | font-weight: 800; 38 | text-decoration: none; 39 | color: black; 40 | display: inline-block; 41 | background: rgba(255,255,255,0.2); 42 | padding: 5px; 43 | -webkit-border-radius: 4px; 44 | -moz-border-radius: 4px; 45 | border-radius: 4px; 46 | } 47 | 48 | #mailinglist:hover { 49 | text-decoration: underline; 50 | background: rgba(255,255,255,0.5); 51 | color: black; 52 | } 53 | 54 | #staff header h1 { 55 | font-weight: 400; 56 | font-style: italic; 57 | border-bottom: 1px solid rgba(0,0,0,0.2); 58 | font-size: 100%; 59 | padding-bottom: 0.5em; 60 | 61 | } 62 | 63 | .person { 64 | float: left; 65 | width: 122px; 66 | } 67 | 68 | .person>a { 69 | border: 1px solid #789340; 70 | background: #fff; 71 | padding: 5px; 72 | width: 72px; 73 | height: 72px; 74 | display: block; 75 | } 76 | 77 | .person>a:hover { 78 | background-color: #FFF0AF; 79 | } 80 | 81 | .person>a img { 82 | display: block; 83 | padding: 0; 84 | margin: 0; 85 | width: 72px; 86 | height: 72px; 87 | } 88 | 89 | .person h1 { 90 | font-weight: 400; 91 | font-size: 100%; 92 | margin-bottom: 0.2em; 93 | } 94 | 95 | .person h2 { 96 | font-weight: 400; 97 | font-style: italic; 98 | font-size: 0.75em; 99 | margin-top: 0; 100 | } 101 | 102 | .person h2 a { 103 | color: #000; 104 | text-decoration: none; 105 | } 106 | 107 | .person h2 a:hover { 108 | text-decoration: underline; 109 | } -------------------------------------------------------------------------------- /docs/migrations/0004_add_git_support.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'DocumentRelease.docs_subdir' 12 | db.add_column('docs_documentrelease', 'docs_subdir', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) 13 | 14 | # Changing field 'DocumentRelease.scm_url' 15 | db.alter_column('docs_documentrelease', 'scm_url', self.gf('django.db.models.fields.CharField')(max_length=200)) 16 | 17 | 18 | def backwards(self, orm): 19 | 20 | # Deleting field 'DocumentRelease.docs_subdir' 21 | db.delete_column('docs_documentrelease', 'docs_subdir') 22 | 23 | # Changing field 'DocumentRelease.scm_url' 24 | db.alter_column('docs_documentrelease', 'scm_url', self.gf('django.db.models.fields.URLField')(max_length=200)) 25 | 26 | 27 | models = { 28 | 'docs.document': { 29 | 'Meta': {'object_name': 'Document'}, 30 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 31 | 'path': ('django.db.models.fields.CharField', [], {'max_length': '500'}), 32 | 'release': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': "orm['docs.DocumentRelease']"}), 33 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '500'}) 34 | }, 35 | 'docs.documentrelease': { 36 | 'Meta': {'object_name': 'DocumentRelease'}, 37 | 'docs_subdir': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), 38 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 39 | 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 40 | 'lang': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), 41 | 'scm': ('django.db.models.fields.CharField', [], {'max_length': '10'}), 42 | 'scm_url': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 43 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '20'}) 44 | } 45 | } 46 | 47 | complete_apps = ['docs'] 48 | -------------------------------------------------------------------------------- /docs/migrations/0005_add_unicity_constaints.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding unique constraint on 'DocumentRelease', fields ['lang', 'version'] 12 | db.create_unique(u'docs_documentrelease', ['lang', 'version']) 13 | 14 | # Adding unique constraint on 'Document', fields ['release', 'path'] 15 | db.create_unique(u'docs_document', ['release_id', 'path']) 16 | 17 | 18 | def backwards(self, orm): 19 | # Removing unique constraint on 'Document', fields ['release', 'path'] 20 | db.delete_unique(u'docs_document', ['release_id', 'path']) 21 | 22 | # Removing unique constraint on 'DocumentRelease', fields ['lang', 'version'] 23 | db.delete_unique(u'docs_documentrelease', ['lang', 'version']) 24 | 25 | 26 | models = { 27 | u'docs.document': { 28 | 'Meta': {'unique_together': "(('release', 'path'),)", 'object_name': 'Document'}, 29 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 30 | 'path': ('django.db.models.fields.CharField', [], {'max_length': '500'}), 31 | 'release': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['docs.DocumentRelease']"}), 32 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '500'}) 33 | }, 34 | u'docs.documentrelease': { 35 | 'Meta': {'unique_together': "(('lang', 'version'),)", 'object_name': 'DocumentRelease'}, 36 | 'docs_subdir': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), 37 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 38 | 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 39 | 'lang': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), 40 | 'scm': ('django.db.models.fields.CharField', [], {'max_length': '10'}), 41 | 'scm_url': ('django.db.models.fields.CharField', [], {'max_length': '200'}), 42 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '20'}) 43 | } 44 | } 45 | 46 | complete_apps = ['docs'] -------------------------------------------------------------------------------- /templates/base_community.html: -------------------------------------------------------------------------------- 1 | {% extends "base_2col.html" %} 2 | 3 | {% block sectionid %}community{% endblock %} 4 | 5 | {% block title %}Community{% endblock %} 6 | 7 | {% block billboard %}

Community

{% endblock %} 8 | 9 | {% block content-related %} 10 |

Get involved

11 | 12 | 16 | 17 |

Mailing lists

18 | 19 |
    20 |
  • django-users: The main list for help and announcements.
  • 21 |
  • django-developers: Where the developers of Django itself discuss new features.
  • 22 |
23 | 24 |

Tell the world

25 | 31 | 32 |

Improve Django

33 | 37 | 38 |

Get help

39 | 40 |
    41 |
  • Check our FAQ first. If you have a basic question that's not answered by the FAQ, file a ticket to tell us you think it should be in there.
  • 42 |
  • Chat live with other Django users in the #django IRC channel on irc.freenode.net.
  • 43 |
  • Ask questions on the django-users mailing list.
  • 44 |
  • Report potential security issues in Django via private email to security@djangoproject.com, and not via Django's Trac instance or the django-developers mailing list
  • 45 |
46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /templates/accounts/user_profile.html: -------------------------------------------------------------------------------- 1 | {% extends "base_community.html" %} 2 | 3 | {% block title %}{% firstof user_obj.profile.name user_obj.username %}{% endblock %} 4 | {% block extrahead %} 5 | 18 | {% endblock extrahead %} 19 | {% block content-related %} 20 |

{% if user_obj == user %}This is you!{% else %}Is this you?{% endif %}

21 |

22 | Need to edit something? Here's how: 23 |

24 |
    25 |
  • Edit your name and email here.
  • 26 |
  • 27 | The image is the Gravatar linked 28 | to the email address you signed up with. You can change the image over 29 | at Gravatar. 30 | If you see a robot, that's because you don't have a Gravatar yet. 31 | (Robots provided by Robohash.) 32 |
  • 33 |
  • 34 | The rest of the data is read-only for the time being. If you see 35 | outragous errors, please email jacob @ this domain. 36 |
  • 37 |
38 | {% endblock %} 39 | 40 | {% block content %} 41 | {% load humanize %} 42 | 44 |
45 |

46 | {% firstof user_obj.profile.name user_obj.username %} 47 | {% if user_can_commit %}core{% endif %} 48 | {% if clas %}cla{% endif %} 49 |

50 | 51 | {% if stats %} 52 |

Lies, damned lies, and statistics:

53 |
    54 | {% for stat, value in stats.items %} 55 |
  • {{ stat }}: {{ value|intcomma }}.
  • 56 | {% endfor %} 57 |
58 | {% endif %} 59 | 60 | {% with user_obj.owned_feeds.all as feeds %} 61 | {% if feeds %} 62 |

Community feeds:

63 |
    64 | {% for f in feeds %} 65 |
  • {{ f.title }}
  • 66 | {% endfor %} 67 |
68 | {% endif %} 69 | {% endwith %} 70 |
71 | {% endblock content %} 72 | -------------------------------------------------------------------------------- /aggregator/migrations/0002_rename_tables.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | # rename tables from the hardcoded old names to the Django defaults. 11 | db.rename_table('aggregator_feeds', 'aggregator_feed') 12 | db.rename_table('aggregator_feeditems', 'aggregator_feeditem') 13 | 14 | def backwards(self, orm): 15 | db.rename_table('aggregator_feed', 'aggregator_feeds') 16 | db.rename_table('aggregator_feeditem', 'aggregator_feeditems') 17 | 18 | models = { 19 | 'aggregator.feed': { 20 | 'Meta': {'object_name': 'Feed'}, 21 | 'feed_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['aggregator.FeedType']"}), 22 | 'feed_url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '500'}), 23 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 24 | 'is_defunct': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 25 | 'public_url': ('django.db.models.fields.URLField', [], {'max_length': '500'}), 26 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '500'}) 27 | }, 28 | 'aggregator.feeditem': { 29 | 'Meta': {'ordering': "('-date_modified',)", 'object_name': 'FeedItem'}, 30 | 'date_modified': ('django.db.models.fields.DateTimeField', [], {}), 31 | 'feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['aggregator.Feed']"}), 32 | 'guid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '500', 'db_index': 'True'}), 33 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 34 | 'link': ('django.db.models.fields.URLField', [], {'max_length': '500'}), 35 | 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 36 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '500'}) 37 | }, 38 | 'aggregator.feedtype': { 39 | 'Meta': {'object_name': 'FeedType'}, 40 | 'can_self_add': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 41 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 42 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '250'}), 43 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '250', 'db_index': 'True'}) 44 | } 45 | } 46 | 47 | complete_apps = ['aggregator'] 48 | -------------------------------------------------------------------------------- /django_docs/settings.py: -------------------------------------------------------------------------------- 1 | # Settings for docs.djangoproject.com 2 | 3 | from django_www.common_settings import * 4 | 5 | 6 | ### Django settings 7 | 8 | ALLOWED_HOSTS = ['docs.djangoproject.com'] 9 | 10 | CACHE_MIDDLEWARE_KEY_PREFIX = 'djangodocs' 11 | 12 | INSTALLED_APPS = [ 13 | 'django.contrib.redirects', 14 | 'django.contrib.sitemaps', 15 | 'django.contrib.sites', 16 | 'django.contrib.staticfiles', 17 | 18 | 'djangosecure', 19 | 'haystack', 20 | 'south', 21 | 22 | 'docs', 23 | ] 24 | 25 | MIDDLEWARE_CLASSES = [ 26 | 'django.middleware.cache.UpdateCacheMiddleware', 27 | 'djangosecure.middleware.SecurityMiddleware', 28 | 'django.middleware.common.CommonMiddleware', 29 | 'django.contrib.redirects.middleware.RedirectFallbackMiddleware', 30 | 'django.middleware.cache.FetchFromCacheMiddleware' 31 | ] 32 | 33 | TEMPLATE_CONTEXT_PROCESSORS = [ 34 | 'django.contrib.auth.context_processors.auth', 35 | 'django.core.context_processors.debug', 36 | 'django.core.context_processors.i18n', 37 | 'django.core.context_processors.static', 38 | 'django.core.context_processors.media', 39 | 'django.contrib.messages.context_processors.messages', 40 | 'docs.context_processors.docs_version', 41 | 'django.core.context_processors.request', 42 | ] 43 | 44 | ROOT_URLCONF = 'django_docs.urls' 45 | 46 | SITE_ID = 2 47 | 48 | USE_I18N = True 49 | LANGUAGE_CODE = 'en' 50 | 51 | ### Docs settings 52 | 53 | if PRODUCTION: 54 | DOCS_BUILD_ROOT = BASE.parent.child('docbuilds') 55 | else: 56 | DOCS_BUILD_ROOT = BASE.child('djangodocs') 57 | 58 | 59 | ### Haystack settings 60 | 61 | HAYSTACK_SITECONF = 'docs.search_sites' 62 | 63 | if PRODUCTION: 64 | HAYSTACK_SEARCH_ENGINE = 'xapian' 65 | HAYSTACK_XAPIAN_PATH = BASE.parent.child('djangodocs.index') 66 | else: 67 | HAYSTACK_SEARCH_ENGINE = 'whoosh' 68 | HAYSTACK_WHOOSH_PATH = BASE.child('djangodocs.index') 69 | 70 | 71 | ### South settings 72 | 73 | SOUTH_TESTS_MIGRATE = False 74 | 75 | 76 | ### Enable optional components 77 | 78 | if DEBUG: 79 | try: 80 | import debug_toolbar 81 | except ImportError: 82 | pass 83 | else: 84 | INSTALLED_APPS.append('debug_toolbar') 85 | INTERNAL_IPS = ['127.0.0.1'] 86 | MIDDLEWARE_CLASSES.insert( 87 | MIDDLEWARE_CLASSES.index('django.middleware.common.CommonMiddleware') + 1, 88 | 'debug_toolbar.middleware.DebugToolbarMiddleware') 89 | 90 | # Log errors to Sentry instead of email, if available. 91 | if 'sentry_dsn' in SECRETS and not DEBUG: 92 | INSTALLED_APPS.append('raven.contrib.django') 93 | SENTRY_DSN = SECRETS['sentry_dsn'] 94 | LOGGING["loggers"]["django.request"]["handlers"].remove("mail_admins") 95 | -------------------------------------------------------------------------------- /aggregator/tests.py: -------------------------------------------------------------------------------- 1 | # email test 2 | # https://docs.djangoproject.com/en/dev/topics/testing/#email-services 3 | from __future__ import absolute_import 4 | 5 | import datetime 6 | from django.conf import settings 7 | from django.contrib.auth.models import Group, User 8 | from django.core import mail 9 | from django.core.urlresolvers import reverse 10 | from django.test import TestCase 11 | from django.test.client import Client 12 | 13 | from docs.models import DocumentRelease 14 | 15 | from .management.commands import send_pending_approval_email 16 | from . import models 17 | 18 | class AggregatorTests(TestCase): 19 | 20 | def setUp(self): 21 | # document release necessary to fetch main page 22 | DocumentRelease(version="1.4", scm="svn", scm_url="/path/to/svn", is_default=True).save() 23 | 24 | # Set up users who will get emailed 25 | g = Group.objects.create(name=settings.FEED_APPROVERS_GROUP_NAME) 26 | self.user = User.objects.create(username="Mr. Potato", email="mr@potato.com") 27 | self.user.groups.add(g) 28 | 29 | 30 | self.feed_type = models.FeedType(name="Test Feed Type", slug="test-feed-type", can_self_add=True) 31 | self.feed_type.save() 32 | 33 | self.approved_feed = models.Feed(title="Approved", feed_url="foo.com/rss/", public_url="foo.com/", 34 | approval_status=models.APPROVED_FEED, feed_type=self.feed_type) 35 | self.denied_feed = models.Feed(title="Denied", feed_url="bar.com/rss/", public_url="bar.com/", 36 | approval_status=models.DENIED_FEED, feed_type=self.feed_type) 37 | self.pending_feed = models.Feed(title="Pending", feed_url="baz.com/rss/", public_url="baz.com/", 38 | approval_status=models.PENDING_FEED, feed_type=self.feed_type) 39 | 40 | for feed in [self.approved_feed, self.denied_feed, self.pending_feed]: 41 | feed.save() 42 | feed_item = models.FeedItem(feed=feed, title="%s Item" % feed.title, link=feed.public_url, 43 | date_modified=datetime.datetime.now(), guid=feed.title) 44 | feed_item.save() 45 | 46 | self.client = Client() 47 | 48 | def test_feed_list_only_approved_and_active(self): 49 | response = self.client.get(reverse('community-feed-list', kwargs={'feed_type_slug': self.feed_type.slug})); 50 | for item in response.context['object_list']: 51 | self.assertEqual(models.APPROVED_FEED, item.feed.approval_status) 52 | 53 | def test_management_command_sends_no_email_with_no_pending_feeds(self): 54 | self.pending_feed.delete() 55 | send_pending_approval_email.Command().handle_noargs() 56 | self.assertEqual(0, len(mail.outbox)) 57 | 58 | def test_management_command_sends_email_with_pending_feeds(self): 59 | send_pending_approval_email.Command().handle_noargs() 60 | 61 | self.assertEqual(1, len(mail.outbox)) 62 | self.assertEqual(mail.outbox[0].to, [self.user.email]) 63 | -------------------------------------------------------------------------------- /static/css/pygments.css: -------------------------------------------------------------------------------- 1 | .c { color: #999988; font-style: italic } /* Comment */ 2 | .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 3 | .k { font-weight: bold } /* Keyword */ 4 | .o { font-weight: bold } /* Operator */ 5 | .cm { color: #999988; font-style: italic } /* Comment.Multiline */ 6 | .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ 7 | .c1 { color: #999988; font-style: italic } /* Comment.Single */ 8 | .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ 9 | .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ 10 | .ge { font-style: italic } /* Generic.Emph */ 11 | .gr { color: #aa0000 } /* Generic.Error */ 12 | .gh { color: #999999 } /* Generic.Heading */ 13 | .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ 14 | .go { color: #888888 } /* Generic.Output */ 15 | .gp { color: #555555 } /* Generic.Prompt */ 16 | .gs { font-weight: bold } /* Generic.Strong */ 17 | .gu { color: #aaaaaa } /* Generic.Subheading */ 18 | .gt { color: #aa0000 } /* Generic.Traceback */ 19 | .kc { font-weight: bold } /* Keyword.Constant */ 20 | .kd { font-weight: bold } /* Keyword.Declaration */ 21 | .kp { font-weight: bold } /* Keyword.Pseudo */ 22 | .kr { font-weight: bold } /* Keyword.Reserved */ 23 | .kt { color: #445588; font-weight: bold } /* Keyword.Type */ 24 | .m { color: #009999 } /* Literal.Number */ 25 | .s { color: #bb8844 } /* Literal.String */ 26 | .na { color: #008080 } /* Name.Attribute */ 27 | .nb { color: #999999 } /* Name.Builtin */ 28 | .nc { color: #445588; font-weight: bold } /* Name.Class */ 29 | .no { color: #008080 } /* Name.Constant */ 30 | .ni { color: #800080 } /* Name.Entity */ 31 | .ne { color: #990000; font-weight: bold } /* Name.Exception */ 32 | .nf { color: #990000; font-weight: bold } /* Name.Function */ 33 | .nn { color: #555555 } /* Name.Namespace */ 34 | .nt { color: #000080 } /* Name.Tag */ 35 | .nv { color: #008080 } /* Name.Variable */ 36 | .ow { font-weight: bold } /* Operator.Word */ 37 | .w { color: #bbbbbb } /* Text.Whitespace */ 38 | .mf { color: #009999 } /* Literal.Number.Float */ 39 | .mh { color: #009999 } /* Literal.Number.Hex */ 40 | .mi { color: #009999 } /* Literal.Number.Integer */ 41 | .mo { color: #009999 } /* Literal.Number.Oct */ 42 | .sb { color: #bb8844 } /* Literal.String.Backtick */ 43 | .sc { color: #bb8844 } /* Literal.String.Char */ 44 | .sd { color: #bb8844 } /* Literal.String.Doc */ 45 | .s2 { color: #bb8844 } /* Literal.String.Double */ 46 | .se { color: #bb8844 } /* Literal.String.Escape */ 47 | .sh { color: #bb8844 } /* Literal.String.Heredoc */ 48 | .si { color: #bb8844 } /* Literal.String.Interpol */ 49 | .sx { color: #bb8844 } /* Literal.String.Other */ 50 | .sr { color: #808000 } /* Literal.String.Regex */ 51 | .s1 { color: #bb8844 } /* Literal.String.Single */ 52 | .ss { color: #bb8844 } /* Literal.String.Symbol */ 53 | .bp { color: #999999 } /* Name.Builtin.Pseudo */ 54 | .vc { color: #008080 } /* Name.Variable.Class */ 55 | .vg { color: #008080 } /* Name.Variable.Global */ 56 | .vi { color: #008080 } /* Name.Variable.Instance */ 57 | .il { color: #009999 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /blog/models.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from docutils.core import publish_parts 3 | 4 | from django.conf import settings 5 | from django.db import models 6 | from django.utils.encoding import smart_str 7 | from django.utils.translation import ugettext_lazy as _ 8 | 9 | 10 | BLOG_DOCUTILS_SETTINGS = getattr(settings, 'BLOG_DOCUTILS_SETTINGS', { 11 | 'doctitle_xform': False, 12 | 'initial_header_level': 4, 13 | 'id_prefix': 's-', 14 | }) 15 | 16 | 17 | class EntryManager(models.Manager): 18 | 19 | def published(self): 20 | return self.active().filter(pub_date__lte=datetime.datetime.now()) 21 | 22 | def active(self): 23 | return super(EntryManager, self).get_query_set().filter(is_active=True) 24 | 25 | CONTENT_FORMAT_CHOICES = ( 26 | (u'reST', u'reStructuredText'), 27 | (u'html', u'Raw HTML'), 28 | ) 29 | 30 | class Entry(models.Model): 31 | headline = models.CharField(max_length=200) 32 | slug = models.SlugField(unique_for_date='pub_date') 33 | is_active = models.BooleanField(help_text=_("Tick to make this entry live (see also the publication date). Note that administrators (like yourself) are allowed to preview inactive entries whereas the general public aren't."), default=False) 34 | pub_date = models.DateTimeField(verbose_name=_("Publication date"), help_text=_("For an entry to be published, it must be active and its publication date must be in the past.")) 35 | content_format = models.CharField(choices=CONTENT_FORMAT_CHOICES, max_length=50) 36 | summary = models.TextField() 37 | summary_html = models.TextField() 38 | body = models.TextField() 39 | body_html = models.TextField() 40 | author = models.CharField(max_length=100) 41 | 42 | objects = EntryManager() 43 | 44 | class Meta: 45 | db_table = 'blog_entries' 46 | verbose_name_plural = 'entries' 47 | ordering = ('-pub_date',) 48 | get_latest_by = 'pub_date' 49 | 50 | def __unicode__(self): 51 | return self.headline 52 | 53 | def get_absolute_url(self): 54 | return "/weblog/%s/%s/" % (self.pub_date.strftime("%Y/%b/%d").lower(), self.slug) 55 | 56 | def is_published(self): 57 | """ 58 | Return True if the entry is publicly accessible. 59 | """ 60 | return self.is_active and self.pub_date <= datetime.datetime.now() 61 | is_published.boolean = True 62 | 63 | def save(self, *args, **kwargs): 64 | if self.content_format == u'html': 65 | self.summary_html = self.summary 66 | self.body_html = self.body 67 | elif self.content_format == u'reST': 68 | self.summary_html = publish_parts(source=smart_str(self.summary), 69 | writer_name="html", 70 | settings_overrides=BLOG_DOCUTILS_SETTINGS)['fragment'] 71 | self.body_html = publish_parts(source=smart_str(self.body), 72 | writer_name="html", 73 | settings_overrides=BLOG_DOCUTILS_SETTINGS)['fragment'] 74 | super(Entry, self).save(*args, **kwargs) 75 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 3 | 4 | 5 | 6 | 7 | {% block title %}The Web framework for perfectionists with deadlines{% endblock %} | Django 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block basecss %} 15 | 16 | {% endblock basecss %} 17 | 18 | {% block extrahead %}{% endblock %} 19 | 20 | 21 |
22 | 33 | 34 |
{% block billboard %}{% endblock %}
35 |
36 | {% block columnwrap %} 37 |
38 | {% block content %}{% endblock %} 39 |
40 | 41 | {% endblock %} 42 |
43 | 44 | 54 | 55 |
56 | 57 | {% block extrabody %}{% endblock extrabody %} 58 | 59 | 60 | -------------------------------------------------------------------------------- /django_www/urls.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.conf.urls import patterns, include, url 4 | from django.contrib import admin 5 | from django.contrib.flatpages.views import flatpage 6 | from django.contrib.sitemaps import FlatPageSitemap 7 | from django.contrib.sitemaps import views as sitemap_views 8 | from django.shortcuts import render 9 | from django.views.decorators.cache import cache_page 10 | from django.views.decorators.csrf import csrf_exempt, requires_csrf_token 11 | from django.views.generic import RedirectView, TemplateView 12 | 13 | from accounts import views as account_views 14 | from aggregator.feeds import CommunityAggregatorFeed, CommunityAggregatorFirehoseFeed 15 | from blog.feeds import WeblogEntryFeed 16 | from blog.sitemaps import WeblogSitemap 17 | 18 | admin.autodiscover() 19 | 20 | sitemaps = { 21 | 'weblog': WeblogSitemap, 22 | 'flatpages': FlatPageSitemap, 23 | } 24 | 25 | urlpatterns = patterns('', 26 | url(r'^$', TemplateView.as_view(template_name='homepage.html'), name="homepage"), 27 | url(r'^accounts/', include('accounts.urls')), 28 | url(r'^admin/', include(admin.site.urls)), 29 | url(r'^community/', include('aggregator.urls')), 30 | url(r'^conduct/$', TemplateView.as_view(template_name='conduct/index.html'), name='code_of_conduct'), 31 | url(r'^conduct/faq/$', TemplateView.as_view(template_name='conduct/faq.html'), name='conduct_faq'), 32 | url(r'^conduct/reporting/$', TemplateView.as_view(template_name='conduct/reporting.html'), name='conduct_reporting'), 33 | url(r'^conduct/enforcement-manual/$', TemplateView.as_view(template_name='conduct/enforcement.html'), name='conduct_enforcement'), 34 | url(r'^conduct/changes/$', TemplateView.as_view(template_name='conduct/changes.html'), name='conduct_enforcement'), 35 | url(r'^contact/', include('contact.urls')), 36 | url(r'^r/', include('django.conf.urls.shortcut')), 37 | 38 | # There's no school like the old school. 39 | url(r'^~(?P[\w-]+)/$', account_views.user_profile, name='user_profile'), 40 | 41 | # Feeds 42 | url(r'^rss/weblog/$', WeblogEntryFeed(), name='weblog-feed'), 43 | url(r'^rss/community/$', RedirectView.as_view(url='/rss/community/blogs/')), 44 | url(r'^rss/community/firehose/$', CommunityAggregatorFirehoseFeed(), name='aggregator-firehose-feed'), 45 | url(r'^rss/community/(?P[\w-]+)/$', CommunityAggregatorFeed(), name='aggregator-feed'), 46 | 47 | # PayPal insists on POSTing to the "thank you" page which means we can't 48 | # just use a flatpage for it. 49 | url(r'^foundation/donate/thanks/$', csrf_exempt(lambda req: render(req, 'donate_thanks.html'))), 50 | 51 | # django-push 52 | url(r'^subscriber/', include('django_push.subscriber.urls')), 53 | 54 | # Trac schtuff 55 | url(r'^trac/', include('tracdb.urls')), 56 | 57 | 58 | url(r'^sitemap\.xml$', cache_page(60 * 60 * 6)(sitemap_views.sitemap), {'sitemaps': sitemaps}), 59 | url(r'^weblog/', include('blog.urls')), 60 | url(r'^download/', include('releases.urls')), 61 | url(r'^svntogit/', include('svntogit.urls')), 62 | url(r'', include('legacy.urls')), 63 | ) 64 | 65 | @requires_csrf_token 66 | def handler500(request): 67 | return render(request, '500.html') 68 | -------------------------------------------------------------------------------- /releases/migrations/0003_auto__add_fields_release_tuple.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | # Adding field 'Release.major' 12 | db.add_column(u'releases_release', 'major', 13 | self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0), 14 | keep_default=False) 15 | 16 | # Adding field 'Release.minor' 17 | db.add_column(u'releases_release', 'minor', 18 | self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0), 19 | keep_default=False) 20 | 21 | # Adding field 'Release.micro' 22 | db.add_column(u'releases_release', 'micro', 23 | self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0), 24 | keep_default=False) 25 | 26 | # Adding field 'Release.status' 27 | db.add_column(u'releases_release', 'status', 28 | self.gf('django.db.models.fields.CharField')(default='', max_length=1), 29 | keep_default=False) 30 | 31 | # Adding field 'Release.iteration' 32 | db.add_column(u'releases_release', 'iteration', 33 | self.gf('django.db.models.fields.PositiveSmallIntegerField')(default=0), 34 | keep_default=False) 35 | 36 | 37 | # Changing field 'Release.date' 38 | db.alter_column(u'releases_release', 'date', self.gf('django.db.models.fields.DateField')()) 39 | 40 | def backwards(self, orm): 41 | # Deleting field 'Release.major' 42 | db.delete_column(u'releases_release', 'major') 43 | 44 | # Deleting field 'Release.minor' 45 | db.delete_column(u'releases_release', 'minor') 46 | 47 | # Deleting field 'Release.micro' 48 | db.delete_column(u'releases_release', 'micro') 49 | 50 | # Deleting field 'Release.status' 51 | db.delete_column(u'releases_release', 'status') 52 | 53 | # Deleting field 'Release.iteration' 54 | db.delete_column(u'releases_release', 'iteration') 55 | 56 | 57 | # Changing field 'Release.date' 58 | db.alter_column(u'releases_release', 'date', self.gf('django.db.models.fields.DateField')(auto_now_add=True)) 59 | 60 | models = { 61 | u'releases.release': { 62 | 'Meta': {'object_name': 'Release'}, 63 | 'date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}), 64 | 'iteration': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 65 | 'major': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 66 | 'micro': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 67 | 'minor': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), 68 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '1'}), 69 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '16', 'primary_key': 'True'}) 70 | } 71 | } 72 | 73 | complete_apps = ['releases'] 74 | -------------------------------------------------------------------------------- /docs/fixtures/doc_test_fixtures.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pk": 1, 4 | "model": "docs.documentrelease", 5 | "fields": { 6 | "lang": "en", 7 | "scm": "git", 8 | "scm_url": "git://github.com/django/django.git", 9 | "is_default": false, 10 | "version": "dev", 11 | "docs_subdir": "docs" 12 | } 13 | }, 14 | { 15 | "pk": 2, 16 | "model": "docs.documentrelease", 17 | "fields": { 18 | "lang": "en", 19 | "scm": "git", 20 | "scm_url": "git://github.com/django/django.git@stable/1.0.x", 21 | "is_default": false, 22 | "version": "1.0", 23 | "docs_subdir": "docs" 24 | } 25 | }, 26 | { 27 | "pk": 3, 28 | "model": "docs.documentrelease", 29 | "fields": { 30 | "lang": "en", 31 | "scm": "git", 32 | "scm_url": "git://github.com/django/django.git@stable/1.1.x", 33 | "is_default": false, 34 | "version": "1.1", 35 | "docs_subdir": "docs" 36 | } 37 | }, 38 | { 39 | "pk": 4, 40 | "model": "docs.documentrelease", 41 | "fields": { 42 | "lang": "en", 43 | "scm": "git", 44 | "scm_url": "git://github.com/django/django.git@stable/1.2.x", 45 | "is_default": false, 46 | "version": "1.2", 47 | "docs_subdir": "docs" 48 | } 49 | }, 50 | { 51 | "pk": 5, 52 | "model": "docs.documentrelease", 53 | "fields": { 54 | "lang": "en", 55 | "scm": "git", 56 | "scm_url": "git://github.com/django/django.git@stable/1.3.x", 57 | "is_default": false, 58 | "version": "1.3", 59 | "docs_subdir": "docs" 60 | } 61 | }, 62 | { 63 | "pk": 6, 64 | "model": "docs.documentrelease", 65 | "fields": { 66 | "lang": "en", 67 | "scm": "git", 68 | "scm_url": "git://github.com/django/django.git@stable/1.4.x", 69 | "is_default": false, 70 | "version": "1.4", 71 | "docs_subdir": "docs" 72 | } 73 | }, 74 | { 75 | "pk": 7, 76 | "model": "docs.documentrelease", 77 | "fields": { 78 | "lang": "en", 79 | "scm": "git", 80 | "scm_url": "git://github.com/django/django.git@stable/1.5.x", 81 | "is_default": false, 82 | "version": "1.5", 83 | "docs_subdir": "docs" 84 | } 85 | }, 86 | { 87 | "pk": 8, 88 | "model": "docs.documentrelease", 89 | "fields": { 90 | "lang": "fr", 91 | "scm": "git", 92 | "scm_url": "git://github.com/django/django.git@stable/1.5.x", 93 | "is_default": false, 94 | "version": "1.5", 95 | "docs_subdir": "docs" 96 | } 97 | }, 98 | { 99 | "pk": 9, 100 | "model": "docs.documentrelease", 101 | "fields": { 102 | "lang": "en", 103 | "scm": "git", 104 | "scm_url": "git://github.com/django/django.git@stable/1.6.x", 105 | "is_default": true, 106 | "version": "1.6", 107 | "docs_subdir": "docs" 108 | } 109 | }, 110 | { 111 | "pk": 10, 112 | "model": "docs.documentrelease", 113 | "fields": { 114 | "lang": "fr", 115 | "scm": "git", 116 | "scm_url": "git://github.com/django/django.git@stable/1.6.x", 117 | "is_default": false, 118 | "version": "1.6", 119 | "docs_subdir": "docs" 120 | } 121 | } 122 | ] 123 | -------------------------------------------------------------------------------- /static/img/logos/django-logo-positive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | ]> 7 | 9 | 10 | 11 | 14 | 17 | 22 | 25 | 32 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/fixtures/doc_releases.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pk": 1, 4 | "model": "docs.documentrelease", 5 | "fields": { 6 | "lang": "en", 7 | "scm": "git", 8 | "scm_url": "git://github.com/django/django.git", 9 | "is_default": false, 10 | "version": "dev", 11 | "docs_subdir": "docs" 12 | } 13 | }, 14 | { 15 | "pk": 2, 16 | "model": "docs.documentrelease", 17 | "fields": { 18 | "lang": "en", 19 | "scm": "git", 20 | "scm_url": "git://github.com/django/django.git@stable/1.0.x", 21 | "is_default": false, 22 | "version": "1.0", 23 | "docs_subdir": "docs" 24 | } 25 | }, 26 | { 27 | "pk": 3, 28 | "model": "docs.documentrelease", 29 | "fields": { 30 | "lang": "en", 31 | "scm": "git", 32 | "scm_url": "git://github.com/django/django.git@stable/1.1.x", 33 | "is_default": false, 34 | "version": "1.1", 35 | "docs_subdir": "docs" 36 | } 37 | }, 38 | { 39 | "pk": 4, 40 | "model": "docs.documentrelease", 41 | "fields": { 42 | "lang": "en", 43 | "scm": "git", 44 | "scm_url": "git://github.com/django/django.git@stable/1.2.x", 45 | "is_default": false, 46 | "version": "1.2", 47 | "docs_subdir": "docs" 48 | } 49 | }, 50 | { 51 | "pk": 5, 52 | "model": "docs.documentrelease", 53 | "fields": { 54 | "lang": "en", 55 | "scm": "git", 56 | "scm_url": "git://github.com/django/django.git@stable/1.3.x", 57 | "is_default": false, 58 | "version": "1.3", 59 | "docs_subdir": "docs" 60 | } 61 | }, 62 | { 63 | "pk": 6, 64 | "model": "docs.documentrelease", 65 | "fields": { 66 | "lang": "en", 67 | "scm": "git", 68 | "scm_url": "git://github.com/django/django.git@stable/1.4.x", 69 | "is_default": false, 70 | "version": "1.4", 71 | "docs_subdir": "docs" 72 | } 73 | }, 74 | { 75 | "pk": 7, 76 | "model": "docs.documentrelease", 77 | "fields": { 78 | "lang": "en", 79 | "scm": "git", 80 | "scm_url": "git://github.com/django/django.git@stable/1.5.x", 81 | "is_default": false, 82 | "version": "1.5", 83 | "docs_subdir": "docs" 84 | } 85 | }, 86 | { 87 | "pk": 8, 88 | "model": "docs.documentrelease", 89 | "fields": { 90 | "lang": "fr", 91 | "scm": "git", 92 | "scm_url": "git://github.com/django/django.git@stable/1.5.x", 93 | "is_default": false, 94 | "version": "1.5", 95 | "docs_subdir": "docs" 96 | } 97 | }, 98 | { 99 | "pk": 9, 100 | "model": "docs.documentrelease", 101 | "fields": { 102 | "lang": "en", 103 | "scm": "git", 104 | "scm_url": "git://github.com/django/django.git@stable/1.6.x", 105 | "is_default": true, 106 | "version": "1.6", 107 | "docs_subdir": "docs" 108 | } 109 | }, 110 | { 111 | "pk": 10, 112 | "model": "docs.documentrelease", 113 | "fields": { 114 | "lang": "fr", 115 | "scm": "git", 116 | "scm_url": "git://github.com/django/django.git@stable/1.6.x", 117 | "is_default": false, 118 | "version": "1.6", 119 | "docs_subdir": "docs" 120 | } 121 | } 122 | ] 123 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import hashlib 4 | import json 5 | from django.shortcuts import redirect, render, get_object_or_404 6 | from django.contrib.auth.decorators import login_required 7 | from django.contrib.auth.models import User 8 | from django.conf import settings 9 | from django.core import cache 10 | from django.http import HttpResponse 11 | 12 | from cla.models import find_agreements 13 | from tracdb import stats as trac_stats 14 | 15 | from .forms import ProfileForm 16 | from .models import Profile 17 | 18 | def user_profile(request, username): 19 | u = get_object_or_404(User, username=username) 20 | ctx = { 21 | 'user_obj': u, 22 | 'email_hash': hashlib.md5(u.email).hexdigest(), 23 | 'user_can_commit': u.has_perm('auth.commit'), 24 | 'clas': find_agreements(u), 25 | 'stats': get_user_stats(u), 26 | } 27 | return render(request, "accounts/user_profile.html", ctx) 28 | 29 | @login_required 30 | def edit_profile(request): 31 | profile, created = Profile.objects.get_or_create(user=request.user) 32 | form = ProfileForm(request.POST or None, instance=profile) 33 | if form.is_valid(): 34 | form.save() 35 | return redirect('user_profile', request.user.username) 36 | return render(request, "accounts/edit_profile.html", {'form': form}) 37 | 38 | def json_user_info(request): 39 | """ 40 | Return info about some users as a JSON object. 41 | 42 | Part of a set of hacks that feed more info into Trac. This takes 43 | a list of users as GET['user'] and returns a JSON object:: 44 | 45 | { 46 | {USERNAME: {"core": false, "cla": true}}, 47 | {USERNAME: {"core": false, "cla": true}}, 48 | ... 49 | } 50 | 51 | De-duplication on GET['user'] is performed since I don't want to have to 52 | think about how best to do it in JavaScript :) 53 | """ 54 | 55 | userinfo = dict([ 56 | (name, get_user_info(name)) 57 | for name in set(request.GET.getlist('user'))]) 58 | return JSONResponse(userinfo) 59 | 60 | def get_user_info(username): 61 | c = cache.get_cache('default') 62 | username = username.encode('ascii', 'ignore') 63 | key = 'trac_user_info:%s' % hashlib.md5(username).hexdigest() 64 | info = c.get(key) 65 | if info is None: 66 | try: 67 | u = User.objects.get(username=username) 68 | except User.DoesNotExist: 69 | info = {"core": False, "cla": False} 70 | else: 71 | info = { 72 | "core": u.has_perm('auth.commit'), 73 | "cla": bool(find_agreements(u)) 74 | } 75 | c.set(key, info, 60*60) 76 | return info 77 | 78 | def get_user_stats(user): 79 | c = cache.get_cache('default') 80 | key = 'user_vital_status:%s' % hashlib.md5(user.username).hexdigest() 81 | info = c.get(key) 82 | if info is None: 83 | info = trac_stats.get_user_stats(user.username) 84 | # Hide any stat with a value = 0 so that we don't accidentally insult 85 | # non-contributors. 86 | for k, v in info.items(): 87 | if v == 0: 88 | info.pop(k) 89 | c.set(key, info, 60*60) 90 | return info 91 | 92 | class JSONResponse(HttpResponse): 93 | def __init__(self, obj): 94 | super(JSONResponse, self).__init__( 95 | json.dumps(obj, indent=(2 if settings.DEBUG else None)), 96 | content_type='application/json', 97 | ) 98 | -------------------------------------------------------------------------------- /static/img/logos/django-logo-negative.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | ]> 7 | 9 | 11 | 12 | 13 | 17 | 20 | 25 | 28 | 35 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /aggregator/views.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from django.shortcuts import render, get_object_or_404, redirect 4 | from django.contrib import messages 5 | from django.contrib.auth.decorators import login_required 6 | from django.views.generic.list import ListView 7 | 8 | from .models import FeedItem, Feed, FeedType, APPROVED_FEED 9 | from .forms import FeedModelForm 10 | 11 | def index(request): 12 | """ 13 | Displays the latest feeds of each type. 14 | """ 15 | feeds = [] 16 | for ft in FeedType.objects.all(): 17 | feeds.append((ft, ft.items()[0:5])) 18 | ctx = {'feedtype_list': feeds} 19 | return render(request, 'aggregator/index.html', ctx) 20 | 21 | class FeedListView(ListView): 22 | """ 23 | Shows the latest feeds for the given type. 24 | """ 25 | 26 | paginate_by = 25 27 | 28 | def get_queryset(self): 29 | self.feed_type = get_object_or_404(FeedType, slug=self.kwargs.pop('feed_type_slug')) 30 | return FeedItem.objects.filter(feed__feed_type=self.feed_type, feed__approval_status=APPROVED_FEED) 31 | 32 | def get_context_data(self, **kwargs): 33 | context = super(FeedListView, self).get_context_data(**kwargs) 34 | context['feed_type'] = self.feed_type 35 | return context 36 | 37 | @login_required 38 | def my_feeds(request): 39 | """ 40 | Lets the user see, edit, and delete all of their owned feeds. 41 | """ 42 | feed_types = FeedType.objects.all() 43 | if not request.user.is_superuser: 44 | feed_types = feed_types.filter(can_self_add=True) 45 | 46 | ctx = { 47 | 'feeds': Feed.objects.filter(owner=request.user), 48 | 'feed_types': feed_types 49 | } 50 | return render(request, 'aggregator/my-feeds.html', ctx) 51 | 52 | @login_required 53 | def add_feed(request, feed_type_slug): 54 | """ 55 | Lets users add new feeds to the aggregator. 56 | 57 | Users only get to add new feeds of types indicated as "can self add." 58 | """ 59 | ft = get_object_or_404(FeedType, slug=feed_type_slug, can_self_add=True) 60 | if not ft.can_self_add and not request.user.is_superuser: 61 | return render(request, 'aggregator/denied.html') 62 | 63 | instance = Feed(feed_type=ft, owner=request.user) 64 | f = FeedModelForm(request.POST or None, instance=instance) 65 | if f.is_valid(): 66 | f.save() 67 | messages.add_message( 68 | request, messages.INFO, 'Your feed has entered moderation. Please allow up to 1 week for processing.') 69 | return redirect('community-index') 70 | 71 | ctx = {'form': f, 'feed_type': ft, 'adding': True} 72 | return render(request, 'aggregator/edit-feed.html', ctx) 73 | 74 | @login_required 75 | def edit_feed(request, feed_id): 76 | """ 77 | Lets a user edit a feed they've previously added. 78 | 79 | Only feeds the user "owns" can be edited. 80 | """ 81 | feed = get_object_or_404(Feed, pk=feed_id, owner=request.user) 82 | f = FeedModelForm(request.POST or None, instance=feed) 83 | if f.is_valid(): 84 | f.save() 85 | return redirect('community-my-feeds') 86 | 87 | ctx = {'form': f, 'feed': feed, 'adding': False} 88 | return render(request, 'aggregator/edit-feed.html', ctx) 89 | 90 | @login_required 91 | def delete_feed(request, feed_id): 92 | """ 93 | Lets a user delete a feed they've previously added. 94 | 95 | Only feeds the user "owns" can be deleted. 96 | """ 97 | feed = get_object_or_404(Feed, pk=feed_id, owner=request.user) 98 | if request.method == 'POST': 99 | feed.delete() 100 | return redirect('community-my-feeds') 101 | return render(request, 'aggregator/delete-confirm.html', {'feed': feed}) 102 | -------------------------------------------------------------------------------- /fabfile.py: -------------------------------------------------------------------------------- 1 | import unipath 2 | from fabric.api import * 3 | from fabric.contrib import files 4 | 5 | # Fab settings 6 | env.hosts = ['ve.djangoproject.com'] 7 | 8 | # Deployment environment paths and settings and such. 9 | env.deploy_base = unipath.Path('/home/www/djangoproject.com') 10 | env.virtualenv = env.deploy_base 11 | env.code_dir = env.deploy_base.child('src') 12 | env.git_url = 'git://github.com/django/djangoproject.com.git' 13 | env.default_deploy_ref = 'origin/master' 14 | 15 | def full_deploy(): 16 | """ 17 | Full deploy: new code, update dependencies, migrate, and restart services. 18 | """ 19 | deploy_code() 20 | update_dependencies() 21 | migrate() 22 | collectstatic() 23 | apache("restart") 24 | memcached("restart") 25 | 26 | def deploy(): 27 | """ 28 | Quick deploy: new code and an in-place reload. 29 | """ 30 | deploy_code() 31 | collectstatic() 32 | apache("reload") 33 | 34 | def apache(cmd): 35 | """ 36 | Manage the apache service. For example, `fab apache:restart`. 37 | """ 38 | sudo('invoke-rc.d apache2 %s' % cmd) 39 | 40 | def memcached(cmd): 41 | """ 42 | Manage the memcached service. For example, `fab apache:restart`. 43 | """ 44 | sudo('invoke-rc.d memcached %s' % cmd) 45 | 46 | def deploy_code(ref=None): 47 | """ 48 | Update code on the servers from Git. 49 | """ 50 | ref = ref or env.default_deploy_ref 51 | puts("Deploying %s" % ref) 52 | if not files.exists(env.code_dir): 53 | sudo('git clone %s %s' % (env.git_url, env.code_dir)) 54 | with cd(env.code_dir): 55 | sudo('git fetch && git reset --hard %s' % ref) 56 | with cd(env.code_dir.child('docs')): 57 | managepy('compilemessages', site='docs') 58 | 59 | def update_dependencies(): 60 | """ 61 | Update dependencies in the virtualenv. 62 | """ 63 | pip = env.virtualenv.child('bin', 'pip') 64 | reqs = env.code_dir.child('deploy-requirements.txt') 65 | sudo('%s -q install -U pip' % pip) 66 | sudo('%s -q install -r %s' % (pip, reqs)) 67 | 68 | def collectstatic(): 69 | """ 70 | Run collectstatic. 71 | """ 72 | managepy('collectstatic --noinput') 73 | managepy('collectstatic --noinput', site='docs') 74 | 75 | def migrate(): 76 | """ 77 | Run migrate/syncdb. 78 | """ 79 | managepy('syncdb') 80 | managepy('migrate') 81 | managepy('syncdb', site='docs') 82 | managepy('migrate', site='docs') 83 | 84 | def update_docs(): 85 | """ 86 | Force an update of the docs on the server. 87 | """ 88 | managepy('update_docs -v2', site='docs') 89 | 90 | def copy_dbs(): 91 | """ 92 | Copy the production DBs locally for testing. 93 | """ 94 | for db in ('djangoproject', 'code.djangoproject'): 95 | local('ssh %s pg_dump -U %s -c %s | psql %s' % (env.hosts[0], db, db, db)) 96 | 97 | def copy_docs(): 98 | """ 99 | Copy build docs locally for testing. 100 | """ 101 | local('rsync -av --delete --exclude=.svn %s:%s/ /tmp/djangodocs/' % 102 | (env.hosts[0], env.deploy_base.child('docbuilds'))) 103 | 104 | def managepy(cmd, site='www'): 105 | """ 106 | Helper: run a management command remotely. 107 | """ 108 | assert site in ('docs', 'www') 109 | django_admin = env.virtualenv.child('bin', 'django-admin.py') 110 | sudo('%s %s --settings=django_%s.settings' % (django_admin, cmd, site)) 111 | 112 | def southify(app): 113 | """ 114 | Southify an app remotely. 115 | 116 | This fakes the initial migration and then migrates forward. Use it the first 117 | time you do a deploy on app that's been newly southified. 118 | """ 119 | managepy('migrate %s 0001 --fake' % app) 120 | managepy('migrate %s' % app) 121 | -------------------------------------------------------------------------------- /docs/models.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.core.cache import cache 3 | from django.db import models 4 | 5 | 6 | class DocumentReleaseManager(models.Manager): 7 | 8 | def current(self, lang='en'): 9 | current = self.get(is_default=True) 10 | if lang != 'en': 11 | try: 12 | return self.get(lang=lang, version=current.version) 13 | except DocumentRelease.DoesNotExist: 14 | pass 15 | return current 16 | 17 | def current_version(self): 18 | current_version = cache.get(DocumentRelease.DEFAULT_CACHE_KEY) 19 | if not current_version: 20 | try: 21 | current_version = self.current().version 22 | except DocumentRelease.DoesNotExist: 23 | current_version = 'dev' 24 | cache.set( 25 | DocumentRelease.DEFAULT_CACHE_KEY, 26 | current_version, 27 | settings.CACHE_MIDDLEWARE_SECONDS, 28 | ) 29 | return current_version 30 | 31 | 32 | class DocumentRelease(models.Model): 33 | """ 34 | A "release" of documentation -- i.e. English for v1.2. 35 | """ 36 | DEFAULT_CACHE_KEY = "%s_docs_version" % settings.CACHE_MIDDLEWARE_KEY_PREFIX 37 | SVN = 'svn' 38 | GIT = 'git' 39 | SCM_CHOICES = ( 40 | (SVN, 'SVN'), 41 | (GIT, 'git'), 42 | ) 43 | 44 | lang = models.CharField(max_length=2, choices=settings.LANGUAGES, default='en') 45 | version = models.CharField(max_length=20) 46 | scm = models.CharField(max_length=10, choices=SCM_CHOICES) 47 | scm_url = models.CharField(max_length=200) 48 | docs_subdir = models.CharField(max_length=200, blank=True) 49 | is_default = models.BooleanField() 50 | 51 | objects = DocumentReleaseManager() 52 | 53 | class Meta: 54 | unique_together = ('lang', 'version') 55 | 56 | def __unicode__(self): 57 | return "%s/%s" % (self.lang, self.version) 58 | 59 | @models.permalink 60 | def get_absolute_url(self): 61 | return ('document-index', [], {'lang': self.lang, 'version': self.version}) 62 | 63 | def save(self, *args, **kwargs): 64 | # There can be only one. Default, that is. 65 | if self.is_default: 66 | DocumentRelease.objects.update(is_default=False) 67 | cache.set( 68 | self.DEFAULT_CACHE_KEY, 69 | self.version, 70 | settings.CACHE_MIDDLEWARE_SECONDS, 71 | ) 72 | super(DocumentRelease, self).save(*args, **kwargs) 73 | 74 | @property 75 | def human_version(self): 76 | """ 77 | Return a "human readable" version of the version. 78 | """ 79 | return "Development trunk" if self.is_dev else "Django %s" % self.version 80 | 81 | @property 82 | def is_dev(self): 83 | return self.version == 'dev' 84 | 85 | 86 | class Document(models.Model): 87 | """ 88 | An individual document. Used mainly as a hook point for Haystack. 89 | """ 90 | release = models.ForeignKey(DocumentRelease, related_name='documents') 91 | path = models.CharField(max_length=500) 92 | title = models.CharField(max_length=500) 93 | 94 | class Meta: 95 | unique_together = ('release', 'path') 96 | 97 | def __unicode__(self): 98 | return "/".join([self.release.lang, self.release.version, self.path]) 99 | 100 | @models.permalink 101 | def get_absolute_url(self): 102 | if self.path: 103 | kwargs = { 104 | 'lang': self.release.lang, 105 | 'version': self.release.version, 106 | 'url': self.path, 107 | } 108 | return ('document-detail', [], kwargs) 109 | else: 110 | kwargs = { 111 | 'lang': self.release.lang, 112 | 'version': self.release.version, 113 | } 114 | return ('document-index', [], kwargs) 115 | --------------------------------------------------------------------------------