Code Garden

Loadding Instance of model from serializer: can help you fix over Max Length when load data

I was migrating data from SQLite to Postgresql. After dumped data from SQLite to XML file, I change database engine to Postgresql,  then I tried to load data using 'python manage.py loaddata' command, but it raise 'too long value' error. I didn't capture the actual error message...

To made it quick, I don't want to do any code change ( add max_length validation to the form ) at that time. So I would go with a workaround script that just help me to skip one that exceed limit or cut off the string because it's not very important.

Serialization seemed to be a way to go as I can load instance of a model from XML file, edit then save to Postgresql.

As it said that max_length is 240 characters, I can see that only 'short_description' field has limit at that length. So I'll just focus on 'short_description' field.

from django.core import serializers

def load():
    listing3 = open( 'sqlite_data/listing.xml')
    listing3_data = listing3.read()
   
    des= serializers.deserialize( "xml", listing3_data )
   
    for each_des in des:
        print each_des
        #check if an object has attribute name 'short_description'
        if getattr( each_dess.object , 'short_description' , ''):
        
            if len( each_des.object.short_description) > 240:
                #Cut off text if it exceeds limit
                each_des.object.short_description =                         
each_des.object.short_description[:240]
                each_des.save()
fix_max_length.py (625 bytes) , listing3.xml (3.9 KB)

You can run the function by go to working directory. Bring up a Django shell.

python manage.py shell

Then load the function we created.

from fix_max_length import load
load()

How to get BPython working with Django

bpython is a fancy interface to the Python interpreter for Unix-like operating systems -- www.bpython-interpreter.org

I usually used interactive Python shell, but now so in love with BPython. It works very well on Mac OS X .

At first, I couldn't get Django's "python manage.py shell" to work with Bpython. I can only make it work with IPython.

But I want to use BPython so bad, so let's try to make it work with Django Environment!!

My goal is to run "bpython" in any Django project working directory and get BPython interactive shell running in Django environment. However, running "bpython" in other directorys should behave normally.

Before I made it work, I tried to run some code that relates to Django environment, to see how things fail.


In the picture below, I tried to print out "settings.INSTALLED_APPS". An error message showed up that Django environment has not been set

To fix this, first of all, you have to export the variable PYTHONSTARTUP to the system.

On Mac OS X, do it in ~/.bash_profile
on Linux, if ~/.bash_profile does not exist use ~/.profile

export PYTHONSTARTUP=~/.pythonrc

Add these lines to ~/.pythonrc

try:
     from django.core.management import setup_environ
     import settings
     setup_environ(settings)
except:
    pass
 

Make sure that you append a blank line at the end. (or it raises error like one that Ryan found)

Now load the value that you've just set -- PYTHONSTARTUP. Reopen the shell or if you don't want to exit the shell:

chanita@proteus-tech:~/testbpython$ source ~/.bash_profile


Check check check.

Voila!! It works. :D

Confusion between Form Validation and Model Validation in Django

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design-- www.djangoproject.com

Using Django Model Form can make it fast and powerful to validate input data. But new Django programmer can be confused between form validation and model validation. Both of these are defined in models.py

class Report(models.Model):
    name = models.CharField(_('Name'), max_length=20, blank=False, null=False, default=None)

When you define "null=False" and "blank=False" to the model field, let see what you will get?

"null = False", sure thing that it's gonna raise IntegrityError when you try to save but didn't assign value to the field.

"blank=False", Do you suppose that it's gonna work at model level?

If so, you will be disappointed because "blank=False" will take effect only at form level. Means that you can save the instance using the shell.

(InteractiveConsole)
>>> from report.models import Report
>>> new_report = Report()
>>> new_report.save()
>>> Traceback (most recent call last):
...
>>> IntegrityError: report_report.name may not be NULL

 Assign blank name.

>>> new_report.name = ''
>>> new_report.save()

Now you get the Report object with blank in the name field in the database!

To avoid this, let's create the helper:

from django.db import IntegrityError
def not_null_not_blank(instance, attribute_name_iter ):
    for attribute_name in attribute_name_iter:
        if not getattr(instance, attribute_name):
            raise IntegrityError('%s.%s may not be NULL or BLANK' % (instance.__class__.__name__, attribute_name )) #This line is inspired by Nattapon (@wrongite)

And override your model's save function:

class Report(models.Model):
    name = models.CharField(_('Name'), max_length=20, blank=False, null=False, default=None)
    def save(self, force_insert=False, force_update=False):
        not_null_not_blank(self,('name',  ))
        return super(Report , self).save(force_insert=force_insert, force_update=force_update)

Now exit the shell and open it again ( to reload new code you've just changed )

(InteractiveConsole)
>>> from report.models import Report
>>> another_report = Report()
>>> another_report.name=''
>>> another_report.save()
>>> Traceback (most recent call last):
...
>>> IntegrityError: Report.name may not be NULL or BLANK

Now you're good to go!! ; )

Author:

  • chanita

Archives:

Powered by Django.