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

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.

Related

Django error: Value too long for type character varying(2)

I did a database flush to reset my database. I am getting this error when I try to do the following code.
Code that throws error:
try:
print("Attempting to load %s" % store.get('name'))
# THIS NEXT LINE THROWS ERROR
store_obj = Store.objects.get(name=store.get('name'))
except Store.DoesNotExist:
store_obj = Store(name=store.get('name'),
last_updated=last_updated,
address=store.get('address'),
city=store.get('city'),
state=store.get('state'),
zip_code=store.get('zip_code'))
Error:
Exception Type: DataError at /stores/
Exception Value: value too long for type character varying(2)
\d of stores_store
Model in django:
class Store(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_updated = models.DateTimeField(default=datetime.now, blank=True)
# Address
address = models.CharField(_("address"), max_length=128)
city = models.CharField(_("city"), max_length=128)
state = USStateField(_("state"))
zip_code = USZipCodeField(_("zip code"), max_length=5)
def __str__(self):
return self.name
As you can see the store name is a VARCHAR of 200, not 2. However, I cannot complete this get operation without getting this error. I tried another flush and makemigrations -> migrate but still have no luck. What else can I try?
Thanks!
the column "state" has USStateField(_("state")) which I assume is varying(2), are you trying to add a tuple which state is bigger than varying(2)?
I can suggest you to change the USStateField(_("state")) to a CharField or to put a max_length.
If that doesn't work you can try to delete the migrations history to make them again. Inside the app folder in migrations delete all the files that look like 0001_initial.py, don't delete the init.py inside the migrations folder, hope it helps :D
Go to your migrations file and track the value stated in the error within those files and increase the value to match it with the one in your models.py file and your database

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.

Django Custom Primary Key Tries to insert Null

There are some constraints to this problem. We currently use a production database, with live Virtual Machine Statistics. We are trying to create a django interface, that interfaces with the tables we want our administrators to be able to edit. Thus, migrations are out of the question, for unless I have come to understand migrations wrong it will affect the current database structure and or data.
I matched the database structure exactly in my models.py file. However I have run into a few issues. One of the issues I have run into is when I try to add a new item under the admin control panel it will give me an integrity error as it is attempting to insert a null value for the field I have set as the primary key in the models.py file.
We are currently using an oracle database.
My Models.py not all of it but a sample of it.
class License(models.Model):
license_id = models.AutoField(primary_key = True, editable = False, db_column='license_id')
license_authority_id = models.ForeignKey(License_authoritie, on_delete = models.PROTECT, db_column='license_authority_id')
product = models.CharField(max_length = 20)
class Meta:
managed = False
db_table = 'licenses'
ordering = ['product']
def __unicode__(self): # Python 3: def __str__(self):
return self.product
class Vm_license(models.Model):
vm_license_id = models.AutoField(primary_key = True, db_column='vm_license_id')
vm_id = models.ForeignKey(Vm, on_delete = models.PROTECT, db_column='vm_id')
license = models.ManyToManyField(License)
class Meta:
managed = False
db_table = 'vm_licenses'
The error I get:
Request Method: POST
Request URL: http://127.0.0.1:8000/admin/portal/vm_license/add/
Django Version: 1.6.5
Exception Type: IntegrityError
Exception Value:
ORA-01400: cannot insert NULL into ("DEV"."VM_LICENSES"."VM_LICENSE_ID")
On top of that I have run into another problem.
For these two tables, under the vm_licenses section in the admin panel which is a table that holds all VM's and their assigned licenses. I need the ability to select multiple licenses at a time for each vm_id under the add section of the admin panel but i'm not quite sure how to do this.
admin.py code
class vm_license_admin(admin.ModelAdmin):
#list_display = ('vm_id', 'license_id')
list_display = ('vm_id',)
search_fields = ('vm_id__vm_name',)
ordering = ('vm_id',)
filter_horizontal = ('license',)
admin.site.register(Vm_license, vm_license_admin)
I also made an oracle trigger to auto increment a primary key if there is none, but im still getting the same error.
CREATE OR REPLACE TRIGGER license_trigger
BEFORE INSERT ON vm_licenses
FOR EACH ROW
BEGIN
SELECT vm_license_seq.nextval
INTO :new.vm_license_id
FROM dual;
END;
to be more percise I am using a manytomany field and it displays correctly when I goto add a new item before clicking save and getting the null error, however if I goto an existing item it will say table or view doesnt exist.
I was going to comment on your question, but I do not have the reputation yet...
but can I suggest you post your relevant admin.py code? Perhaps there is something within it relating to the Null PK error.
With regards to the second part, a ManyToManyField sounds more suitable.

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/RapidSMS Foreignkey not a column in table

so I'm working with RapidSMS which builds on Django and I'm trying to sort of combine their tutorials specifically the poll app in django and thevoting app in rapidsms I started with voting and was trying to expand it using code from the django tutorial when I ran into trouble.
(I'm using python27 on a Windows7 64bit, Django 1.5, and SQLite3) Here's what I have in voting.models
from django.db import models
from django.utils import timezone
# Create your models here.
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
poll = models.ForeignKey(Poll)
name = models.CharField(max_length=40, unique=True)
votes = models.IntegerField(default=0)
def __unicode__(self):
return self.name
The poll part shows up fine on admin, I can the question and date, but when I try to add a choice, or touch choices at all I get the error "table voting_choice has no column named poll_id"
I added poll = models.ForeignKey(Poll) after I had made a table for Choice, which I thought might be the problem after some research (maybe it still is) I got the impression that the tables weren't being written over. So this is what I did :
>manage.py sqlclear voting
BEGIN;
DROP TABLE "voting_choice";
DROP TABLE "voting_poll";
COMMIT;
>manage.py sql voting
BEGIN;
CREATE TABLE "voting_poll" (
"id" integer NOT NULL PRIMARY KEY,
"question" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL
)
;
CREATE TABLE "voting_choice" (
"id" integer NOT NULL PRIMARY KEY,
"poll_id" integer NOT NULL REFERENCES "voting_poll" ("id"),
"name" varchar(40) NOT NULL UNIQUE,
"votes" integer NOT NULL
)
;
COMMIT;
So it /says/ that it has that column here. I then syncdb, migrate for good measure and runserver, or the shell and either way entering a poll question/date is fine, but once I try to add a choice or look at a created poll, I get the above mentioned error.
Voting is definitely included in INSTALLED_APPS. So being a Django newbie, I'm lost. If anyone has more suggestions to try they would be very much appreciated.
Thanks,
Lizzy
What manage.py sql voting says is the SQL that wold be generated if Django was going to create the tables. It does not output the current state of the tables nor does it apply the SQL that it outputs. Likewise manage.py sqlclear voting shows the SQL to clear the tables but does not apply it to the database.
I added poll = models.ForeignKey(Poll) after I had made a table for Choice...
There is your problem. syncdb does not alter existing tables. You need to either alter the table yourself or drop and have Django recreate it (if you don't have any data worth keeping).