Reputation: 71
url.py
router.register(r'Costumers', CostumerViewSet, base_name='costumer')
.register(r'Agreements', AgreementViewSet, base_name='agreement', parents_query_lookups=['costumer']).
.register(r'Programs', ProgramViewSet,base_name='programs',parents_query_lookups=['agreement']),
model.py
class Costumer(models.Model):
company_name = models.CharField(max_length=300)
supplier = models.ForeignKey(Supplier)
class Agreement(models.Model):
agreement_name = models.CharField(max_length=300)
programs = models.ManyToManyField(Program, through='Programs_in_Agreement')
costumer = models.ForeignKey(Costumer)
class Program(models.Model):
program_name = models.CharField(max_length=300)
class Programs_in_Agreement(models.Model):
programs = models.ForeignKey(Program)
agreement = models.ForeignKey(Agreement)
Im trying to get this page
/api/v1/Costumers/1/Agreements/1/Programs/
and I've got this error
"^Costumers/(?P<parent_lookup_agreement>[^/.]+)/Agreements/(?P<parent_lookup_agreement>[^/.]+)/Programs/$" is not a valid regular expression: redefinition of group name 'parent_lookup_agreement' as group 2; was group 1
the relation between Programs and Agreements is M2M and the relation between Agreement and costumer is M21 can somone help me please?
Upvotes: 3
Views: 1511
Reputation: 41671
You are nesting the routers, which means you are using one of the nested router plugins. The problem is that you are not providing all of the lookup fields for the last register
call.
The relationship that it looks like you are trying to achieve is
Program -> Agreement -> Costumers
And the routers are generating
Costumers
Agreement -> Costumers
Program -> Agreement -> Costumers
Where the ->
signals the lookup that is being made. The lookup must manually be provided when registering by passing in parents_query_lookups
. This is important, as otherwise the plugin has to guess what the lookup is, and it's bound to be wrong. The lookups are not maintained across nestings of the routers, so a lookup defined on router A will not be passed down to router B, it must be repeated on router B as well.
So what you should be doing when registering the router is passing in the parent lookup. The snippet below should work:
router.register(r'Costumers', CostumerViewSet, base_name='costumer')
.register(r'Agreements', AgreementViewSet, base_name='agreement', parents_query_lookups=['costumer']).
.register(r'Programs', ProgramViewSet, base_name='programs', parents_query_lookups=['agreement__costumer', 'agreement'])
Note the addition of agreement__costumer
in the parents_query_lookups
for the last call. This allows the plugin to fill in the lookup field for that part of the URL, preventing duplicated groups from showing up.
Upvotes: 4