2

I'm using MySQL with Django and unable to see the data returned from the query executed within my model manager.

The page is rendered with the table, borders and pagination is working, however, none of the fields values are appearing in the table.

I'm guessing there is a step needed between returning the query results and presenting it in html but I'm stumped.

For context, I am setting up my manager so I can execute more sophisticated queries than what is offered with Django.

I followed some examples for using model Managers with a fairly simple query as a start - .. one of many references I have researched outside of this site: https://docs.djangoproject.com/en/dev/topics/db/managers/#custom-managers

After spending a lot of time searching I trust someone here can help. Thanks in advance!!

Here is the model manager :

class ElectionsManager(models.Manager):
def is_active(self):
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("""
                    SELECT * 
                    FROM
                        newvoterproject.fullvh vh1
                    WHERE
                    vh1.city = 'Glocester' and 
                    vh1.current_party = 'd' 
                    group by 
                        vh1.city,
                        vh1.street_name,
                        vh1.street_name_2,
                        vh1.street_number, 
                        vh1.unit
                    ;""")
    result_list = cursor.fetchall()
    return result_list

and here a snip of the model:

class Election(models.Model):
voter_id = models.CharField(primary_key=True, max_length=25)
last_name = models.CharField(max_length=50, blank=True, null=True)
first_name = models.CharField(max_length=50, blank=True, null=True)
middle_name = models.CharField(max_length=50, blank=True, null=True)
current_party = models.CharField(max_length=50, blank=True, null=True)
street_number = models.CharField(max_length=50, blank=True, null=True)
street_name = models.CharField(max_length=50, blank=True, null=True)
street_name_2 = models.CharField(max_length=50, blank=True, null=True)
unit = models.CharField(max_length=50, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
state = models.CharField(max_length=50, blank=True, null=True)
zip_code = models.CharField(max_length=50, blank=True, null=True)
zip_code_4 = models.CharField(max_length=50, blank=True, null=True)
precinct = models.CharField(max_length=50, blank=True, null=True)
status = models.CharField(max_length=50, blank=True, null=True)
objects = ElectionsManager() # model manager 

class Meta:
    managed = False
    verbose_name = 'Election'
    verbose_name_plural = 'Elections'
    db_table = 'fullvh'

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

Calling the model manager from the view:

def vhistfun(request):
election_table = Election.objects.is_active()
paginator = Paginator(election_table , 25) # Show 25 contacts per page - may want to change this to READ 25 at a time...
page = request.GET.get('page')
try:
    electpage = paginator.page(page)
except PageNotAnInteger:   
    electpage = paginator.page(1)
except EmptyPage:      
    electpage = paginator.page(paginator.num_pages)

context = {'electpage': electpage,
           }
return render(request, 'elections/electable.html', context)

.. and the html snip processing the results

    {% for elect in electpage  %}
    <tr id="voterrowclass" class=""> 
        <td> {{ elect.first_name|lower|capfirst }} </td>
        <td> {{ elect.last_name|lower|capfirst }} </td>
        <td> {{ elect.current_party}} </td>
        <td> {{ elect.street_number}} {{ elect.unit}} </td>
        <td> {{ elect.street_name|lower|capfirst}} {{ elect.street_name_2|lower|capfirst}} </td>
        <td> {{ elect.city|lower|capfirst}} </td>
    </tr> <!-- # model data sent from view -->
{% endfor %}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
catonalake
  • 44
  • 1
  • 6

2 Answers2

0

Your custom manager method isn't returning Election objects; it's returning tuples representing database rows. So you can't reference the results in your template by field name as though they were objects.

Really this is not what managers are for; your manager methods should always return querysets.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • So is there a way to convert the results to a set of iterable objects ? the query set features within django won't work for my needs. – catonalake Jan 27 '16 at 22:17
  • They are iterable; the problem is not the for loop, it's the fact that you refer to each field by name, whereas you just have a tuple of values. However you should probably be using the [`raw`](https://docs.djangoproject.com/en/1.9/topics/db/sql/#performing-raw-queries) queryset method rather than directly calling the cursor, as that does map to field names. – Daniel Roseman Jan 28 '16 at 07:24
0

Thanks for the insights.

I have made a few changes and have it working but without using a model manager (for now).

  • I removed the reference to my model manager in models.py for now - (I may add that back in later iterations / when refactoring)
  • Using a raw sql call to my database I was successful at working with the results of a fairly simple query (correct data is populating in my html - no change to html was required)

Here is the enhanced view which got things working:

def vhistfun(request):
election_table = Election.objects.raw("""
                SELECT *
            FROM
                newvoterproject.fullvh vh1
            WHERE
                vh1.city = 'Glocester'
                    AND (vh1.current_party = 'r' or vh1.current_party = 'u') 
                    GROUP BY vh1.city , 
                    vh1.street_name ,  
                    CONVERT(SUBSTRING_INDEX(vh1.street_number,'-',-1),UNSIGNED INTEGER)  , 
                    vh1.unit
            ;
                    """)
party_list=('r','u')
town_list=('Glocester')
query_information ='Voters in the 2012 Presidential Election (election_3) and either the 2008 Presidential Election (election_8)or the 2012 Presidential Primary (election_5)'

paginator = Paginator(list(election_table), 10) # NOTE > this was changed from paginator = Paginator(election_table , 25)
page = request.GET.get('page')
try:
    electpage = paginator.page(page)
except PageNotAnInteger:      
    electpage = paginator.page(1)
except EmptyPage:     
    electpage = paginator.page(paginator.num_pages)

context = {'electpage': electpage,
           'party_list': party_list,
           'town_list': town_list,
           'query_information ': query_information
           }
return render(request, 'elections/electable.html', context)

Just a note/ caution - using objects.raw caused this issue with pagination:

object of type 'int' has no len()

I found out how to fix it here: Django paginator and raw SQL

for now i'm getting my table populated with data and will proceed to more advanced queries I will need for my project....

I am leaving this question unanswered for now. While I was successful at getting the data I require using raw, it does not address the question asked - why a query in a model manager is not presenting the data correctly on the html...

Community
  • 1
  • 1
catonalake
  • 44
  • 1
  • 6