charles-vdulac / django-roa

Fork of original Django ROA lib. Now ROA works directly with an API like Django Rest Framework
BSD 3-Clause "New" or "Revised" License
51 stars 25 forks source link

How to make a relation between a local and remote Model #21

Open fxdgear opened 10 years ago

fxdgear commented 10 years ago

In your DRF example you have frontend and backend apps.

In each, you are defining the models for "Articles" "Tags" etc...

But if for example there was a model in the front end, and you wanted to create a relationship to the "backend" between the two, how would you handle this?

JocelynDelalande commented 10 years ago

@fxdgear You can use a custom ForeignKeyField class.

Eg:

class CrossDbForeignKey(models.ForeignKey):
    def validate(self, value, model_instance):
        if self.rel.parent_link:
            return
        super(models.ForeignKey, self).validate(value, model_instance)
        if value is None:
            return

        # Here is the trick, get db relating to fk, not to root model
        using = router.db_for_read(self.rel.to, instance=model_instance)

        qs = self.rel.to._default_manager.using(using).filter(
                **{self.rel.field_name: value}
             )
        qs = qs.complex_filter(self.rel.limit_choices_to)
        if not qs.exists():
            raise exceptions.ValidationError(self.error_messages['invalid'] % {
                'model': self.rel.to._meta.verbose_name, 'pk': value})

It can be used like:

class Membership(models.Model):
    member = CrossDbForeignKey(LdapUser)

I originally wrote this code to reference LDAP models from regular (db) model. More details in this article (in french, sorry).

But you have to be careful, you loose referential integrity.