nuriffah
nuriffah

Reputation: 99

Django Tastypie: post value in multiple models to a single Tastypie Resource

First model:

class Profile(models.Model):

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(
                r'^[\w.@+-]+$',
                _('Enter a valid username. This value may contain only '
                  'letters, numbers ' 'and @/./+/-/_ characters.')
            ),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
   password = models.CharField(max_length=12, default='123456')
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

second model:

class UserEbiz(models.Model):
    user_id = models.ForeignKey('Profile')
    password = models.CharField(max_length=12, default='123456')

Tastypie Resource:

class ProfileResources(ModelResource):
    id = fields.CharField(attribute='id')

    class Meta:
        queryset = Profile.objects.all()
        resource_name = 'profile'

        filtering = {
            "id": ALL,
        }

I want to create a function that can save a value to both table at the same time by using only one resource. My question is how to post value into Profile and UserEbiz models using ProfileResources.

Upvotes: 5

Views: 267

Answers (2)

Satyajeet
Satyajeet

Reputation: 2044

@sean-hayes Answer is fine But if You really want to Post data on ProfileResource instead of UserEbiz first change ProfileResource to

class ProfileResource(ModelResource):
    ebiz = fields.ToManyField(UserEbizResource, 'userebiz_set', readonly=True)

Notice First that you have a ForeignKey of Profile. So it is 1:M for Profile to UserEbiz.

Second i have set readonly to true because i am going to handle UserEbiz data myself. However if You have models.ForeignKey('Profile', blank=True, null=True) then it is just like creating M2M data so just remove the readonly attribute and you are all set.

So you can override the obj_create to handle ebiz data yourself. Code might look like

def obj_create(self, bundle, **kwargs):
    ebiz = bundle.data.pop('ebiz', None)
    bundle = super(ProfileResource, self).obj_create(bundle, **kwargs)
    if not ebiz:
        return bundle

    ebiz.update(user_id=bundle.obj) # change it to user in model and here
    ebiz_res = UserEbizResource()
    ebiz_bundle = ebiz_res.build_bundle(data=ebiz)
    ebiz_res.obj_create(ebiz_bundle)
    return bundle

Upvotes: 2

Seán Hayes
Seán Hayes

Reputation: 4360

You'll want something like this:

class UserEbizResource(ModelResource):
    user_id = fields.ToOneField(ProfileResources, attribute='user_id')

    class Meta:
        queryset = UserEbiz.objects.all()
        resource_name = 'userebiz'

        excludes = ['password']
        filtering = {
            "id": ALL,
        }

Some other suggestions:

  • Rename ProfileResources to ProfileResource
  • Rename UserEbiz.user_id to UserEbiz.profile
  • Consider using Django's User model or customizing it instead of a completely custom model

Upvotes: 1

Related Questions