whoisearth
whoisearth

Reputation: 4170

tastypie using itertools chain

For people from the future. I have scrapped tastypie and had success using Django-Rest-Framework and itertools as was suggested in the approved answer to this question.

I have a 2 models I want to link the results on as they're associated by a FK.

I've made the class in my API.py as follows -

class JobmstResource(ModelResource):
    jobdtl_id = fields.ForeignKey(JobdtlResource, 'jobdtl_id')
    class Meta:
        jobdtlquery = Jobdtl.objects.using('Admiral').all()
        jobmstquery = Jobmst.objects.using('Admiral').all()
        queryset = chain(jobdtlquery, jobmstquery)
        resource_name = 'Jobmst'

I then hit my api from the URL calling an ID (common ID in both queries).

http://localhost:8080/api/jobmst/3296/?format=xml

When I run it it fails complaining about -

'itertools.chain' object has no attribute 'model'

It seems django has no clean and clear way to do inner joins when you want results from more than 1 model so curious where the break is? Should I be attacking this differently.

If I view the query from a simple HTML it is displaying the results but does separate the values into the 2 models fields and all.

I want the values to display as if from 1 model.

Here is the models.py for the 2 models in question -

class Jobdtl(models.Model):
    jobdtl_id = models.IntegerField(primary_key=True)
    jobdtl_cmd = models.TextField(blank=True)
    jobdtl_envfile = models.TextField(blank=True)
    jobdtl_retnsn = models.SmallIntegerField(blank=True, null=True)
    jobdtl_allowadhoc = models.CharField(max_length=1, blank=True)
    jobdtl_waitop = models.CharField(max_length=1, blank=True)
    jobdtl_fromdt = models.DateTimeField(blank=True, null=True)
    jobdtl_untildt = models.DateTimeField(blank=True, null=True)
    jobdtl_fromtm = models.DateTimeField(blank=True, null=True)
    jobdtl_untiltm = models.DateTimeField(blank=True, null=True)
    jobdtl_proxy = models.ForeignKey('Usrmst', db_column='jobdtl_proxy', related_name='Jobdtl_jobdtl_proxy',blank=True, null=True)
    jobdtl_proxy2 = models.ForeignKey('Usrmst', db_column='jobdtl_proxy2', related_name='Jobdtl_jobdtl_proxy2',blank=True, null=True)
    jobdtl_interval = models.SmallIntegerField(blank=True, null=True)
    jobdtl_intervalcnt = models.SmallIntegerField(blank=True, null=True)
    jobdtl_unit = models.CharField(max_length=1, blank=True)
    jobdtl_duration = models.IntegerField(blank=True, null=True)
    jobdtl_concur = models.SmallIntegerField(blank=True, null=True)
    jobdtl_priority = models.SmallIntegerField(blank=True, null=True)
    jobdtl_minrun = models.IntegerField(blank=True, null=True)
    jobdtl_maxrun = models.IntegerField(blank=True, null=True)
    jobdtl_failalarm = models.CharField(max_length=1, blank=True)
    nodmst_id = models.ForeignKey('Nodmst', db_column='Nodmst_id', related_name='Jobdtl_Nodmst_id', blank=True, null=True)
    nodlstmst_id = models.ForeignKey('Nodlstms', db_column='Nodlstmst_id', related_name='Jobdtl_Nodlstmst_id',blank=True, null=True)
    jobdtl_inhevent = models.CharField(max_length=1, blank=True)
    jobdtl_inhoptions = models.CharField(max_length=1, blank=True)
    jobdtl_inhagent = models.CharField(max_length=1, blank=True)
    jobdtl_inhrepeat = models.CharField(max_length=1, blank=True)
    jobdtl_inhtime = models.CharField(max_length=1, blank=True)
    jobdtl_timewin = models.SmallIntegerField(blank=True, null=True)
    jobdtl_saveoutput = models.CharField(max_length=1, blank=True)
    jobdtl_outputname = models.TextField(blank=True)
    jobdtl_trackmethod = models.SmallIntegerField(blank=True, null=True)
    jobdtl_trackcmd = models.TextField(blank=True)
    jobdtl_deplogic = models.SmallIntegerField(blank=True, null=True)
    jobdtl_rerun = models.CharField(max_length=1, blank=True)
    jobdtl_params = models.TextField(blank=True) # This field type is a guess.
    jobdtl_sapcount = models.IntegerField(blank=True, null=True)
    jobdtl_normalexit = models.SmallIntegerField(blank=True, null=True)
    jobdtl_normalrange = models.SmallIntegerField(blank=True, null=True)
    jobdtl_normalop = models.SmallIntegerField(blank=True, null=True)
    jobdtl_deprerun = models.CharField(max_length=1, blank=True)
    jobdtl_carryover = models.SmallIntegerField(blank=True, null=True)
    jobdtl_psjob = models.IntegerField(blank=True, null=True)
    jobdtl_savelogonly = models.CharField(max_length=1, blank=True)
    jobdtl_trxid = models.IntegerField(blank=True, null=True)
    jobdtl_rerunok = models.CharField(max_length=1, blank=True)
    jobdtl_workdir = models.TextField(blank=True)
    jobdtl_extinfo = models.TextField(blank=True) # This field type is a guess.
    servicemst_id = models.ForeignKey('Servicemst', db_column='Servicemst_id', blank=True, null=True)
    jobdtl_estmethod = models.SmallIntegerField(blank=True, null=True)
    jobdtl_nearoutage = models.SmallIntegerField(blank=True, null=True)
    jobdtl_trackcl = models.CharField(max_length=1, blank=True)
    jobdtl_statuscl = models.CharField(max_length=1, blank=True)
    jobdtl_abrtonclderr = models.CharField(max_length=1, blank=True)
    jobdtl_estdurexclude = models.IntegerField(blank=True, null=True)
    class Meta:
        managed = False
        db_table = 'jobdtl'

