Django Reversion - Viewing incompatible version data - django

Is there a way to view incompatible version data using Django-Reversion or after making a change to the model? I understand I wouldn't be able to revert or reinstate a previous version before the model change, but is there a way to simply view the data?
Here's the model before the change:
class Product(models.Model):
product_code = models.CharField(max_length=120, blank=True, null=True) #max_length=required
related_category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, blank = True, null=True)
Then I added a 'discount' field:
class Product(models.Model):
product_code = models.CharField(max_length=120, blank=True, null=True) #max_length=required
related_category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, blank = True, null=True)
discount = models.BooleanField()
when I try to access previous versions, I see an error - "Could not save XXXXX version - missing dependency."
I tried accessing previous versions via admin site and also by calling Version.objects.get_for_model(Product). I was expecting to be able to view the historical versions, but instead I get an error (missing dependency).

Related

django multilevel nested formsets

django provide inline formset which allow to 3rd level of nesting, but I need much more complex nesting. It should be fully dynamic, so I can go one to one on each level, but it could be one to many on each level. So far I have this only, but could be expanded for additional sublevels.
class Srts(models.Model):
data = models.CharField(max_length=10, blank=True, null=True)
class Volume(models.Model):
srts = models.ForeignKey('Srts', on_delete=models.CASCADE)
name = models.CharField(max_length=120, blank=True, null=True)
class Qtree(models.Model):
volume = models.ForeignKey('Volume', on_delete=models.CASCADE)
name = models.CharField(max_length=120)
class Server(models.Model):
qtree = models.ForeignKey('Qtree', on_delete=models.CASCADE)
hostname = models.CharField(max_length=120, blank=True, null=True)
class CifsPermission(models.Model):
qtree = models.ForeignKey('Qtree', on_delete=models.CASCADE)
group = models.CharField(max_length=30, blank=True, null=True, default='None')
permission = models.CharField(max_length=30, blank=True, null=True, default='None')
I have been googling a lot last days, but there is not much.
Some examples
django-nested-inline-formsets-example -that basic only 3rd level
Django-better forms -could handle multiple forms on one submit, but not formsets
django-nested-inline -only for admin page
Shoudl be the way to work with not model related form , then do some separation and appropriate logic and then save it to models?
can't add image, some sever error ocured, so giving the link directly
https://imgur.com/a/NQBR6tJ
I would like to to something simular over normal view, not admin view.

Django fetch related child with parent object

I am using Django 2.2 and I have a model with two classes Product and ProductRevision. When I retrieve a Product, or a list of Products, I always fetch the corresponding ProductRevision. ProductRevision objects are incremented and only the last revision should be fetched with the Product.
class Product(models.Model):
name = models.CharField(max_length=50, null=False, blank=False,
verbose_name=_("name"))
product_code = models.CharField(max_length=10, null=False, blank=False,
verbose_name=_("product code"))
slug = models.SlugField(null=False, unique=True)
#property
def current_item(self):
return ProductRevision.objects.filter(product=self, active=True).order_by('-version').first()
class ProductRevision(models.Model):
product = models.ForeignKey(Product, null=True, on_delete=models.PROTECT)
version = models.IntegerField(default=0,
verbose_name=_("version"))
active = models.BooleanField(default=False, null=False, blank=True,
verbose_name=_("is active"))
qty_close = models.IntegerField(default=0,
verbose_name=_("qty of accounts to be closed"))
price_eur = models.DecimalField(max_digits=6, decimal_places=2, default=0,
verbose_name=_("price in EUR"))
I tried to add a property current_item to get the last revision of a given product. While this is working, it is very inefficient because when I use it in a template, it hits the database every time I display a field from the related ProductRevision.
I found this answer based on an old version of Django (Fetch latest related objects in django) and I'm wondering if there is no other ways to achieve the same result with current versions of Django? I'm particularly interrested in achieving this in my models.
I have managed to achieve something similar to this by using a custom prefetch related queryset
products = Product.objects.prefetch_related(Prefetch(
'productrevision_set',
queryset=ProductRevision.objects.order_by('product', '-version').distinct('product'),
to_attr='latest_revision'
))
The queryset above will only return one ProductRevision per Product which in effect gives us the latest ProductRevision for all Products in only 2 queries
for product in products:
for latest_revision in product.latest_revision:
print(product, latest_revision)

