Third-party-app for merging Django user objects? - django

I need to merge two users in a Django database.
So I wonder if there is any simple way (maybe a dedicated app) to do that?
For example:
We have user_a and user_b and some models that have foreign keys to the User model (Books, Interests, Teams and so on…).
By merging users, I want to delete the object user_b and to set all foreign keys pointing to this object to point to user_a. And – this is my main concern – I want the objects that need to be changed because they reference the to-be-deleted object to be determined automatically without having to specify a list of those Models and foreign key fields in them manually.
Is this already implemented and I'm reinventing the wheel?
Is this possible?
If not, please show me the way to do it: how can I build a list of Django models that have a foreign key to a specific model (User in my case) in runtime?
Thank you for your time.

I found this snippet http://djangosnippets.org/snippets/2283/ . I'm going to have to modify it though, to make it recursive. I will share my code once I'm done.

With Django 1.8 and beyond, you could achieve this robustly using the Model _meta API.
Specifically, you could use Options.get_fields. This will even let you handle generic relations.
You'll need to consider for each related field whether you want to add or replace on merge. This decision depends on your application logic and corresponding schema choices.
u = User.objects.get(pk=123)
related_fields = [
f for f in u._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and not f.concrete
]
for f in related_fields:
# use field's attributes to perform an update

Related

Get ContentType id in Django for generic relation

I'm porting a project from Rails to Django with a legacy database. In Rails I had a polymorphic association that allowed me to add a footnote to any row in the database. I'm trying to implement the same thing in the Django app. I found the documentation on Generic Relations and it looks perfect. Unfortunately, I first need to create new fields in my legacy database to hold the ContentType id for the relevant models. I only used the polymorphic association with 2 tables, so all I need are those two corresponding ids from the Django app, but I can't seem to find the appropriate command for looking up a ContentType id in Django.
Any suggestions are most welcome. I tried searching through previous questions but couldn't seem to find what I am looking for. Thank you very much for you time and help.
from the docs
you can do:
>>> b = Bookmark.objects.get(url='https://www.djangoproject.com/')
>>> bookmark_type = ContentType.objects.get_for_model(b)
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id,
... object_id=b.id)
so just instantiate an instance of your model and then do ContentType.objects.get_for_model(<instance>).id
I think there's a way to pass just the model name, too... let me know if that would work better and I'll try to find it; I've used it in the past.
You can also get ContentType ID without creating an instance, which is more efficient if you don't have and don't need an instance but just want to get ContentType ID by model name.
ContentType.objects.get(model='bookmark').id
Notes : if the name of your model is upper case, please use lower case to search. For example: model = 'bookmark' rather than 'Bookmark'

What do I use instead of ForiegnKey relationship for multi-db relation

I need to provide my users a list of choices from a model which is stored in a separate legacy database. Foreign keys aren't supported in django multi-db setups. The ideal choice would be to use a foreign key, but since thats not possible I need to some up with something else.
So instead I created an IntegerField on the other database and tried using choices to get a list of available options.
class OtherDBTable(models.Model):
client = models.IntegerField(max_length=20, choices=Client.objects.values_list('id','name'))
the problem I'm having is that the choices seem to get populated once but never refreshed. How do I ensure that whenever the client list changes that those newest options area available to pick.
What I was really looking for was a way that I could simulate the behavior of a Foreign key field, at least as far as matching up ID's go.
There wasn't a clear way to do this, since it doesn't seem like you can actually specify an additional field when you instantiate a model (you can with forms, easily)
In any case to deal with the problem, since the database is MySQL based, I ended up creating views from the tables I needed in the other database.
To build on #Yuji's answer - if you do self.fields['field'].choices = whatever in the model's __init__, whatever can be any iterable.
This means you can inherit from iterable, and have that object interface to your legacy database, or you can use a generator function (in case you are unfamiliar, look up the yield keyword).
Citing a Django's manual:
Finally, note that choices can be any iterable object -- not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking choices to be dynamic, you're probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn't change much, if ever.
Why dont you want just export data from the legacy database and to import it into the new one? This could be done periodically, if the legacy database still in use.

Django removing object from ManyToMany relationship

How would I delete an object from a Many-to-Many relationship without removing the actual object?
Example:
I have the models Moods and Interest.
Mood has a many-to-many field interests (which is a models.ManyToManyField(Interest)).
I create an instance of Moods called my_mood. In my_moods's interests field I have my_interest, meaning
>>> my_mood.interests.all()
[my_interest, ...]
How do I remove my_interest from my_mood without deleting either model instance? In other words, how do I remove the relationship without affecting the related models?
my_mood.interests.remove(my_interest)
Django's Relations Docs
Note: you might have to get an instance of my_mood and my_interest using Django's QuerySet API before you can execute this code.
If you need to remove all M2M references without touching the underlying objects, it's easier to work from the other direction:
interest.mood_set.clear()
While this does not directly address the OP's question, it's often useful in this situation.
In your case you can simply clear the relationship
my_mood.interests.clear()
Then perhaps when you are again creating new relation in your serializer you can do something like this
interests = Interests.objects.get_or_create(name='Something')
my_mood_obj.tags.add(tag[0])
my_mood_obj.save()
model.field.remove(object_you_want_to_remove)
In this case use: my_mood.interests.remove(my_interest)

Django inline formset with child of a child

I have three models:
Variable, which has Group as a foreign key
Group, which has Set as a foreign key
Set
I want to create a form that lets user create a new Set based on existing Set. Only things that user is able to modify are the Set name and Variable values.
This has given me an idea of using inlineformset_factory to access models' children. Sadly, all the examples I found go only one layer down.
Is there any way to access the Variables of a Set through inlineformset_factory?
If not - what is a good way to accomplish my goal?
Thank you.
From my experience, it is not worth hacking the existing inlineformset_factory to achieve much beyond what it is meant to do.
You are better off writing a custom view with the qs you want to use and create unique ids for each form element, to identify its parent.

Is there an autoincrement-per-user field in Django?

I was wondering if there is already a way to create a separate autoincrement-ID-per-user field in Django?
Basically, I'm storing many related models and I need the IDs generated to be autoincrement per user.
I don't want to change how id works, just need a new field that I can add which is unique=True per user.
Any suggestions (other than overriding save and implementing it myself)?
No, there's no such field, but I wonder why you think you need it. The ID is really just for the model's internal use, you shouldn't ever care what it is.
For example, if you want to know how many related items there are for a user then you would just use the count() method on the related queryset. If you want something to be unique per user, you can use the unique_together meta property.
Can you given an example of a use case for a per-user unique id?
Edited in response to comments: to get the object from a URL as you mention, you just need to do:
myuser.myobject_set.all()[7]