How to override model field in Django for library model? [duplicate] - python

This question already has answers here:
django: modifying/extending 3rd party apps
(3 answers)
Closed 3 months ago.
I need to override library model field in Django. This model is integrated in that library and used there. The changes I need is to add a unique constraint to one of the model fields. But this is not the abstract model so I can't inherit this model as I understand.
The question: is there a way to override usual model field in Django without inheritance?

Not that I'm aware of. I'd be looking at modifying (forking) the "library" model, although there might be issues if it's proprietary 3rd party code for which you do not have source.
The usual thing against concrete inheritance is that it causes a new DB table to be created and thereafter, every query involves a join on a OneToOne field between the two tables. However, I'm wondering whether this happens if you merely add a constraint to an existing field. Might be worth investigating in detail.
Likewise, can you inherit merely to subclass the .save() method, and apply the equivalent to a constraint therein? This isn't bullet-proof, because it's enforced only by the saving of Django objects and can be overridden both by django bulk_update and by anybody accessing the DB table without Django. And again, does it end up creating and joining a second DB table even if it contains no fields at all (except a primary key).
Sorry, more questions than a proper answer. Maybe somebody knows these answers?

Related

Django custom auth model

Not sure how to name this problem, let me elaborate.
I have very old django project, been migrating it since django 1.5 or so.
It has always had class Member, extending User and has been practically used as authentication model for the app. AUTH_USER_MODEL was never changed, however SOCIAL_AUTH_USER_MODEL is set to custom auth model (and it works that way).
Currently I am migrating to django 3.x and I am ran into trouble with django-registration - it used to work with Member set as model, but now it checks it against AUTH_USER_MODEL. Bottom line is, I want to make it the "right" way and set proper custom model and make sure I do it right before I dig deep into it as I expect it not to be too easy.
When I simply set AUTH_USER_MODEL to custom model, I get error members.Member.user_ptr: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
When I make Member extend AbstractUser instead of User, I am missing id and fields as django then expects all data in single table (rather than having 2 one-to-one relationship tables).
I could somehow manually merge data into this single table, but I am not even sure if that's the right way.
What would be the best way to keep this project out of trouble for the future? How do I migrate/proceed? I am willing to get my hands dirty :-)
Difficult to help without sample code. Otherwise
Changing AUTH_USER_MODEL after you’ve created database tables is
significantly more difficult since it affects foreign keys and
many-to-many relationships
These articles might help you.
Ruddra.com
Tobias McNulty

Django ORM : model with a list of items from another model

In my Django models, I have two models : one called Site and the other SiteFeature.
Object-wise, it is very clear how this should work : every instance of the Site class should have as property a list containing instances of the SiteFeature class, simply because the SiteFeature objects should only exist in relation to a Site object.
Database-wise, it is also very clear how it should work : the SiteFeature table should contain a not-nullable column referencing the primary key id column of the Site table, with a foreign key.
But in terms of Django ORM, I don't know how to code this.
Based on this question, and this other example, it seems the classical way to proceed works the other way round :
The Site model class contains no ORM model field referencing the SiteFeature list.
Instead, the SiteFeature ORM model class has a ForeignKey field referencing the Site class.
I see there is a way to code this out : by adding a function to the Site model class that searches all the related SiteFeature, and make this function a property (decorator #property):
#property
def site_features(self):
return SiteFeature.objects.filter(site_id=site_id)
But that leaves me doubts :
The proper logic for me would also be that when I save, update or create an instance of the Site class, it would also automatically save / update / create the instances of SiteFeature that are related to it. (same thing for deleting the object, but that can be covered by the on_delete=models.CASCADE parameter of the ForeignKey field).
I could add my own save_with_features / update_with_features / create_with_features methods that cascade all but I am not sure what would happen in case of calls made automatically by Django to the standard save / update / create such as in bulk operations.
This problem seems to basic that I suppose there is already a proper way to do it. How would that be ?
Eventually, I solved the problem with the sitefeature_set Manager.
Reference: https://docs.djangoproject.com/en/3.0/topics/db/queries/#following-relationships-backward

Why doesn't Django support Single Table Inheritance?

What is the rationale behind the decision to not support Single Table Inheritance in Django?
Is STI a bad design? Does it result in poor performance? Would it conflict with the Django ORM as it is?
Just wondering because it's been a missing feature for like ten years now and so there must have been a conscious decision made that it would never be supported.
One reason is possibly that Django does not (currently) have the ability to modify database tables after creation.
You can 'kind-of' do STI using proxy models. This will not allow you to have different fields on the different models, but it will allow you to attach different behaviour (via model methods) to different subclasses.
However, if you decide to create a subclass with extra fields, Django will not be able to update the database to reflect that.

data validation for SQLAlchemy declarative models

I'm using CherryPy, Mako templates, and SQLAlchemy in a web app. I'm coming from a Ruby on Rails background and I'm trying to set up some data validation for my models. I can't figure out the best way to ensure, say, a 'name' field has a value when some other field has a value. I tried using SAValidation but it allowed me to create new rows where a required column was blank, even when I used validates_presence_of on the column. I've been looking at WTForms but that seems to involve a lot of duplicated code--I already have my model class set up with the columns in the table, why do I need to repeat all those columns again just to say "hey this one needs a value"? I'm coming from the "skinny controller, fat model" mindset and have been looking for Rails-like methods in my model like validates_presence_of or validates_length_of. How should I go about validating the data my model receives, and ensuring Session.add/Session.merge fail when the validations fail?
Take a look at the documentation for adding validation methods. You could just add an "update" method that takes the POST dict, makes sure that required keys are present, and uses the decorated validators to set the values (raising an error if anything is awry).
I wrote SAValidation for the specific purpose of avoiding code duplication when it comes to validating model data. It works well for us, at least for our use cases.
In our tests, we have examples of the model's setup and tests to show the validation works.
API Logic Server provides business rules for SQLAlchemy models. This includes not only multi-field, multi-table validations, but multi-table validations. It's open source.
I ended up using WTForms after all.

Django Data Migration, using South with Inheritance

We are migrating the data in several instances of our Django project to a new schema.
The old schema had:
class Group(models.Model)
class User(models.Model)
And the new schema has:
class AccessEntity(models.Model)
class Group(AccessEntity)
class User(AccessEntity)
We are trying to use South to do a data migration for these groups and users. http://south.aeracode.org/docs/tutorial/part3.html
I've gathered that I'll need to use forward rules to specify how to migrate the Users but there are a few issues I've run up against.
The main issue is how to keep the ID of the User/Group the same if I were to create a new User object that extends the AccessEntity class.
Users & Groups are referenced to by objects they own or are assigned to them. If I change their ID that information would be lost. Is there a way of keeping the same ID for an object even though I need it to now extend from AccessEntity?
not sure if I understand your question correctly, but the way multi-table model inheritance works ist that there will be an implicit one-to-one field in the parent and child models. So both User and Group would use an ID field of AccessEntity if AccessEntity has such a field.
If you create AccessEntity such that it has a field ID you can assign to it when you write a forward (data)-migration. That way you can make sure that the AccessEntity gets the right ID.
If have written a longer multi-table inheritance tutorial and it looks like you are trying to do something similar.
And furthermore the answer to this question could also be helpful (note that some things in the original answer does will not work in new versions of django / south, see my tutorial / the answer at the bottom for changes).
What might be a problem in your case is that if you already have data in both User and Groups and the id field is auto-generated, IDs likely not be distinct, e.g. you are likely going to have both a User and a Group with ID==1. This could be a problem if you want to query based on those IDs and of course ID could not be a primary key for AccessEntity then.

Categories