diff --git a/relationships/fixtures/initial_data.json b/relationships/fixtures/initial_data.json index 30c0506..f312847 100644 --- a/relationships/fixtures/initial_data.json +++ b/relationships/fixtures/initial_data.json @@ -1,9 +1,9 @@ [ { - "pk": 1, - "model": "relationships.relationshipstatus", + "model": "relationships.relationshipstatus", "fields": { - "name": "Following", + "id": "RS_2c249083b333a261", + "name": "Following", "to_slug": "followers", "from_slug": "following", "symmetrical_slug": "friends", @@ -11,10 +11,10 @@ } }, { - "pk": 2, - "model": "relationships.relationshipstatus", + "model": "relationships.relationshipstatus", "fields": { - "name": "Blocking", + "id": "RS_718a303ac84ccb20", + "name": "Blocking", "to_slug": "blockers", "from_slug": "blocking", "symmetrical_slug": "!", diff --git a/relationships/migrations/0001_initial.py b/relationships/migrations/0001_initial.py index 515c651..68d564f 100644 --- a/relationships/migrations/0001_initial.py +++ b/relationships/migrations/0001_initial.py @@ -1,102 +1,113 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime from south.db import db -from relationships.models import * +from south.v2 import SchemaMigration +from django.db import models +from ..utils import (User, user_orm_label, user_model_label) -class Migration: - def forwards(self, orm): +class Migration(SchemaMigration): + def forwards(self, orm): # Adding model 'RelationshipStatus' - db.create_table('relationships_relationshipstatus', ( - ('id', orm['relationships.RelationshipStatus:id']), - ('name', orm['relationships.RelationshipStatus:name']), - ('verb', orm['relationships.RelationshipStatus:verb']), - ('from_slug', orm['relationships.RelationshipStatus:from_slug']), - ('to_slug', orm['relationships.RelationshipStatus:to_slug']), - ('symmetrical_slug', orm['relationships.RelationshipStatus:symmetrical_slug']), - ('login_required', orm['relationships.RelationshipStatus:login_required']), - ('private', orm['relationships.RelationshipStatus:private']), + db.create_table(u'relationships_relationshipstatus', ( + ('id', self.gf('relationships.models.SIDField')(default='RS_e2988c32b44df4d0', unique=True, max_length=20, primary_key=True, db_index=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=100)), + ('verb', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=100)), + ('from_slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=100)), + ('to_slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=100)), + ('symmetrical_slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=100)), + ('login_required', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('private', self.gf('django.db.models.fields.BooleanField')(default=False)), )) - db.send_create_signal('relationships', ['RelationshipStatus']) + db.send_create_signal(u'relationships', ['RelationshipStatus']) # Adding model 'Relationship' - db.create_table('relationships_relationship', ( - ('id', orm['relationships.Relationship:id']), - ('from_user', orm['relationships.Relationship:from_user']), - ('to_user', orm['relationships.Relationship:to_user']), - ('status', orm['relationships.Relationship:status']), - ('created', orm['relationships.Relationship:created']), + db.create_table(u'relationships_relationship', ( + ('id', self.gf('relationships.models.SIDField')(default='R_4d4e7df6f454c503', unique=True, max_length=20, primary_key=True, db_index=True)), + ('from_user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='from_users', to=orm[user_orm_label])), + ('to_user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='to_users', null=True, to=orm[user_orm_label])), + ('status', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['relationships.RelationshipStatus'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('weight', self.gf('django.db.models.fields.FloatField')(default=1.0, null=True, blank=True)), + ('site', self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='relationships', to=orm['sites.Site'])), + ('extra_data', self.gf('jsonfield.fields.JSONField')(default=None, null=True, blank=True)), )) - db.send_create_signal('relationships', ['Relationship']) + db.send_create_signal(u'relationships', ['Relationship']) - # Creating unique_together for [from_user, to_user, status] on Relationship. - db.create_unique('relationships_relationship', ['from_user_id', 'to_user_id', 'status_id']) + # Adding unique constraint on 'Relationship', fields ['from_user', 'to_user', 'status', 'site'] + db.create_unique(u'relationships_relationship', ['from_user_id', 'to_user_id', 'status_id', 'site_id']) - def backwards(self, orm): - # Deleting unique_together for [from_user, to_user, status] on Relationship. - db.delete_unique('relationships_relationship', ['from_user_id', 'to_user_id', 'status_id']) + def backwards(self, orm): + # Removing unique constraint on 'Relationship', fields ['from_user', 'to_user', 'status', 'site'] + db.delete_unique(u'relationships_relationship', ['from_user_id', 'to_user_id', 'status_id', 'site_id']) # Deleting model 'RelationshipStatus' - db.delete_table('relationships_relationshipstatus') + db.delete_table(u'relationships_relationshipstatus') # Deleting model 'Relationship' - db.delete_table('relationships_relationship') + db.delete_table(u'relationships_relationship') + models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'relationships': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'symmetrical': 'False'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, - 'relationships.relationship': { - 'Meta': {'unique_together': "(('from_user', 'to_user', 'status'),)"}, + # http://kevindias.com/writing/django-custom-user-models-south-and-reusable-apps/ + user_model_label: { + # We've accounted for changes to: + # the app name, table name, pk attribute name, pk column name. + # The only assumption left is that the pk is an AutoField (see below) + 'Meta': { 'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table }, + User._meta.pk.attname: ('django.db.models.fields.AutoField', [], {'primary_key': 'True', 'db_column': "'%s'" % User._meta.pk.column}) + }, + u'relationships.relationship': { + 'Meta': {'ordering': "('created',)", 'unique_together': "(('from_user', 'to_user', 'status', 'site'),)", 'object_name': 'Relationship'}, 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_users'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['relationships.RelationshipStatus']"}), - 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_users'", 'to': "orm['auth.User']"}) + 'extra_data': ('jsonfield.fields.JSONField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), + 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_users'", 'to': u"orm['{}']".format(user_orm_label)}), + 'id': ('relationships.models.SIDField', [], {'default': "'R_968e881c1c1ee895'", 'unique': 'True', 'max_length': '20', 'primary_key': 'True', 'db_index': 'True'}), + 'site': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'related_name': "'relationships'", 'to': u"orm['sites.Site']"}), + 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['relationships.RelationshipStatus']"}), + 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'to_users'", 'null': 'True', 'to': u"orm['{}']".format(user_orm_label)}), + 'weight': ('django.db.models.fields.FloatField', [], {'default': '1.0', 'null': 'True', 'blank': 'True'}) }, - 'relationships.relationshipstatus': { - 'from_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + u'relationships.relationshipstatus': { + 'Meta': {'ordering': "('name',)", 'object_name': 'RelationshipStatus'}, + 'from_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}), + 'id': ('relationships.models.SIDField', [], {'default': "'RS_7d17358149d10a4f'", 'unique': 'True', 'max_length': '20', 'primary_key': 'True', 'db_index': 'True'}), + 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'symmetrical_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), - 'to_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), - 'verb': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'symmetrical_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}), + 'to_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}), + 'verb': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'sites.site': { + 'Meta': {'ordering': "(u'domain',)", 'object_name': 'Site', 'db_table': "u'django_site'"}, + 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) } } - complete_apps = ['relationships'] + complete_apps = ['relationships'] \ No newline at end of file diff --git a/relationships/migrations/0002_add_site_fk.py b/relationships/migrations/0002_add_site_fk.py deleted file mode 100644 index 7a083b8..0000000 --- a/relationships/migrations/0002_add_site_fk.py +++ /dev/null @@ -1,80 +0,0 @@ -from south.db import db -from relationships.models import * - - -class Migration: - - def forwards(self, orm): - - # Adding field 'Relationship.site' - db.add_column('relationships_relationship', 'site', orm['relationships.relationship:site']) - - def backwards(self, orm): - - # Deleting field 'Relationship.site' - db.delete_column('relationships_relationship', 'site_id') - - models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'relationships': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'symmetrical': 'False'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'relationships.relationship': { - 'Meta': {'unique_together': "(('from_user', 'to_user', 'status'),)"}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_users'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['sites.Site']"}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['relationships.RelationshipStatus']"}), - 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_users'", 'to': "orm['auth.User']"}) - }, - 'relationships.relationshipstatus': { - 'from_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'symmetrical_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), - 'to_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}), - 'verb': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'sites.site': { - 'Meta': {'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['relationships'] diff --git a/relationships/migrations/0003_slugs_to_charfields.py b/relationships/migrations/0003_slugs_to_charfields.py deleted file mode 100644 index 241d3c8..0000000 --- a/relationships/migrations/0003_slugs_to_charfields.py +++ /dev/null @@ -1,116 +0,0 @@ -from south.db import db -from relationships.models import * - - -class Migration: - - def forwards(self, orm): - - # Deleting unique_together for [symmetrical_slug] on relationshipstatus. - db.delete_unique('relationships_relationshipstatus', ['symmetrical_slug']) - - # Deleting unique_together for [from_slug] on relationshipstatus. - db.delete_unique('relationships_relationshipstatus', ['from_slug']) - - # Deleting unique_together for [to_slug] on relationshipstatus. - db.delete_unique('relationships_relationshipstatus', ['to_slug']) - - # Changing field 'RelationshipStatus.to_slug' - # (to signature: django.db.models.fields.CharField(max_length=100)) - db.alter_column('relationships_relationshipstatus', 'to_slug', orm['relationships.relationshipstatus:to_slug']) - - # Changing field 'RelationshipStatus.symmetrical_slug' - # (to signature: django.db.models.fields.CharField(max_length=100)) - db.alter_column('relationships_relationshipstatus', 'symmetrical_slug', orm['relationships.relationshipstatus:symmetrical_slug']) - - # Changing field 'RelationshipStatus.from_slug' - # (to signature: django.db.models.fields.CharField(max_length=100)) - db.alter_column('relationships_relationshipstatus', 'from_slug', orm['relationships.relationshipstatus:from_slug']) - - def backwards(self, orm): - - # Changing field 'RelationshipStatus.to_slug' - # (to signature: django.db.models.fields.SlugField(max_length=50, unique=True, db_index=True)) - db.alter_column('relationships_relationshipstatus', 'to_slug', orm['relationships.relationshipstatus:to_slug']) - - # Changing field 'RelationshipStatus.symmetrical_slug' - # (to signature: django.db.models.fields.SlugField(max_length=50, unique=True, db_index=True)) - db.alter_column('relationships_relationshipstatus', 'symmetrical_slug', orm['relationships.relationshipstatus:symmetrical_slug']) - - # Changing field 'RelationshipStatus.from_slug' - # (to signature: django.db.models.fields.SlugField(max_length=50, unique=True, db_index=True)) - db.alter_column('relationships_relationshipstatus', 'from_slug', orm['relationships.relationshipstatus:from_slug']) - - # Creating unique_together for [to_slug] on relationshipstatus. - db.create_unique('relationships_relationshipstatus', ['to_slug']) - - # Creating unique_together for [from_slug] on relationshipstatus. - db.create_unique('relationships_relationshipstatus', ['from_slug']) - - # Creating unique_together for [symmetrical_slug] on relationshipstatus. - db.create_unique('relationships_relationshipstatus', ['symmetrical_slug']) - - models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'relationships': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'symmetrical': 'False'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'relationships.relationship': { - 'Meta': {'unique_together': "(('from_user', 'to_user', 'status'),)"}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_users'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['sites.Site']"}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['relationships.RelationshipStatus']"}), - 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_users'", 'to': "orm['auth.User']"}) - }, - 'relationships.relationshipstatus': { - 'from_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'symmetrical_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'to_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'verb': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'sites.site': { - 'Meta': {'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['relationships'] diff --git a/relationships/migrations/0004_add_site_to_unique_together.py b/relationships/migrations/0004_add_site_to_unique_together.py deleted file mode 100644 index 4deff5a..0000000 --- a/relationships/migrations/0004_add_site_to_unique_together.py +++ /dev/null @@ -1,86 +0,0 @@ -from south.db import db -from relationships.models import * - - -class Migration: - - def forwards(self, orm): - - # Deleting unique_together for [from_user, to_user, status] on relationship. - db.delete_unique('relationships_relationship', ['from_user_id', 'to_user_id', 'status_id']) - - # Creating unique_together for [from_user, to_user, status, site] on Relationship. - db.create_unique('relationships_relationship', ['from_user_id', 'to_user_id', 'status_id', 'site_id']) - - def backwards(self, orm): - - # Deleting unique_together for [from_user, to_user, status, site] on Relationship. - db.delete_unique('relationships_relationship', ['from_user_id', 'to_user_id', 'status_id', 'site_id']) - - # Creating unique_together for [from_user, to_user, status] on relationship. - db.create_unique('relationships_relationship', ['from_user_id', 'to_user_id', 'status_id']) - - models = { - 'auth.group': { - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'relationships': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'symmetrical': 'False'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'relationships.relationship': { - 'Meta': {'unique_together': "(('from_user', 'to_user', 'status', 'site'),)"}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_users'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'default': '24', 'related_name': "'relationships'", 'to': "orm['sites.Site']"}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['relationships.RelationshipStatus']"}), - 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_users'", 'to': "orm['auth.User']"}) - }, - 'relationships.relationshipstatus': { - 'from_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'symmetrical_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'to_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'verb': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'sites.site': { - 'Meta': {'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['relationships'] diff --git a/relationships/migrations/0005_add_weight_column.py b/relationships/migrations/0005_add_weight_column.py deleted file mode 100644 index a286480..0000000 --- a/relationships/migrations/0005_add_weight_column.py +++ /dev/null @@ -1,85 +0,0 @@ -# encoding: utf-8 -from south.db import db -from south.v2 import SchemaMigration - - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'Relationship.weight' - db.add_column('relationships_relationship', 'weight', self.gf('django.db.models.fields.FloatField')(default=1.0, null=True, blank=True), keep_default=False) - - def backwards(self, orm): - - # Deleting field 'Relationship.weight' - db.delete_column('relationships_relationship', 'weight') - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'relationships': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'related_to'", 'symmetrical': 'False', 'through': "orm['relationships.Relationship']", 'to': "orm['auth.User']"}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'relationships.relationship': { - 'Meta': {'unique_together': "(('from_user', 'to_user', 'status', 'site'),)", 'object_name': 'Relationship'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_users'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'related_name': "'relationships'", 'to': "orm['sites.Site']"}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['relationships.RelationshipStatus']"}), - 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_users'", 'to': "orm['auth.User']"}), - 'weight': ('django.db.models.fields.FloatField', [], {'default': '1.0', 'null': 'True', 'blank': 'True'}) - }, - 'relationships.relationshipstatus': { - 'Meta': {'object_name': 'RelationshipStatus'}, - 'from_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), - 'symmetrical_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'to_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'verb': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'sites.site': { - 'Meta': {'object_name': 'Site', 'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['relationships'] diff --git a/relationships/models.py b/relationships/models.py index 051b6d0..07908eb 100644 --- a/relationships/models.py +++ b/relationships/models.py @@ -1,4 +1,8 @@ +from functools import partial +import random + import django +import jsonfield from django.conf import settings from django.contrib.sites.models import Site from django.db import models, connection @@ -6,6 +10,51 @@ from django.utils.translation import ugettext_lazy as _ from .compat import User +from south.modelsinspector import add_introspection_rules + + +def sid_creator(prefix): + try: + sid_creator.limit + except AttributeError: + sid_creator.limit = 16**SIDField.SID_LENGTH + # http://stackoverflow.com/a/2782859/440060 + return prefix + '_' + ('%0{}x'.format(SIDField.SID_LENGTH) % random.randrange(sid_creator.limit)) + + +class SIDField(models.CharField): + SID_LENGTH = 16 + + def __init__(self, *args, **kwargs): + kwargs['max_length'] = SIDField.SID_LENGTH + 4 + kwargs['unique'] = True + kwargs['db_index'] = True + kwargs['editable'] = False + kwargs['primary_key'] = True + if 'prefix' in kwargs: + self.prefix = kwargs.pop('prefix') + super(SIDField, self).__init__(*args, **kwargs) + + def contribute_to_class(self, cls, name, virtual_only=False): + if not hasattr(self, 'prefix'): + self.prefix = cls.__name__[0].upper() + self.default = partial(sid_creator, self.prefix) + super(SIDField, self).contribute_to_class(cls, name, virtual_only=virtual_only) + + +rules = [ + ( + (SIDField,), + [], + { + "db_index": [True, {"is_value": True}], + "max_length": [SIDField.SID_LENGTH + 4, {"is_value": True}], + "unique": [True, {"is_value": True}], + "primary_key": [True, {"is_value": True}] + }, + ) +] +add_introspection_rules(rules, ["^relationships\.models\.SIDField"]) class RelationshipStatusManager(models.Manager): @@ -25,14 +74,18 @@ def by_slug(self, status_slug): class RelationshipStatus(models.Model): + id = SIDField(prefix='RS') name = models.CharField(_('name'), max_length=100) - verb = models.CharField(_('verb'), max_length=100) + verb = models.CharField(_('verb'), max_length=100, unique=True) from_slug = models.CharField(_('from slug'), max_length=100, - help_text=_("Denote the relationship from the user, i.e. 'following'")) + help_text=_("Denote the relationship from the user, i.e. 'following'"), + unique=True) to_slug = models.CharField(_('to slug'), max_length=100, - help_text=_("Denote the relationship to the user, i.e. 'followers'")) + help_text=_("Denote the relationship to the user, i.e. 'followers'"), + unique=True) symmetrical_slug = models.CharField(_('symmetrical slug'), max_length=100, - help_text=_("When a mutual relationship exists, i.e. 'friends'")) + help_text=_("When a mutual relationship exists, i.e. 'friends'"), + unique=True) login_required = models.BooleanField(_('login required'), default=False, help_text=_("Users must be logged in to see these relationships")) private = models.BooleanField(_('private'), default=False, @@ -50,15 +103,19 @@ def __unicode__(self): class Relationship(models.Model): + id = SIDField() from_user = models.ForeignKey(User, - related_name='from_users', verbose_name=_('from user')) + related_name='from_relationships', verbose_name=_('from user')) to_user = models.ForeignKey(User, - related_name='to_users', verbose_name=_('to user')) + related_name='to_relationships', verbose_name=_('to user'), + null=True, blank=True) status = models.ForeignKey(RelationshipStatus, verbose_name=_('status')) created = models.DateTimeField(_('created'), auto_now_add=True) weight = models.FloatField(_('weight'), default=1.0, blank=True, null=True) site = models.ForeignKey(Site, default=settings.SITE_ID, verbose_name=_('site'), related_name='relationships') + extra_data = jsonfield.JSONField(_('extra data'), default=None, blank=True, + null=True, serialize=False) class Meta: unique_together = (('from_user', 'to_user', 'status', 'site'),) @@ -69,7 +126,15 @@ class Meta: def __unicode__(self): return (_('Relationship from %(from_user)s to %(to_user)s') % {'from_user': self.from_user.username, - 'to_user': self.to_user.username}) + 'to_user': self.to_user.username if self.to_user else 'None'}) + + @staticmethod + def get_owner_fields(): + return ('to_user', 'from_user') + + def is_owner(self, user): + return user.pk in (self.to_user_id, self.from_user_id) + field = models.ManyToManyField(User, through=Relationship, symmetrical=False, related_name='related_to') @@ -80,7 +145,7 @@ def __init__(self, instance=None, *args, **kwargs): super(RelationshipManager, self).__init__(*args, **kwargs) self.instance = instance - def add(self, user, status=None, symmetrical=False): + def add(self, user, status=None, symmetrical=False, extra_data=None): """ Add a relationship from one user to another with the given status, which defaults to "following". @@ -97,15 +162,24 @@ def add(self, user, status=None, symmetrical=False): if not status: status = RelationshipStatus.objects.following() - relationship, created = Relationship.objects.get_or_create( - from_user=self.instance, - to_user=user, - status=status, - site=Site.objects.get_current() - ) + try: + relationship = Relationship.objects.get( + from_user=self.instance, + to_user=user, + status=status, + site=Site.objects.get_current(), + ) + except Relationship.DoesNotExist: + relationship = Relationship.objects.create( + from_user=self.instance, + to_user=user, + status=status, + site=Site.objects.get_current(), + extra_data=extra_data + ) if symmetrical: - return (relationship, user.relationships.add(self.instance, status, False)) + return (relationship, user.relationships.add(self.instance, status, False, extra_data)) else: return relationship @@ -131,16 +205,16 @@ def remove(self, user, status=None, symmetrical=False): def _get_from_query(self, status): return dict( - to_users__from_user=self.instance, - to_users__status=status, - to_users__site__pk=settings.SITE_ID, + to_relationships__from_user=self.instance, + to_relationships__status=status, + to_relationships__site__pk=settings.SITE_ID, ) def _get_to_query(self, status): return dict( - from_users__to_user=self.instance, - from_users__status=status, - from_users__site__pk=settings.SITE_ID + from_relationships__to_user=self.instance, + from_relationships__status=status, + from_relationships__site__pk=settings.SITE_ID ) def get_relationships(self, status, symmetrical=False): @@ -186,23 +260,23 @@ def exists(self, user, status=None, symmetrical=False): users. An optional :class:`RelationshipStatus` instance can be specified. """ query = dict( - to_users__from_user=self.instance, - to_users__to_user=user, - to_users__site__pk=settings.SITE_ID, + to_relationships__from_user=self.instance, + to_relationships__to_user=user, + to_relationships__site__pk=settings.SITE_ID, ) if status: - query.update(to_users__status=status) + query.update(to_relationships__status=status) if symmetrical: query.update( - from_users__to_user=self.instance, - from_users__from_user=user, - from_users__site__pk=settings.SITE_ID + from_relationships__to_user=self.instance, + from_relationships__from_user=user, + from_relationships__site__pk=settings.SITE_ID ) if status: - query.update(from_users__status=status) + query.update(from_relationships__status=status) return User.objects.filter(**query).exists() diff --git a/relationships/utils.py b/relationships/utils.py index 0dcfd32..56e0ef9 100644 --- a/relationships/utils.py +++ b/relationships/utils.py @@ -1,3 +1,12 @@ +# Safe User import for Django < 1.5 +try: + from django.contrib.auth import get_user_model +except ImportError: + from django.contrib.auth.models import User +else: + User = get_user_model() + + from .compat import User from .models import RelationshipStatus @@ -43,3 +52,9 @@ def negative_filter(qs, user_qs, user_lookup=None): query = {'%s__in' % user_lookup: user_qs} return qs.exclude(**query).distinct() + + +# With the default User model these will be 'auth.User' and 'auth.user' +# so instead of using orm['auth.User'] we can use orm[user_orm_label] +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.model_name)