1

im new to django and am trying to figure out how to add a specific field to a django model. I want to upload a csv document and save its headers. As you can see, i want to use the headers i send with the document, or if they arent send, the ones from the first line of the document.

from django.db import models

class CSV_API_DB(models.Model):
    headers = models.CharField(max_length=250, blank=True)
    delimiter = models.CharField(max_length=1, default=';')
    filefield = models.FileField(upload_to='uploads/', max_length=100, default='empty')

    actual_headers = ''

    def __str__(self):
        actual_headers = ''

        if not self.headers:
            file_path = str(self.filefield)
            file = open(file_path)
            for line in file:
                string_line = str(line[:-1])
                actual_headers = string_line.split(self.delimiter)
                break

        else:
            actual_headers = self.headers.split(self.delimiter)
        return str(actual_headers)


    true_headers = models.CharField(max_length=250, default = str(actual_headers), editable=False)

The issue seems to be, that true_headers does not get overridden from the '__ str __' function, since the values in the database for true_headers are always just empty strings.

jan biel
  • 35
  • 6
  • quick tip: It's better to use context manager to open files more secure (to be sure that there will be no unclosed file descriptors if error occurs). Read about context managers and "with open(filename) as f" – Pavel Shishmarev Nov 19 '19 at 08:27
  • I will read about context managers, thanks for the tip. – jan biel Nov 19 '19 at 16:32

1 Answers1

0

The default argument is being called during migration process, but not when you're creating new object. To provide dynamic default value you should pass a callable to default= arg.

So to provide dynamic default value, you need to pass a function that returns it instead of just string. Like this:

...
    some_field = fields.CharField(max_length=10, default=get_some_field)  # note that no () after function name

def get_some_field():
    return some_dynamic_value

But note that you can not access model instance from called function so you have to search it using YourModel.objects.get(...) if it is possible or just use other way to set dynamic value. For example, you can override save() method:

class CSV_API_DB(models.Model):
    ...
    def save(self, *args, **kwargs):
         if not self.true_headers and self._state.adding:  # _state.adding indicates that object is being created (not just edited), so we have to set default value if none provided
             self.true_headers = self.headers.split(self.delimiter)
         super().save(*args, **kwargs)
Pavel Shishmarev
  • 1,335
  • 9
  • 24
  • I will try this out in the next couple of days, thanks for your quick answer. I will report back, when i get it working. – jan biel Nov 19 '19 at 16:59
  • Have you had a result? – Pavel Shishmarev Dec 07 '19 at 16:38
  • 1
    Hey, sorry for just answering now. I was trying around and actually made a different thread and used the solution provided by someone else. I am still thankful for your help though. Here is the link (https://stackoverflow.com/questions/59181875/simple-operations-with-data-requested-from-a-django-model/59182860#59182860) – jan biel Dec 16 '19 at 10:44