Skip to content

Commit 94c3139

Browse files
wapcapletericholscher
authored andcommitted
Created a mechanism for user profiles. For now, this just allows users to have a personal homepage URL, along with a flag indicating their whitelisted status. Users can edit their own profiles, but cannot change their own whitelist status. There's an admin interface included so the site administrator can whitelist certain users.
At Eric H's suggestion, the model was added to the core app; there's a South migration to create the new table (./manage.py migrate core), and a new dependency (pip install django-profiles). User profiles can be viewed at /profiles, and your own profile can be created at /profiles/create, then edited at /profiles/edit. The detail of any user's profile can be viewed at /profiles/<username>. We may want to eventually tie this in with a list of that user's projects. There are currently no visible links to any of the profile stuff; it might be good to at least add a link from the dashboard to create your profile. It may also make sense to automatically create an empty profile for any new users that sign up. None of this stuff is addressed in this initial version.
1 parent 128390a commit 94c3139

13 files changed

+183
-1
lines changed

core/admin.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django.contrib import admin
2+
3+
from core.models import UserProfile
4+
5+
class UserProfileAdmin(admin.ModelAdmin):
6+
pass
7+
8+
admin.site.register(UserProfile, UserProfileAdmin)
9+

core/forms.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.db import models
2+
from django.forms import ModelForm
3+
from models import UserProfile
4+
5+
class UserProfileForm (ModelForm):
6+
class Meta:
7+
model = UserProfile
8+
# Don't allow users edit someone else's user page,
9+
# or to whitelist themselves
10+
exclude = ('user', 'whitelisted',)
11+

core/migrations/0001_initial.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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 'UserProfile'
12+
db.create_table('core_userprofile', (
13+
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14+
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], unique=True)),
15+
('whitelisted', self.gf('django.db.models.fields.BooleanField')(default=False)),
16+
('homepage', self.gf('django.db.models.fields.CharField')(max_length=100)),
17+
))
18+
db.send_create_signal('core', ['UserProfile'])
19+
20+
21+
def backwards(self, orm):
22+
23+
# Deleting model 'UserProfile'
24+
db.delete_table('core_userprofile')
25+
26+
27+
models = {
28+
'auth.group': {
29+
'Meta': {'object_name': 'Group'},
30+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
31+
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
32+
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
33+
},
34+
'auth.permission': {
35+
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
36+
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
37+
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
38+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
39+
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
40+
},
41+
'auth.user': {
42+
'Meta': {'object_name': 'User'},
43+
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
44+
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
45+
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
46+
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
47+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
48+
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
49+
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
50+
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
51+
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
52+
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
53+
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
54+
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
55+
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
56+
},
57+
'contenttypes.contenttype': {
58+
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
59+
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
60+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
61+
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
62+
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
63+
},
64+
'core.userprofile': {
65+
'Meta': {'object_name': 'UserProfile'},
66+
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
67+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
68+
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}),
69+
'whitelisted': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
70+
}
71+
}
72+
73+
complete_apps = ['core']

core/migrations/__init__.py

Whitespace-only changes.

core/models.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1-
#Grr
1+
from django.db import models
2+
from django.contrib.auth.models import User
3+
4+
class UserProfile (models.Model):
5+
"""Additional information about a User.
6+
"""
7+
user = models.ForeignKey(User, unique=True)
8+
whitelisted = models.BooleanField()
9+
homepage = models.CharField(max_length=100)
10+
11+
def get_absolute_url(self):
12+
return ('profiles_profile_detail', (), {'username': self.user.username})
13+
get_absolute_url = models.permalink(get_absolute_url)
14+
15+
def __unicode__(self):
16+
return "%s's profile" % self.user.username
17+

pip_requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ghettoq
88
importlib
99
django-extensions
1010
django-haystack
11+
django-profiles
1112
-e git+http://github.com/nathanborror/django-basic-apps.git#egg=basic
1213
-e hg+http://bitbucket.org/andrewgodwin/south/#egg=south
1314
-e git+http://github.com/alex/django-taggit.git#egg=taggit

settings/base.py

+4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
'django_extensions',
9191
'basic.flagging',
9292
'haystack',
93+
'profiles',
9394

9495
# our apps
9596
'projects',
@@ -109,3 +110,6 @@
109110
HAYSTACK_SEARCH_ENGINE = 'solr'
110111
#HAYSTACK_WHOOSH_PATH = os.path.join(SITE_ROOT, 'whooshindex.db')
111112
HAYSTACK_SOLR_URL = 'http://loki:8983/solr'
113+
114+
AUTH_PROFILE_MODULE = "core.UserProfile"
115+

templates/profiles/base_profile.html

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{% extends "base.html" %}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{% extends "profiles/base_profile.html" %}
2+
3+
{% block title %}Create your profile{% endblock %}
4+
5+
{% block content-header %}
6+
<h1>Create your profile</h1>
7+
{% endblock %}
8+
9+
{% block content %}
10+
<form method="POST" action=".">{% csrf_token %}
11+
{{ form }}
12+
<input type="submit" name="submit" value="Create it!" id="submit"/>
13+
</form>
14+
{% endblock %}
15+

templates/profiles/edit_profile.html

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{% extends "profiles/base_profile.html" %}
2+
3+
{% block title %}Edit your profile{% endblock %}
4+
5+
{% block content-header %}
6+
<h1>Edit your profile</h1>
7+
{% endblock %}
8+
9+
{% block content %}
10+
<form method="POST" action=".">{% csrf_token %}
11+
{{ form }}
12+
<input type="submit" name="submit" value="OK, save it!" id="submit"/>
13+
</form>
14+
{% endblock %}
15+
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{% extends "profiles/base_profile.html" %}
2+
3+
{% block title %}{{ user }}'s profile{% endblock %}
4+
5+
{% block content-header %}
6+
<h1>{{ user }}'s profile</h1>
7+
{% endblock %}
8+
9+
{% block content %}
10+
<h3>Homepage</h3>
11+
{% if profile.homepage %}
12+
<p><a href="{{ profile.homepage }}">{{ profile.homepage }}</a></p>
13+
{% else %}
14+
<p>Unknown</p>
15+
{% endif %}
16+
17+
<h3>Whitelisted?</h3>
18+
<p>{{ profile.whitelisted }}</p>
19+
{% endblock %}
20+

templates/profiles/profile_list.html

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{% extends "profiles/base_profile.html" %}
2+
3+
{% block title %}User profiles{% endblock %}
4+
5+
{% block content-header %}
6+
<h1>User profiles</h1>
7+
{% endblock %}
8+
9+
{% block content %}
10+
{% for profile in object_list %}
11+
<a href="{% url profiles_profile_detail profile.user %}">{{ profile }}</a>
12+
{% endfor %}
13+
{% endblock %}
14+

urls.py

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.contrib import admin
44
from django.conf import settings
5+
from core.forms import UserProfileForm
56
admin.autodiscover()
67

78
handler500 = 'core.views.server_error'
@@ -31,6 +32,8 @@
3132
'core.views.render_header',
3233
name='render_header'
3334
),
35+
url(r'^profiles/edit', 'profiles.views.edit_profile', {'form_class': UserProfileForm}),
36+
url(r'^profiles/', include('profiles.urls')),
3437
)
3538

3639
if settings.DEBUG:

0 commit comments

Comments
 (0)