Populate Data in Database Using YAML File through Fixtures in Django

645 Views Asked by At

I'm trying to populate the data in the database for the Employee Model Also, I'm not going to use Foreign Key ID's as given below

Example 1:

- model: employee.employee
  pk: 1
  fields: 
    user: 1
    manager: NULL
    department: 1
    job_level: 5
    created_at: '2021-06-03'
    updated_at: '2021-06-03'

Instead, I'm going to Use Unique values of the respective Model as given below

Example 2:

- model: employee.employee
  pk: 1
  fields: 
    user: [manager.finance]
    manager: NULL
    department: [Finance]
    job_level: [MNGR]
    created_at: '2021-06-03'
    updated_at: '2021-06-03'

models.py File

from django.db import models
from django.conf import settings
from django.db.models import Q



class TimestampedModel(models.Model):
    created_at = models.DateField(auto_now_add=True)
    updated_at = models.DateField(auto_now=True)

    class Meta:
        abstract = True


class DepartmentManager(models.Manager):
    def get_by_natural_key(self, name):
        return self.get(name=name)


class Department(TimestampedModel):
    name = models.CharField(max_length=128, unique=True)

    objects = DepartmentManager()

    class Meta:
        db_table = 'tc_departments'

    def __str__(self):
        return f'{self.name}'


class JobLevelManager(models.Manager):
    def get_by_natural_key(self, handle):
        return self.get(handle=handle)


class JobLevel(models.Model):
    handle = models.CharField(max_length=32, unique=True)
    display_name = models.CharField(max_length=64, null=True, blank=True)
    
    objects = JobLevelManager()

    class Meta:
        db_table = 'tc_job_levels'

    def __str__(self):
        return f'{self.handle} and {self.display_name}'





class EmployeeManager(models.Manager):
    def get_by_natural_key(self, user):
        return self.get(user=user)


class Employee(TimestampedModel):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
    manager = models.ForeignKey('self', on_delete=models.CASCADE,
        limit_choices_to={'manager__isnull': True}, null=True, blank=True)
    department = models.ForeignKey(Department, on_delete=models.CASCADE)
    job_level = models.ForeignKey(JobLevel, on_delete=models.CASCADE)
    profile_pic = models.ImageField(upload_to='photos/%Y/%m/%d', max_length=128,
        null=True,
        blank=True)
    
    objects = EmployeeManager()

    class Meta:
        db_table = 'tc_employees'
        unique_together = [['department', 'job_level']]

    def __str__(self):
        return f'{self.user}'


class Asset(TimestampedModel):

    class DeviceType(models.TextChoices):
        PHONE = 'PH', 'Phone'
        TABLET = 'TB', 'Tablet'
        LAPTOP = 'LP', 'Laptop'
        DESKTOP = 'DS', 'Desktop'

    device_type = models.CharField(max_length=2,
                                   choices=DeviceType.choices,
                                   default=DeviceType.LAPTOP)
    serial_number = models.CharField(max_length=32, unique=True)
    assigned_to = models.ForeignKey(Employee, on_delete=models.PROTECT)
    assigned_on = models.DateTimeField()
    returned_on = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'tc_assets'

    def __str__(self):
        return f'{self.device_type.label} serial: {self.serial_number}'

Let's consider Example 2 I'm going to populate data as like in Example 2 To do that

We can use the user field from Employee Model because the user field is unique

If I use the below YAML file I'm getting an error

Example 3:

- model: employee.employee
  pk: 1
  fields: 
    user: [manager.finance]
    manager: NULL
    department: [Finance]
    job_level: [MNGR]
    created_at: '2021-06-03'
    updated_at: '2021-06-03'
- model: employee.employee
  pk: 2
  fields: 
    user: [team_leader.finance]
    manager: [manager.finance]
    department: [Finance]
    job_level: [LEAD]
    created_at: '2021-06-03'
    updated_at: '2021-06-03'

Error

Traceback (most recent call last):
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 1823, in get_prep_value
    return int(value)
ValueError: invalid literal for int() with base 10: 'manager.finance'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/serializers/python.py", line 134, in Deserializer
    value = base.deserialize_fk_value(field, field_value, using, handle_forward_references)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/serializers/base.py", line 310, in deserialize_fk_value
    obj = default_manager.db_manager(using).get_by_natural_key(*field_value)
  File "/home/selvaganesh/models/mtest/employee/models.py", line 67, in get_by_natural_key
    return self.get(user=user)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/query.py", line 424, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/query.py", line 941, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1391, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1410, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1345, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1191, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/lookups.py", line 25, in __init__
    self.rhs = self.get_prep_lookup()
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/fields/related_lookups.py", line 117, in get_prep_lookup
    self.rhs = target_field.get_prep_value(self.rhs)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/db/models/fields/__init__.py", line 1825, in get_prep_value
    raise e.__class__(
ValueError: Field 'id' expected a number but got 'manager.finance'.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/commands/loaddata.py", line 78, in handle
    self.loaddata(fixture_labels)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/commands/loaddata.py", line 123, in loaddata
    self.load_label(fixture_label)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/management/commands/loaddata.py", line 181, in load_label
    for obj in objects:
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/serializers/pyyaml.py", line 76, in Deserializer
    yield from PythonDeserializer(yaml.load(stream, Loader=SafeLoader), **options)
  File "/home/selvaganesh/.virtualenvs/mtest/lib/python3.8/site-packages/django/core/serializers/python.py", line 136, in Deserializer
    raise base.DeserializationError.WithData(e, d['model'], d.get('pk'), field_value)
django.core.serializers.base.DeserializationError: Problem installing fixture '/home/selvaganesh/models/mtest/employee/fixtures/employee.yaml': Field 'id' expected a number but got 'manager.finance'.: (employee.employee:pk=2) field_value was '['manager.finance']'

The problem I'm facing is only because of the pk: 2, manager field in Example 3

Example 2 is working Fine

Other Foreign Key Fields user, department, job_level everything working fine

If I use manager: NULL working fine But If I use manager: [manager.fianance] I'm getting an Error

How to resolve this Problem manager: [manager.finance] Please help me out

0

There are 0 best solutions below