Django ModelForm save using db_alias param "using" - database

Is it possible to save ModelForm object data with db_alias different than "default"
my_form = MyModelForm(request.POST)
my_form.save(commit=True,using="db_alias")
as well as saving data with model instance?
Thank you.

Short Answer: Unfortunately ,you can't save the form that way. If you form doesn't contain ForeignKey or m2m fields (or you are controlling them yourself, for example using an autocompletefield, etc.), you can handle the object after the form:
_obj = _form.save(commit=False)
_obj.save(using=_db_alias)
Long answer: If you want the modelform to behave like a normal one with ForeignKeys and m2m-fields, something like:
# The form's foreign_keys and m2m-fields get the data from the db_alias database
# and evertyhing is sdisplayed correctly on the template.
_form = myModelForm(request, db_alias=_db_alias)
# The form saves to the correct DB and foreigns & M2ms are matched correctly in this DB
# _form.save()
Although this would be ideal, you just can't use this behaviour. There are many DB hooks that you need to alter in Django code to get this working. What I have done is to create a new modelform class from the base modelform, and get the (partial) functionality described before.
Hope this helps, and also hopping a better solution comes soon.

Related

How to provide model configuration presets in Django

so what I am trying to achieve is the following:
I have two models A and B which have a OneToOne relationship. Instances of model A are always created before their respective model B instances. Dependent on a parameter, I want to be able to initialize an instance of model b with different initial values.
What I've come up with is to define a ProtoTypeModel and subclass it with the actual Model like so:
from django.db import models
#other imports
class PrototypeB(models.Model):
#define all fields
class B(PrototypeB):
pass
By using dict = PrototypeB.objects.filter(**my criteria).values()[0] or a custom Serializer from Django Rest Framework, I will get a dict which I can then use to instantiate my instance of model B : B.objects.create(**dict).
Is this the proper way to do so or am I missing a huge point?
Best,
D
In case anyone stumbles upon the same question on his path, here's how I did it.
First I thought about implementing the solution I mentioned above. However, researching about multi table inheritance, I found that this is actually a non functioning one.
The multi table inheritance will create an implicit OneToOne _ptr field, which will trigger cascade deleting behavior, causing my arche type models to be deleted, when an instance of B is deleted.
I went along implementing two models PrototypeB and B which works perfectly fine.

Proper way to access entity key outside the original class

I'm coding my first GAE web app in Python. I need to collect ~30 properties and instantiate a Client object (I'm using Model.db). I'd like to accomplish this on 4 separate sequential forms. If I use a separate page handler for each form, what is the best way to extract and reference the key or id on each form and put data into the same data entity? How do I avoid a global variable?
Not sure I follow... You may need to explain the issue a little more clearly.
First, do not use a global variable.
You can have 4 forms on the same template, all with the same handler. Give each a separate hidden attribute. Or, depending on your templating package, you should be able to access the form by ID.
In your handler:
entity = MyModel.get_by_key_name('my_key_name')
if request.method == 'POST':
if request.POST['hidden_field'] == 'firstform':
entity['prop_1'] = form.prop_1.data
...
if request.POST['hidden_field'] == 'secondform':
...
...
entity.put()
else:
return <template>
You will need to modify the syntax above to suit your templating pkg.

Custom South migration with custom fields - Django

