materialAres
materialAres

Reputation: 47

Django error: ValueError: Cannot assign "(<Category: Cultural>, True)": "Site.category" must be a "Category" instance

I need to create a database importing data from a csv file. Following the instructions of the exercise, I created the models and a file for the script, but when I run the command python manage.py runscript many_load it gives me the error in the title. Here's the code:

- models.py:

from django.db import models


class Category(models.Model):
    category = models.CharField(max_length=128)

    def __str__(self):
        return self.category

class State(models.Model):
    state = models.CharField(max_length=25)

    def __str__(self):
        return self.state


class Region(models.Model):
    region = models.CharField(max_length=25)

    def __str__(self):
        return self.region

class Iso(models.Model):
    iso = models.CharField(max_length=5)

    def __str__(self):
        return self.iso

class Site(models.Model):
    name = models.CharField(max_length=128)
    year = models.CharField(max_length=128)
    area = models.CharField(max_length=128)
    describe = models.TextField(max_length=500)
    justify = models.TextField(max_length=500, null=True)
    longitude = models.TextField(max_length=25, null=True)
    latitude = models.TextField(max_length=25, null=True)

    #one to many field
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    state = models.ForeignKey(State, on_delete=models.CASCADE)
    region = models.ForeignKey(Region, on_delete=models.CASCADE)
    iso = models.ForeignKey(Iso, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

- many_load.py:

import csv

from unesco.models import Site, Category, Iso, Region, State


def run():
    fhand = open('unesco/whc-sites-2018-clean.csv')
    reader = csv.reader(fhand)
    next(reader)

    Category.objects.all().delete()
    Iso.objects.all().delete()
    Region.objects.all().delete()
    State.objects.all().delete()

    Site.objects.all().delete()

    for row in reader:
        # print(row)
        # print (len(row))

        name = row[0]
        describe = row[1]
        justification = row[2]
        year = row[3]
        longitude = row[4]
        latitude = row[5]
        area = row[6]

        category = Category.objects.get_or_create(category=row[7])
        state = State.objects.get_or_create(state=row[8])
        region = Region.objects.get_or_create(region=row[9])
        iso = Iso.objects.get_or_create(iso=row[10])

        st = Site(category=category, state=state, region=region, iso=iso,
                  name=name, area=area, describe=describe, year=year, justification=justification,
                  longitude=longitude, latitude=latitude)
        st.save()

I must admit that I didn't understand very well the whole process of importing, so I cannot figure out how to look.. if you can explain to me it would be appreciated. Thanks in advance!

Upvotes: 0

Views: 313

Answers (1)

Yevhen Bondar
Yevhen Bondar

Reputation: 4707

get_or_create method returns tuple of two elements:

Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.

So, you need to unpack tuples to extract models

category, _ = Category.objects.get_or_create(category=row[7])
state, _ = State.objects.get_or_create(state=row[8])
region, _ = Region.objects.get_or_create(region=row[9])
iso, _ = Iso.objects.get_or_create(iso=row[10])

st = Site(category=category, state=state, region=region, iso=iso,
                  name=name, area=area, describe=describe, year=year, justification=justification,
                  longitude=longitude, latitude=latitude)

Single underscore _ variable in Python is often used as "throwaway" variable name, as described here

Upvotes: 5

Related Questions