Can I add additional fields to ModelSerializer subclass?
By saying 'additional field', I mean some fields don't belong any models in database, which any effort that try to map those fields to exist model fields will fail. The reason I need to include those fields is for design purpose. I need to those fields' value to do the validation and creating a new instance eventually.
I know there is a kwarg in ModelSerialzer called 'context'. By putting all the additional information into 'context', it will work. However, I want to know is that possible to create additional fields?
I have tried adding 'write_only=True', which doesn't work. The only left option is to override default restore_object method to create the instance with my will.
Any other ideas?
As you have not posted any code I can only give you a generic answer, but if I understand you correctly, you wish to add a custom field to a ModelSerializer thats not part of your model...
In DSF you can do this very esaily (read here):
In this case you just want a simple read-only field, so instead just use:
custom_field = Field(source='get_whatever')
In terms if validation after that please read the DRF guide here
Related
I am planning to use a same user model for two different users with some additional fields in one model. Is it possible to do this in Django? If it is possible, how can I do it?
You have two options :
Firstly
You create a new Model (call it ExtendedUser) and you put the extra fields in that model.
You then set your ExtendedUser model to inherit from your MainUser model. This will create two tables with a one to one link between them.
The advantage of this is that your ExtendedUser model will inherit any methods defined in your original MainUser model, and you only need add methods to the ExtendedUser model if you absolutely have to. You can also write functions which can deal with both the MainUser and ExtendedUser models easily, since they are all instances of the MainUser model. One of the benefits of using inhertiance is if you write a query on the ExtendedUser model fetching all fields, it well fetch the MainUser fields too.
A Second (worse) option :
Have a single extended model with a flag on it which says whether to use the extra fields. This can be made to work, but will make your queries more complex, and if you need the extra fields to be indexed, the indexes are likely to be a bit less efficient.
Note : having a second table with a relationship between the two is no bad thing in SQL - that is how data is normally managed. Having special optional fields for some types of users isn't great as mentioned.
Is it possible get a queryset from a table in the app database that is NOT a model in the app?
If I have a table that is not a model named "cartable", conceptually, I want to do this:
myqueryset = cartable.objects.all()
Is there a relatively easy way to do this? Thanks!
If you want to access an existing table in your database that is not managed by your application, you can still create a class for it, and tell django to ignore it for migrations.
Just create a model and add the fields you need to access and then add a meta class to tell django to leave it alone.
class MyModel(model.Model):
class Meta:
managed = False
you can read about that at https://docs.djangoproject.com/en/1.9/ref/models/options/#managed
To do so you would need to create a class (not a model), with methods that use raw SQL. You should see more details here on how to do so: https://docs.djangoproject.com/en/1.9/topics/db/sql/#executing-custom-sql-directly
Please note that you will have to manually create the object with the right properties afterwards.
If you wanted to use Django ORM without the models, I don't think it is possible. You could however create a model that matches your db in a separate app and never create migrations for it to ensure you don't accidentally modify the DB.
Short answer is, "not really". Django QuerySet deals with model instances, so everything in QuerySet API is tied into models. Everything expects to return model instances, uses model fields etc.
That said, you should be able to create a model for an existing table. You will need to add db_table to the Meta, so Django knows where the table lives. If you have some indexing, you will need to make sure Django's idea of indexes is the same as the one in the database. indexed=True on fields and unique_together in Meta should help a lot with that.
Does anyone can tell me if it's possible to create a Model class, with some model fields and some other fields taking their data from external data sources. The point is that I would like this model to be exploited the same way as another model by ModelForm for instance. I mean if I redefine "objects" Manager of the model by specifying the actions to get the datas for special fields (those who may not be linked to datas from the database), would the modelForm link the input with the fields not attached to the database ? Similar question about related objects. If I have a Model that has a relation with that special Model, can I get this Model instances through the classic way to get related objects (with both the classic model fields and the non-database fields) ?
Please tell me if I'm not clear, I'll reformulate.
Thanks.
EDIT: I tried to make a Model with custom fields, and then override the default Manager and its functions: all, get, ... to get objects like it would be with classical Model and Manager, it works. However, I don't use QuerySet, and it seems that the only way to get ModelForm, related objects and the admin functionnalities, working with it, is to build the QuerySet properly and let it being returned by the manager. That's why now I'm wondering if it's possible to properly and manually build a QuerySet with data got from external sources, or tell django-admin, model forms and related objects to take care of another class than queryset on this Model.
Thanks
The way is to define custom methods:
Define custom methods on a model to add custom "row-level"
functionality to your objects. Whereas Manager methods are intended to
do "table-wide" things, model methods should act on a particular model
instance.
This is a valuable technique for keeping business logic in one place
-- the model.
I have now a partial solution. I override the Manager and in particular its all() and get() functions (because I only need those functions for now). all() returns a queryset in which I added the result of some logics that give me objects build from external datas (taken through xmlrpc in my case). I added those objects to the qs through _result_cache attribute.
I think it's not clean and in fact my Model is now a custom Model and I don't have any database field. I may use it to fill database Models... However I can use it the same way as classic models: MyModel.objects.all() for example.
If anyone has another idea I'd really appreciate.
Regards
how can I iterate and retrieve all fields of a django model?
I know that foo.item._meta.get_all_field_names() brings me all field names.
How can I access those fields (incl. their actual values) on a model instance? (Except the normal notation foo.fieldname).
I need this in order to build a custom output for my model including its manyTomany relations.
Any ideas?
How about:
getattr(foo.__class__, <field_name>)
This should give you the field object, rather than the value in the given model instance. If you want the value of the field in the given model insance you can call it like this:
getattr(foo, <field_name>)
This looks ugly but it will work:
for each in model_instance._meta.fields:
print each.value_from_object(model_instance)
That said, I have another suggestion. Given that your requirement is to
to build a custom output for my model including its manyTomany relations.
how about serializing the instance to a suitable format (XML/JSON) and then working on that? this avoids any dependency on _meta or any of the internal methods (which can possibly change).
I am using 0.97-pre-SVN-unknown release of Django.
I have a model for which I have not given any primary_key. Django, consequently, automatically provides an AutoField that is called "id". Everything's fine with that. But now, I have to change the "verbose_name" of that AutoField to something other than "id". I cannot override the "id" field the usual way, because that would require dropping/resetting the entire model and its data (which is strictly not an option). I cannot find another way around it. Does what I want even possible to achieve? If you may suggest any alternatives that would get me away with what I want without having to drop the model/table, I'd be happy.
Hmm... and what about explicitly write id field in the model definition? Like this for example:
class Entry(models.Model):
id = models.AutoField(verbose_name="custom name")
# and other fields...
It doesn't require any underlying database changes.
Look into the command-line options for manage.py; there's a command to dump all of the model data to JSON, and another command to load it back in from JSON. You can export all of your model data, add your new field to the model, then import your data back in. Just make sure that you set the db_column option to 'id' so you don't break your existing data.
Edit: Specifically, you want the commands dumpdata and loaddata.