I am pretty new to Django and just got a job that involves maintaining and adding features to a site I did not design, so I am still kind of confused about the structure and what not of the project. The site is using South for database migrations and I've got a hang of using it to add new applications to the project. The trouble I am having now is that I need to delete a certain field in a model because it is no longer needed and on the admin page it is required to be filled out. From my understanding of Django so far it appears to be a custom field. It is defined like this in its own separate library application(still not sure if thats the right lingo).
class Genre(models.Model):
name = models.CharField(max_length=255)
def __unicode__(self):
return u"%s" % self.name
Here is the models that uses the custom field if that helps out any.
class Entry(models.Model):
artist = d51fields.ForeignKey(Artist, instantiate_fn=instant_artist)
album = d51fields.ForeignKey(Album, js_methods=['match_artist_and_startswith'], instantiate_fn=instant_album)
track = d51fields.ForeignKey(Track, js_methods=['match_album_and_startswith'], instantiate_fn=instant_track)
genre = models.ForeignKey(Genre)
submitted = models.DateTimeField(auto_now_add=True)
is_rotation = models.BooleanField()
dj = models.ForeignKey(DJ)
show = models.ForeignKey(Show, null=True, blank=True)
objects = EntryManager()
def __unicode__(self):
return "%s [%s]" % (self.artist, self.track)
class Meta:
verbose_name = "entry"
verbose_name_plural = "entries"
I've looked at the documentation for migrating custom fields but it is all really confusing for me, so I am looking for some more help. I just want to get rid of the table holding the Genre field and clean up the dependencies with the foreign keys associated with it. Do you think I should write some custom rules for South and use a migration or just try and do it manually in Postgresql. I tried doing it with just Postgres and I failed miserably.
Any guidance would be greatly appreciated. If you want more info about the situation just ask and I can add it to the post. I have a feeling there is a lot of dependencies I will have to deal with, but hopefully there is a simple fix.
Also if some one knows how to get a good view of the database structure that would be great.
Thanks so much. All of you guys are great.
Edit1
Here what I got when I removed the ForeignKeys and then ran
manage.py schemamigration logs --auto
! Cannot freeze field 'logs.entry.artist'
! (this field has class d51_admin_autofk.fields.ForeignKey)
! Cannot freeze field 'logs.entry.album'
! (this field has class d51_admin_autofk.fields.ForeignKey)
! Cannot freeze field 'logs.entry.track'
! (this field has class d51_admin_autofk.fields.ForeignKey)
! South cannot introspect some fields; this is probably because they are custom
! fields. If they worked in 0.6 or below, this is because we have removed the
! models parser (it often broke things).
I am not totally sure what sort of action I should take next. I looked into the South documentation and it wasn't too clear about how to write the rules for migrating things like this.
I don't see any custom field anywhere in the code you posted. All I see is two models, all containing standard fields shipped with Django.
If I understand correctly, you can just delete all ForeignKey references to your Genre model. Then run ./manage.py schemamigration <yourappname> --auto. This will ask you for a default value for the genre field in the Entry model, provide an ID of some kind. (This is because migrations can be applied both forwards and backwards, so if you try to undo the migration, this is the value that will get inserted in all your model instances.)
Finally, just applying the migration should make it happen: ./manage.py migrate <yourappname>.
After that you should be safe to drop the table storing your Genre model.
Be sure to try this on a development server though, just to make sure it doesn't blow up. (-;

Django: cannot detect changes on many-to-many field with m2m_changed signal - auditing at model-level

I'd like to keep track on what field has changed on any model (i.e. audit at model level since it's more atomic, not at admin/form-level like what django and django-reversion can already do). I'm able to do that for any field using pre/post save/delete signals. However, I have a problem of doing that on an m2m field.
For the code sample below, i define 'custom_groups' m2m field in user change form since it's a reverse relation. When user saves the form on admin interface for example, I'd like to log if there's a change in 'custom_groups' field.
Model:
from django.contrib.auth.models import User
class CustomGroup(models.Model):
users = models.ManyToManyField(User, related_name='custom_groups')
ModelForm:
class CustomUserChangeForm(UserChangeForm):
custom_groups = forms.ModelMultipleChoiceField(required=False, queryset=CustomGroup.objects.all())
The problem with using m2m_changed signal is that i can't check what has actually changed for the case where the m2m field is updated using assignment operator:
user.custom_groups = self.cleaned_data['custom_groups']
This is because internally django will perform a clear() on *custom_groups*, before manually adding all objects. This will execute pre/post-clear and then pre/post save on the m2m field.
Am I doing all this the wrong way? Is there a simpler method that can actually work?
Thanks!
I had a similar problem and I think I could solve it. I don't know how you are using the m2m_changed but it should be on models.py and should be similar to something like this:
signals.m2m_changed.connect(your_function, sender=CustomGroup.users.through)
Now, I would create a signals.py file containing that function, and the following code should print you the options that you have selected:
def your_function(sender, instance, action, reverse, model, pk_set, **kwargs):
if action == 'post_add':
for val in pk_set:
print val
Now, you know the updated values. I hope this could solve your problem.

Django: form that updates X amount of models

I have a page where it displays a filtered model instance list and allows users to update some fields of it or add new fields as a form.
I am curious what wpuld be a clever way of doing this, to delete and resave all the input data or make comparison for each data and save edited / new fields& entities.
I would like to mind you that I use postgres for saving these values and I display around 20 entries for this form.
The QuerySet object has the update() method - it's used in ie. Admin Panel for bulk updating multiple selected objects from change lists. Here is the method reference at django's official documentation.
How to use it:
Just create queryset with the models you want to update (assumng that MyModel has field named 'my_field'):
qs = MyModel.objects.all()
qs.update(my_field=value)
That's it - remember that update() method will not send any signals like the save() method - it will just run query directly to database.
As for 'adding fields via form' - I don't know if I got it right? You want to add additional related models or dynamically add fields to the model table on database?
If you want to add related models then use InlineFormset (http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-form) - it's quite easy to handle.
Otherwise you have to add fields to models' _meta as described here: How dynamic add custom field to model.

Resources