3
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?

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.