Strangest bug I ever encountered
User model is the regular one from conrtib.auth.User
Let's say I have the following model:
class Region(model.Model):
name = models.CharField(max_length=256)
rakazim = models.ManyToManyField(settings.AUTH_USER_MODEL)
goal = models.IntegerField(default=0)
and someplace else I have:
user_model = get_user_model()
rakaz = user_model.objects.create_user(username, email, password)
Then Immediately after the user creation method is called the "rakaz" instance has a random region connected
rakaz.region_set.all() = [<random_region>]
It also sometimes connects to another model that has a similar ManyToManyField to AUTH_USER_MODEL
I debugged with pdb into the user creation method (in auth contrib) and immediately after calling save inside this happens.
AFAIK it happens only on the staging server, but until I find the reason I'm afraid to deploy to prod..
Django version 1.84. server using mariabdb on RDS
I don't use signals in my code (and at all :) ) and can't find relevant third party code doing this, (And if so it would happen on my machine also)
Any Ideas?
The issue turned out to be:
I seeded the staging server with data from prod for "region" the dumpdata command dumps the region with foreign keys for rakazim . But since the users where actually missing (I didn't copy the users from my prod environment) Instead of shouting at me, and not allowing me to loaddata with non existing foreign keys, mariadb chose to give me :+1 and add random foreign keys each time I created a user (Perhaps not random, but according to the imported mapping, not sure).
Lesson learned: use a proper DBMS and not a mysql varient.
Related
I am working on a project and I have decided to use Google App Engine for hosting (Django-nonrel). The website will have multiple types of users (inheriting from AbstractUser), and I want to be able to create permissions to control what a user can see/do. Since the native Django permissions do not work on Nonrel, I tried using permission_backend_nonrel, however it only works if you use the standard User model.
I have spent lots of time searching for how others have gotten permissions to work on Nonrel and AbstractUser, but have not found anything. It seems like I should give up on getting permissions to work and just create fields within the user models to replicate permissions. For example, if I want only some users to have the ability to change their email address, then I could do:
accounts\models.py
class UserProfile(AbstractUser):
address = models.CharField(max_length=40)
can_change_email = models.BooleanField(default=True)
customers\models.py
class CustomerProfile(UserProfile):
company = models.BooleanField(max_length=40)
In this scenario I could set 'can_change_email' and control this behavior in the views for UserProfile.
I would prefer to use the built-in permission system, but running out of ideas. Any suggestions?
I'd say you might have better luck creating separate one-to-one models to signify the difference between your users. Django expects you to have a single user model.
Another option is to use the normal User model and create proxy models that reflect the changes you want to have between users.
The first way:
class CustomerProfile(models.Model):
user = models.OneToOneField(User)
The second way:
class CustomerProfile(User):
class Meta:
proxy = True
My django project uses django-helpdesk app.
This app has Ticket model.
My app got a Client model, which should have one to many relationship with ticket- so I could for example list all tickets concerning specific client.
Normally I would add models.ForeignKey(Client) to Ticket
But it's an external app and I don't want to modify it (future update problems etc.).
I wold have no problem with ManyToMany or OneToOne but don't know how to do it with ManyToOne (many tickets from external app to one Client from my app)
Even more hacky solution: You can do the following in the module level code after you Client class:
class Client(models.Model):
...
client = models.ForeignKey(Client, related_name='tickets')
client.contribute_to_class(Ticket, name='client')
I haven't fully tested it (I didn't do any actual database migrations), but the correct descriptors (ReverseSingleRelatedObjectDescriptor for Ticket and ForeignRelatedObjectsDescriptor for Client) get added to the class, and South recognizes the new fields. So far it seems to work just like a regular ForeignKey.
EDIT: Actually not even that hacky. This is exactly how Django sets up foreign keys across classes. It just reverses the process by adding the field when the reverse related class is built. It won't raise an error if any of the original fields on either model is shadowed. Just make sure you don't do that, as it could potentially break your code. Other than that, I don't think there should be any issues.
There are (at least) two ways to accomplish it:
More elegant solution: Use a TicketProfile class which has a one-to-one relation to Ticket, and put the Client foreign key into it.
Hacky solution: Use a many-to-many relation, and manually edit the automatically created table and make ticket_id unique.
I'm trying to use django auth ldap (v1.1.7) with a custom user model and, while I have everything else taken care of, I still run into a familiar error message that I just don't know how to fix.
Running python manage.py syncdb returns:
CommandError: One or more models did not validate:
django_auth_ldap.testprofile: 'user' defines a relation with the model 'auth.Use
r', which has been swapped out. Update the relation to point at settings.AUTH_US
ER_MODEL.
My question here is - where can I find django_auth_ldap.testprofile and update the relation, to fix the issue?
Thanks in advance for helping me out.
L.E.: Ok, after a little googleing, i found out that this testprofile is located in django_auth_ldap/models.py and get this: I searched through all of my files and found the file, modified it to point to settings.AUTH_USER_MODEL and still I receive the same error.
Can anyone please help me out with this issue?
This is the part of django_auth_ldap's models.py -
class TestProfile(models.Model):
"""
A user profile model for use by unit tests. This has nothing to do with the
authentication backend itself.
"""
user = models.OneToOneField('auth.User') # <-- here is the trouble
is_special = models.BooleanField(default=False)
populated = models.BooleanField(default=False)
You cannot fix it unless you fix this part of the code and do as said in Django documentation -
Instead of referring to User directly, you should reference the user
model using django.contrib.auth.get_user_model(). This method will
return the currently active User model – the custom User model if one
is specified, or User otherwise.
And I wont recommend modifying the 3rd party packages yourself. If you can, go suggest the change to the developer, or send them a pull request. Once it's accepted, update the package.
I have a django app. The app is a normal application. Everything is running fine for me.
I want to implement a leaderboard as of now. Read couple of places that redis helps in doing it. And is really awesome. So I installed and configured redis on the server.
A minimal representation of the user profile for me is:
class UserProfile(models.Model):
user = models.OneToOneField(User)
invited_friends = models.BooleanField(default=False)
filled_wishlist = models.BooleanField(default=False)
upvote = models.IntegerField()
downvote = models.IntegerField()
#property
def reputation(self):
return int(confidence_fixed(self.upvote, self.downvote)*100)
Based on this reputation property, I get a value. All this is happening at the PostgreSQL db backend.
Now what I want to do is, take these scores, put them in redis key value store, and generate a leaderboard. There is a superawesome redis library for implementing leaderboard: https://github.com/agoragames/leaderboard-python
So my question is, given my redis server is running say at XXX.XXX.XX.XX:6342
How do I connect my python/django app to the redis server, and update the KV store, and once there are some numbers, how do I fetch in a view and display?
I think you're on the right track with the leaderboard-python library.
First you would need to write a onetime script to move the data from your model to redis using leaderboard-python.
# Create a new leaderboard
reputation_lb = Leaderboard('reputation')
for profile in UserProfile.objects.all():
reputation.rank_member('user_%i' % profile.user.pk, profile.reputation)
You would also need to create another property on the UserProfile model that retrieves the reputation from leaderboard-python.
Then you would most likely want to update the score, either you duplicate the information in the database and continue to use your reputation property to update the leaderboard, or you simply increment/decrement the score stored in redis.
The readme of the leaderboard-python library is quite good and should contain all of the examples you need to build this.
For future googlers, the way to tell Leaderboard how to connect to your redis server is by specifying a few more arguments in the Leaderboard constructor:
reputation_lb = Leaderboard('reputation', host="xyz.com", port="1234")
More details about what options are supported can be found in constructor code for Leaderboard here: http://pydoc.net/Python/leaderboard/2.8.0/leaderboard/
We're running django alongside - and sharing a database with - an existing application. And we want to use an existing "user" table (not Django's own) to store user information.
It looks like it's possible to change the name of the table that Django uses, in the Meta class of the User definition.
But we'd prefer not to change the Django core itself.
So we were thinking that we could sub-class the core auth.User class like this :
class OurUser(User) :
objects = UserManager()
class Meta:
db_table = u'our_user_table'
Here, the aim is not to add any extra fields to the customized User class. But just to use the alternative table.
However, this fails (likely because the ORM is assuming that the our_user_table should have a foreign key referring back to the original User table, which it doesn't).
So, is this sensible way to do what we want to do? Have I missed out on some easier way to map classes onto tables? Or, if not, can this be made to work?
Update :
I think I might be able to make the change I want just by "monkey-patching" the _meta of User in a local_settings.py
User._meta.db_table = 'our_user_table'
Can anyone think of anything bad that could happen if I do this? (Particularly in the context of a fairly typical Django / Pinax application?)
You might find it useful to set up your old table as an alternative authentication source and sidestep all these issues.
Another option is to subclass the user and have the subclass point to your user-model. Override the save function to ensure that everything you need to do to preserve your old functionality is there.
I haven't done either of these myself but hopefully they are useful pointers.
Update
What I mean by alternative authentication in this case is a small python script that says "Yes, this is a valid username / password" - It then creates an instance of model in the standard Django table, copies fields across from the legacy table and returns the new user to the caller.
If you need to keep the two tables in sync, you could decide to have your alternative authentication never create a standard django user and just say "Yes, this is a valid password and username"