Django and Pipelinedb: Programming Error: column <database_name>.location_id does not exist

I'm working on a project using Django and postgresdb with streaming data coming in using pipelinedb. A sync script is running this. Everything is Dockerized.
The data is updated every 60 seconds on the test server.
I added this field to the model:
location = models.ForeignKey('Location', related_name='assigned_sensor', on_delete=models.CASCADE, null=True)
And for reference, here are both the Weather and Location models:
class WeatherStatsMrel(models.Model):
id = models.BigIntegerField(db_column='$pk', primary_key=True)
loc = models.CharField(max_length=3, null=True)
dat = models.DateField(blank=True, null=True, editable=True)
tim = models.TimeField(blank=True, null=True, editable=False)
aws = models.FloatField(blank=True, null=True, editable=False)
awd = models.TextField(blank=True, null=True, editable=False)
mws = models.FloatField(blank=True, null=True,editable=False)
mwd = models.TextField(blank=True, null=True,editable=False)
tmp = models.FloatField(blank=True, null=True,editable=False)
hum = models.FloatField(blank=True, null=True,editable=False)
r10 = models.FloatField(blank=True, null=True,editable=False)
r60 = models.FloatField(blank=True, null=True,editable=False)
rda = models.FloatField(blank=True, null=True,editable=False)
rcu = models.TextField(blank=True, null=True,editable=False)
rad = models.TextField(blank=True, null=True,editable=False)
sun = models.TextField(blank=True, null=True,editable=False)
location = models.ForeignKey('Location', related_name='assigned_sensor', on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'weather_stats_mrel'
def __unicode__(self):
return str({self.loc}, {self.dat}, {self.tim}, {self.aws}, {self.awd}, {self.mws}, {self.mwd}, {self.tmp}, {self.hum}, {self.r10}, {self.r60}, {self.rda}, {self.rcu}, {self.rad}, {self.sun})
class Location(models.Model):
id = models.AutoField(primary_key=True)
abbreviated_name = models.CharField(max_length=3)
full_name = models.CharField(max_length=25)
def __str__(self):
return self.abbreviated_name
When I start up the server, everything is fine. Through the admin page (Django's default admin page) I can navigate to the weather_stats_mrel page in an attempt to view the data coming in.
Once Pipelindb updates the table, however, I get this error when I try to view the page:
ProgrammingError at /admin/test_sensor_app/weatherstatsmrel/
column weather_stats_mrel.location_id does not exist
LINE 1: ...er_stats_mrel"."rad", "weather_stats_mrel"."sun", "weather_s...
^
Request Method: GET
Request URL: http://localhost:8000/admin/test_sensor_app/weatherstatsmrel/
Django Version: 2.1.1
Exception Type: ProgrammingError
Exception Value:
column weather_stats_mrel.location_id does not exist
LINE 1: ...er_stats_mrel"."rad", "weather_stats_mrel"."sun", "weather_s...
^
From what I understand, Django should be adding this field automatically, right? Or do I now need to add this table manually? Where would I put it in the model?
I've never had this problem before when using ForeignKeys, but then again, this is the first time I'm working with tables that are pre-generated before Django even touches it.
Is there a work-around for this problem? Has anyone even run into this before?
It looks like you have a continuous view named weather_stats. It is not possible to add columns to an existing continuous view, so unless you included location_id in the continuous view's definition, that column won't be there.

Django ForeignKey TemplateSyntaxError and ProgrammingError

This is are my models i want to relate. i want for collection to appear in the form of occurrence.
class Collection(models.Model):
id = models.AutoField(primary_key=True, null=True)
code = models.CharField(max_length=100, null=True, blank=True)
address = models.CharField(max_length=100, null=True, blank=True)
collection_name = models.CharField(max_length=100)
def __unicode__(self):
return self.collection_name
class Meta:
db_table = u'collection'
ordering = ('collection_name',)
class Occurrence(models.Model):
id = models.AutoField(primary_key=True, null=True)
reference = models.IntegerField(null=True, blank=True, editable=False)
collection = models.ForeignKey(Collection, null=True, blank=True, unique=True),
modified = models.DateTimeField(null=True, blank=True, auto_now=True)
class Meta:
db_table = u'occurrence'
Every time i go to check the Occurrence object i get this error
TemplateSyntaxError at /admin/hotiapp/occurrence/
Caught an exception while rendering: column occurrence.collection_id does not exist
LINE 1: ...LECT "occurrence"."id", "occurrence"."reference", "occurrenc..
And every time i try to add a new occurrence object i get this error
ProgrammingError at /admin/hotiapp/occurrence/add/
column occurrence.collection_id does not exist
LINE 1: SELECT (1) AS "a" FROM "occurrence" WHERE "occurrence"."coll...
What am i doing wrong? or how does ForeignKey works?
The problem is that you have not updated your database table definition since adding the ForeignKey. syncdb doesn't do this for you, as the documentation clearly states. You need to update the SQL manually, or use a tool like South.
Are you sure you mean
collection = models.ForeignKey(Collection, null=True, blank=True, unique=True),
Nullable and Unique? This may not be possible in some databases.
Generally, the unique constraint doesn't seem to make much sense here.
Are you trying to force a 1-to-1 relationship? Use the OneToOneField. http://docs.djangoproject.com/en/1.1/ref/models/fields/#django.db.models.OneToOneField

Django models: Why the name clash?

Firstly, I know how to fix the problem, I'm just trying to understand why it's occuring. The error message:
users.profile: Reverse query name for field 'address' clashes with related field 'Address.profile'. Add a related_name a
rgument to the definition for 'address'.
And the code:
class Address(models.Model):
country = fields.CountryField(default='CA')
province = fields.CAProvinceField()
city = models.CharField(max_length=80)
postal_code = models.CharField(max_length=6)
street1 = models.CharField(max_length=80)
street2 = models.CharField(max_length=80, blank=True, null=True)
street3 = models.CharField(max_length=80, blank=True, null=True)
class Profile(Address):
user = models.ForeignKey(User, unique=True, related_name='profile')
primary_phone = models.CharField(max_length=20)
address = models.ForeignKey(Address, unique=True)
If I understand correctly, this line:
address = models.ForeignKey(Address, unique=True)
Will cause an attribute to be added to the Address class with the name profile. What's creating the other "profile" name?
What if I don't need a reverse name? Is there a way to disable it? Addresses are used for a dozen things, so most of the reverse relationships will be blank anyway.
Is there a way to copy the address fields into the model rather than having a separate table for addresses? Without Python inheritance (this doesn't make sense, and if an Model has 2 addresses, it doesn't work).
in the django docs it says:
If you'd prefer Django didn't create a backwards relation, set related_name to '+'. For example, this will ensure that the User model won't get a backwards relation to this model:
user = models.ForeignKey(User, related_name='+')
but I never tried it myself....
I'm not sure where the errant profile field is coming from… But one way to find out would be: temporary remove address = models.ForeignKey(…) from Profile, ./manage.py shell, from ... import Address then see what Address.profile will tell you.
I don't think there is any official way to inherit only the fields from some other Model without using inheritance… But you could fake it like this (where SourceModel is, eg, Address and TargetModel is, eg, Profile):
for field in SourceModel._meta.fields:
TargetModel.add_to_class(field.name, copy.deepcopy(field))
(this is coming from Django's ModelBase __new__ implementation)
I don't think it's possible to disable the reverse name.
I've just done a quick grep over the code and it doesn't look like there is any logic which will bypass setting up the related_name field on the related model.
For Example: Add just '+'
class GeneralConfiguration(models.Model):
created_at = models.DateTimeField(editable=False, default=settings.DEFAULT_DATE)
updated_at = models.DateTimeField(editable=False, default=settings.DEFAULT_DATE)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.PROTECT, related_name='+')
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.PROTECT, related_name='+')