class Jobmst(models.Model):
    jobmst_id = models.IntegerField(primary_key=True)
    jobmst_type = models.SmallIntegerField()
    jobmst_prntid = TreeForeignKey('self', null=True, blank=True, related_name='children', db_column='jobmst_prntid')
    jobmst_active = models.CharField(max_length=1, blank=True)
    evntmst_id = models.IntegerField(blank=True, null=True)
    jobmst_evntoffset = models.SmallIntegerField(blank=True, null=True)
    jobmst_name = models.TextField(db_column='jobmst_name', blank=True)
    jobmst_mode = models.SmallIntegerField(blank=True, null=True)
    jobmst_owner = models.ForeignKey('Owner', db_column='jobmst_owner', related_name = 'Jobmst_Jobmst_owner', blank=True, null=True)
    jobmst_desc = models.TextField(blank=True) # This field type is a guess.
    jobmst_crttm = models.DateTimeField()
    jobdtl_id = models.ForeignKey('Jobdtl', db_column='jobdtl_id', blank=True, null=True)
    jobmst_lstchgtm = models.DateTimeField(blank=True, null=True)
    jobmst_runbook = models.TextField(blank=True) # This field type is a guess.
    jobcls_id = models.IntegerField(blank=True, null=True)
    jobmst_prntname = models.TextField(blank=True)
    jobmst_alias = models.CharField(max_length=10, blank=True)
    jobmst_dirty = models.CharField(max_length=1, blank=True)
    class MPTTMeta:
        order_insertion_by = ['jobmst_id']
    class Meta:
        managed = True
        db_table = 'jobmst'

Upvotes: 0

Views: 707

Answers (2)

vincent
vincent

Reputation: 6618

Because a ResourceModel is made to allow a REST client to make queries that filter, paginate and sort, which then trigger the appropriate SQL query, it's not possible to just use an iterator which cannot be as flexible.

Maybe you can hack something that works but looks like the cleanest stuff is to use a plain Resource and add your own logic. See this answer Tastypie: How can I fill the resource without database? which refers to Resource VS ModelResource in the documentation http://django-tastypie.readthedocs.org/en/latest/resources.html#why-resource-vs-modelresource

Upvotes: 0

niekas
niekas

Reputation: 9107

Have you tried converting itertools.chain to a list:

queryset = list(chain(jobdtlquery, jobmstquery))

Update You can concatenate the queries on the same model like this:

queryset = query1 | query2

Update As the error message implies, your queryset has to have only one model. You cannot achieve your goal with two different models.

This question seems like a dublicate.

Upvotes: 1

Related Questions