How can i change django rest default behaviour for primary keys - django

According to Docs
http://www.django-rest-framework.org/api-guide/serializers/
The default ModelSerializer uses primary keys for relationships
It means for relation ships by default it will use
PrimaryKeyRelatedField
Now i want that instead of PrimaryKeyRelatedField the django rest should use
CustomPrimaryKeyRelatedField by default.
I don't want to manually write that in my 30 serializers and just want that if its not defined then use CustomPrimaryKeyRelatedField
Which thing i need to override for that

If you want to override this behaviour without modifying your code, you need to mangle with package source code. I think it's sufficient to change serializer_related_field in ModelSerializer https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/serializers.py.
A better approach would be to create a class in your project which inherits from ModelSerializer and overrides this single field, then replace in your project ModelSerializer with MyModelSerializer.

Related

Django: Is it possible to add constraint on model level only (Not on DB level)

Is there a way to add a unique constraint on model level only (not on DB level) in Django?
So, the user cannot create the object from the Model without bypassing the validation, but can create them on DB level without the model validation.
AFAIK - No...
But you can do it programmatically with obeying some rules. First of all, you shouldn't declare constraints as usual in model's fields definitions and Meta.
Second you should override save method of models, which you want containt (https://docs.djangoproject.com/en/3.1/topics/db/models/#overriding-model-methods).
Third, it leads from the link's note - Overridden model methods are not called on bulk operations - so you should avoid modifing methods invoked from .objects, e.g. .object.update(). I'm not sure about .objects.create - would be great to test it or find docs link.

In Django, how to use a manager as default but not for related fields?

Let's say I've got FooManager() that I set as the default manager for a model Foo, i.e. by having it be the first manager that Django encounters in the model definition. Now, admin, dumpdata, and Django generally uses this manager by default, as desired.
However, I don't want related field managers to use FooManager(), i.e. if Foo has a foreign key to Bar, then the related manager bar_instance.foo_set should use the "plain" Foo manager (to use the term in Django docs), not FooManager.
This doesn't seem possible, because the way to have FooManager NOT applied to related fields, is by setting its use_for_related_fields attribute to False. But all that does is get Django to use the the default manager (as opposed to the "plain" manager) for related fields.
And what's the default manager in this case? FooManager! Conundrum.
Any way to make this work, i.e. use FooManager as default manager but not for related fields?
NOTE: I'm using Django 1.6. I don't see anything in the 1.7 docs to suggest default/related manager behavior has changed. Also note I do NOT want to have to explicitly set the related manager per the new 1.7 functionality here; I want the reverse related manager to use the plain manager by default, as I'm refactoring an existing project and would prefer not to change every reverse related manager reference.
In this section the docs say the behavior is exactly what you want it to be.
The implementation also seems to do exactly what you want. 1.6 too.
Update:
If you don't want to change every usage, then create subclass of ForeignKey, which uses subclass of ForeignRelatedObjectsDescriptor as a related_accessor_class with this method overwritten.
Pseudo code:
class PlainManagerForeignRelatedObjectDescriptor(ForeignRelatedObjectDescriptor):
#cached_property
def related_manager_cls(self):
return create_foreign_related_manager(
models.Manager,
self.rel,
)
class PlainManagerForeignKey(ForeignKEy):
related_accessor_class = PlainManagerForeignRelatedObjectDescriptor

How can one best mark a model field as required in Django?

In Django, I would like the ability to mark certain model fields as required at the model (or at least database) level, to make sure that I am specifying them explicitly (i.e. not relying on defaults) when creating objects.
Currently, Django lets you designate a model field as required at the forms level (by specifying blank=False in the model). However, it doesn't seem like there is a similar option to get this behavior at the model or database level.
It does seem like there are various hacks to achieve something similar though. For example, you can set the default to something that violates a database constraint. For example, you can do things like:
models.CharField(_('characters'), max_length=4, default=None)
or
models.CharField(_('characters'), max_length=4, default="abcdef")
The former example works when saving to the database since None violates the default not-null constraint of null=False (raising an IntegrityError). The latter works because a DataError is raised when saving. But I don't know if this is guaranteed to work across all databases, etc.
Am I missing something, or is there a better way?
If django models called full_clean() automatically on save(), your check would run at the model level without a form. I've been playing with making this the default behavior in my django projects by creating an auto-clean model subclass which does full_clean() on save(), then deriving my models off that.
If you want to learn why it isn't already like this: Why doesn't django's model.save() call full_clean()?

Django Model Manager for Default Options

I have a Django model which has a foreign key that is optional. I set it up this way so that table would contain default options of different service_types but one could override this option by specifying a controller foreign key.
Now in my views I have a bunch of code that looks like this:
try:
modeService = RegressionServices.objects.get(controller=controller, service_type=SERVICE_TYPE_CONTROLLER_MODE)
except RegressionServices.DoesNotExist:
modeService = RegressionServices.objects.get(service_type=SERVICE_TYPE_CONTROLLER_MODE)
I would like to reduce this down to one call and I think that a Django model Manager should be the way to do so. Essentially it would check for the controller in **kwargs and if present it would basically do the code above. I am looking in the docs and only finding that the get_query_set method is usually being overridden. Is it okay to override the get() method? Will I even have access to the RegressionServices model in a model Manager get() method?
Can anyone think of a way to do this other than a model manager?
Just do a logical OR, using Q objects.

How do I change field or model attributes of a third-party Django app?

Let's say, I use django.contrib.flatpages, or any other third-party app in my project. I want to change some of this app's model attributes - for example, verbose_name.
How can I do that?
The simple answer is "don't"; use a proxy model instead.
It depends. If you want to add some new fields, you can create another model with OneToOneField. If you want to add some methods, ordering etc., use proxy model. If you want to change some DB restrictions (e.g. max_length) you can patch the source code of the app, but think twice before doing that, you should have a really good reason for that.
If you want to change verbose_name, you can override label in corresponding form field, no change in model needed.