Django model: NULLable field - django

I'm working on a django project where I need a DateField to sometimes be empty. My model looks like this:
#models.py
end = models.DateField(default=None, blank=True)
But when I run python manage.py sql myapp the sql statement always end up being
CREATE TABLE "myapp_date" (
"end" date NOT NULL
);
Therefore my field isn't nullable and I can't understand what I should do to make it so. Any idea would be appreciated !

You should use
end = models.DateField(default=None, blank=True, null=True)
Basically blank allows you to pass it a null value, but null tells the database to accept null values.

Related

Django hitcount order_by("hit_count_generic__hits") gives error on PostgreSQL database

I was using django-hitcont to count the views on my Post model. I am trying to get the most viewed post in my ListView using this query objects.order_by('hit_count_generic__hits') and it is working fine on SQLite but on PostgreSQL, it is giving me this error :
django.db.utils.ProgrammingError: operator does not exist: integer = text LINE 1: ...R JOIN "hitcount_hit_count" ON ("posts_post"."id" = "hitcoun....
models.py
class Post(models.Model, HitCountMixin):
author = models.ForeignKey(User, related_name='authors', on_delete=models.CASCADE)
title = models.CharField('Post Title', max_length = 150)
description = models.TextField('Description', max_length=1000, blank = True)
date_posted = models.DateTimeField('Date posted', default = timezone.now)
date_modifed = models.DateTimeField('Date last modified', default = timezone.now)
document = models.FileField('Document of Post', upload_to='documents', \
validators=[FileExtensionValidator(allowed_extensions = ['pdf', 'docx']), validate_document_size] \
)
hit_count_generic = GenericRelation(
HitCount,
object_id_field='object_pk',
related_query_name='hit_count_generic_relation'
)
views.py
queryset = Post.objects.order_by('hit_count_generic__hits')
I found this issue on Github related to the problem, but I am still not able to figure out the mentioned workaround.
When comparing different types (in this example integer and text), equals operator throws this exception. To fix that, convert HitCount model pk field to integer and you are good to go. To do that, you need to create and apply migration operation. Django is a really good framework to handle this kind of operations. You just need to check values are not null and are "convertable" to integer. Just change the field type and run two commands below.
python manage.py makemigrations
python manage.py migrate
Before updating your model, I highly recommend you to take a backup in case of failure. This is not an easy operation but you can follow the these links to understand what is going on during this the process.
migrations dump and restore initial data
If you don't care the data on table, just drop table and create a brand new migration file and recreate table.

Django Many to Many migration can't insert null into id

I'm trying to migrate a column from a Char field to a Many-to-Many field running Django 1.8.2. I'm doing a custom Data Migration, to move the data properly. When I try to migrate, I get a database error, can't insert null into the many to many table id column.
My models, simplified:
class LicenseArea(models.Model):
#appraisal_account = models.CharField(max_length=17, null=True, db_index=True)
appraisal_account = models.ManyToManyField(TaxAccount, db_table='LicAreaTaxAccount', related_name='accounts_for_license_area', related_query_name='license_area_for_account', null=True)
class TaxAccount(models.Model):
account = models.CharField(max_length=17, db_index=True)
So I first create TaxAccount objects in a RunPython block, then remove the old field and add the new one, like so:
migrations.RunPython(create_tax_account_objects),
migrations.RemoveField(
model_name='licensearea',
name='appraisal_account',
),
migrations.AddField(
model_name='licensearea',
name='appraisal_account',
field=models.ManyToManyField(related_query_name='license_area_for_account', related_name='accounts_for_license_area', db_table='licenses_LicAreaTaxAccount', to='licenses.TaxAccount'),
),
All that works. My issue comes when I try to migrate the data, relating the LicenseArea object with its corresponding TaxAccount object. In another RunPython block, I try the code shown below (I've tried in both directions; acct.licensearea_set.add indicates that the TaxAccount model has no licensearea_set attribute, while the second option shown below gives me the IntegrityError (ORA-01400) that I can't insert null into the ID column :
for la in LicenseArea.objects.all():
acct = TaxAccount.objects.get(account=la.appraisal_account_temp)
#acct.licensearea_set.add(la)
#la.appraisal_account.add(acct)
How do I solve this? Thanks in advance.

How do I replace the null element in django model

I have a model as such:
actual = models.IntegerField(default=0)
What I want to do is tell the model that whenever it null, I want the integer to be 0. How would I do so. I tried the following
actual = models.IntegerField(default=0, null=0)
This did not work.
actual = models.IntegerField(default=0)
will allow for the model to not be null while giving it default of 0.
The Django documentation states that when the null field option is "True, Django will store empty values as NULL in the database. Default is False."
So, by default this should work.
actual = models.IntegerField(default=0)
Source:
https://docs.djangoproject.com/en/1.7/ref/models/fields/

django skip a field's validation

I need to skip validation of the OrderAmount field but for it to still save the invalidated data. Is there a way this can be done? I know django allows you to make your own validation, but I don't know how to make it completely skip just one field's validation.
model:
class LiquorOrder(models.Model):
pack_size = (
('1', '1'),
('2', '2'),
)
LiquorOrderID = models.AutoField(primary_key=True)
storeliquorID = models.ForeignKey(StoreLiquor)
orderID = models.ForeignKey(Order)
OrderAmount = models.PositiveSmallIntegerField('Order Amount', max_length=3, choices=pack_size)
TotalPrice = models.DecimalField('Total Price', max_digits=5, decimal_places=2)
Form:
class AddToOrderForm(forms.ModelForm):
class Meta:
model = LiquorOrder
fields = ('OrderAmount',)
For a PositiveSmallIntegerField the only validation Django does is ensure the value is indeed a positive integer within the appropriate range. If you were to skip this, you would run into problems when Django tries to write the value to your database. If you were to, say, try to write the value "marshmallows" to a DB column that's expecting an integer, the DB will throw errors and Django will turn around and throw you an IntegrityError.
If you really wanted to try, you could override the field to be CharField with required set to False (basically allowing any keyboard input):
class AddToOrderForm(forms.ModelForm):
OrderAmount = forms.CharField(required=False)
Django would then return True when you run is_valid(), but throw errors when you try to call save().
It sounds like your real issue is with your model not matching your current project requirements. If that is the case, look into migrating to a new model. The Python library South is brilliant tool for this purpose and is used heavily by the Django community. I would read up on DB migrations and see if you can come up with a solution that way.

django recursive relationships

My DjangoApp is using categories to generate a navigation and to put stuff in those categories.
There are two types of categories:
ParentCategories (top categories)
ChildCategories (sub categories that have a ParentCategory as a parent)
Because those to categories are so similar I don't want to use two different models.
This is my category model:
class Category(models.Model):
name = models.CharField(max_length=60)
slug = models.SlugField(max_length=80, blank=True)
is_parent = models.BooleanField()
parent = models.ForeignKey('self', null=True, blank=True)
In my djangoadmin the parent won't be represented.
If I use python manage.py sql I get:
CREATE TABLE "catalog_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(60) NOT NULL,
"slug" varchar(80) NOT NULL,
"is_parent" bool NOT NULL
)
;
So the parent relationship won't even be created.
Is there a handy way of fixing this?
I know I could just alter the table but I'm flushing/deleting the database quite a lot because the app changes rapidly and I don't want to alter the table everytime manually.
btw: my dev db is of course sqlite3.
On the server we'll use postgresql
Something else is going on - that definition of parent is fine. If I run manage.py sql on an app with that model copy-pasted in, I get:
BEGIN;
CREATE TABLE "bar_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(60) NOT NULL,
"slug" varchar(80) NOT NULL,
"is_parent" bool NOT NULL,
"parent_id" integer
)
;
COMMIT;