mbogh
mbogh

Reputation: 1361

Tastypie ManyToManyField giving 401 on post/patch/put

I think I'm going mad, so please help me understand this.

My model:

class UserManager(BaseUserManager):
    def create_user(self, email, password, first_name, last_name, year_of_birth, city, gender, country):
        if not email:
            raise ValueError('Users must have an email address')
        if not password:
            raise ValueError('Users must have a password')
        if not first_name:
            raise ValueError('Users must have a first name')
        if not last_name:
            raise ValueError('Users must have a last name')
        if not year_of_birth:
            raise ValueError('Users must have an year of birth')
        if not city:
            raise ValueError('Users must have a city')
        if not gender:
            raise ValueError('Users must have a gender')

        user = self.model(
            email=UserManager.normalize_email(email),
            first_name=first_name,
            last_name=last_name,
            year_of_birth=year_of_birth,
            city=city,
            gender=gender,
            country=country
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password, first_name, last_name, year_of_birth, city, gender, country):
        user = self.create_user(email,
            password=password,
            first_name=first_name,
            last_name=last_name,
            year_of_birth=year_of_birth,
            city=city,
            gender=gender,
            country=country
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

class Tent(models.Model):
    name = models.CharField(max_length=255)
    brand = models.CharField(max_length=255)
    def __unicode__(self):
        return self.name

GENDER_MALE = 0
GENDER_FEMALE = 1
GENDER_NOT_SPECIFIED = 2

GENDER_CHOICES = (
    (GENDER_MALE, _('male')),
    (GENDER_FEMALE, _('female')),
    (GENDER_NOT_SPECIFIED, _('not specified')),
)

class User(AbstractBaseUser):
    email = models.EmailField(max_length=255, unique=True)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    year_of_birth = models.IntegerField()
    country = models.CharField(max_length=255)
    city = models.CharField(max_length=255)
    gender = models.IntegerField(choices=GENDER_CHOICES, default=GENDER_NOT_SPECIFIED)
    newsletter = models.BooleanField(default=False)

    tents = models.ManyToManyField(Tent, blank=True, null=True)

    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = UserManager()

    def get_full_name(self):
        return '%s %s' % self.first_name, self.last_name

    def get_short_name(self):
        return self.first_name

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.is_admin

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'year_of_birth', 'city', 'country', 'gender']

My model resources:

class TentResource(ModelResource):
    class Meta:
        queryset = Tent.objects.all()
        resource_name = 'tents'
        allowed_methods = ['get']

class UserResource(ModelResource):
    tents = ManyToManyField(TentResource, 'tents', null=True)

    class Meta:
        queryset = User.objects.all()
        allowed_methods = ['post', 'get', 'patch', 'put']
        excludes = ['password', 'is_active', 'is_admin', 'id', 'last_login']
        resource_name = 'user'
        authentication = ApiKeyAuthentication()
        authorization = Authorization()

    def obj_create(self, bundle, **kwargs):
        try:
            bundle = super(UserResource, self).obj_create(bundle, **kwargs)
            bundle.obj.set_password(bundle.data.get('password'))
            bundle.obj.save() 
        except IntegrityError:
            raise BadRequest(_("A user with that username already exists."))
        return bundle

    def authorized_read_list(self, object_list, bundle):
        return object_list.filter(id=bundle.request.user.id)

I can easily POST data to my endpoint and create a users as long as I do not include tents, so the following works fine:

{
  "year_of_birth" : 1986,
  "newsletter" : false,
  "first_name" : "Morten",
  "city" : "Aalborg",
  "last_name" : "Bøgh",
  "country" : "Denmark",
  "gender" : 1,
  "email" : "[email protected]",
  "password" : "1234"
}

But if I add tent info I simply get a 401 and no reason.

{
  "year_of_birth" : 1986,
  "newsletter" : false,
  "tents" : [
    "/v1/tents/3/",
    "/v1/tents/4/"
  ],
  "first_name" : "Morten",
  "city" : "Aalborg",
  "last_name" : "Bøgh",
  "country" : "Denmark",
  "gender" : 1,
  "email" : "[email protected]",
  "password" : "1234"
}

Without any error message I'm kinda lost here, hope you girls and guys can help me.

Cheers Morten

Update

Changed my Tent resource to:

class TentResource(ModelResource):
    class Meta:
        queryset = Tent.objects.all()
        resource_name = 'tents'
        allowed_methods = ['get', 'post', 'patch']
        authentication = ApiKeyAuthentication()
        authorization = Authorization()

Upvotes: 0

Views: 322

Answers (1)

Stefan Strijker
Stefan Strijker

Reputation: 81

In your tent meta you have:

allowed_methods = ['get']

Posting a tent is thereby not allowed. Add 'post' to the allowed methods.

Upvotes: 1

Related Questions