Can I change a default property in appengine model? - python

I didn't read the doc enough before starting this, my mistake.
I have :
class A(db.Model):
date = db.DateTimeProperty(auto_now_add=True)
I would prefer auto_now=True instead. Can I just change it ? I know that a change won't affect existing data (i.e it won't magically change the date of objects in the datastore to their last update date).
Bu what will happen to entities that were created with the auto_now_add=True ? Is a model transformation like that permitted ? Or will this just affect new objects ?
I can reformulate my questions if I am not clear, don't hesitate to ask

This is not a model transformation. auto_now and auto_now_add are applied entirely in the Python db client, not at the datastore level. You can change it whenever you like, and all entities that you modify after making that change (as long as you're using the new code) will update the date field when put() is called.

Related

Possible source of cascade deletion on Django 1.9 project?

I'm working on a Django 1.9 project with a huge source and lots of is inherited from previous developers.
When I delete a User object from the shell there are many other related objects that get deleted as well. I get a print output with a Tuple containing:
(# of deleted objects, {u'CLASS_NAME': #number of deleted objects...})
I've searched all the code throughly and there are no Signals attached to User pre_ post_ or on_ delete, neither I can find where this print output is constructed... so, I have no idea where this is coming from.
Any ideas for other possible ways this can be happening?
A ForeignKey [Django-doc] has an on_delete=… parameter. Prior to django-2.0, you did not have to state this explicitly, in that case it used uses CASCADE, as is specified in the documentation:
on_delete will become a required argument in Django 2.0. In older versions it defaults to CASCADE.
This thus means that if you did not specify an on_delete=… parameter, or you specified this as CASCADE, then if the target record is removed, that model record is removed as well.
You can specify another handler for this. In fact you can even write your own handler, but unless you have to do something very sophisticated, the builtin handlers will likely be sufficient, you can choose between:
CASCADE
PROTECT
SET_NULL
SET_DEFAULT
SET(…)
DO_NOTHING
There are basically four categories: a cascade (CASCADE), prevent the removal (PROTECT), set it to another value (SET_NULL, SET_DEFAULT, SET(…), and DO_NOTHING.
DO_NOTHING is often not a good idea, since most databases enforce referential integrity and will thus refuse to update/delete, since then the foreign key column no longer points to a valid record. By SET_NULL, the field needs to be NULLable (so null=True), you can also set t to a different view.
You should thus pick the strategy that you think is the best, and then the ForeignKey looks like:
class MyModel(models.Model):
my_field = models.ForeignKey(OtherModel, null=True, on_delete=models.SET_NULL)

What's the best approach for this database models structure?

I'm developing a Property Management System with Django, right now I'm working on an app named by "Property Check", basically the purpose of it is to provide a form with a list of tasks like "Diswasher: clean & empty?", those tasks need to be checked at a property by a staff member.
The main idea is to allow admin to create Tasks and their Categories on the admin side.
Example: Task - Dishwater: clean & empty belongs to Category - Kitchen.
Each Property Check belongs to a property, it has the list of tasks and those tasks have different status, like "Checked" or "Needs attention".
So far this is what I've created:
models.py
class Task(models.Model):
name = models.CharField(db_column='SafetyTaskName', max_length=100, blank=False, null=False)
category = models.ForeignKey(Categories, db_column='category')
task_check = models.ForeignKey(TaskCheck)
class Categories(models.Model):
name = models.CharField(db_column='Categories', max_length=40, null=False, blank=False)
class TaskCheck(models.Model):
status = models.CharField(db_column='Status', choices=STATUS_CHOICES, default='nd')
image = models.ImageField(upload_to='property_check',null=True)
notes = models.CharField(db_column='Notes', max_length=500, blank=True, null=True) # Field name made lowercase.
class Propertycheck(models.Model):
property = models.ForeignKey(Property, models.DO_NOTHING, db_column='ID_Property') # Field name made lowercase.
task = models.CharField(TaskCheck)
name = models.CharField(db_column='Name', max_length=150)
date = models.DateField(db_column='Date', default=timezone.now) # Field name made lowercase.
next_visit = models.DateField(db_column='Next Visit')
staff = models.ForeignKey(User, db_column='Staff', max_length=25)
notes = models.CharField(db_column='Notes', max_length=500, blank=True, null=True) # Field name made lowercase.
Functional example of what I pretend:
A staff member goes to a property that needs to be checked, he fills
the form that contains all the tasks. In case of needing more tasks,
the admin goes to the admin panel and adds a new one. The same status
applies to every task.
Requirements:
A property has many property checks;
A property check has a list of tasks;
Admin must be capable to add tasks and categories;
Tasks belong to one category;
Property checks are made by a staff member;
The task list is the same to every property;
Every task must have a status (Ex.: completed state);
Problem:
I'm a bit confused about where to use the foreignkeys. I need property check to show the list of tasks, and for each one, their status.
Due to my experience I'm stuck at this right now, so I need some help with this.
Could you please take a look at what've done and let me know a better solution?
* **Update ***
Thanks to Bruno Desthuilliers answer, I could restructure my models by following his advices. I think this solution is closer to what I need, but my question is, are my changes 100% correct according to the requirements on Bruno's answer?
class Task(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Categories)
property = models.ManyToManyField(Property)
class Categories(models.Model):
name = models.CharField(max_length=40)
class TaskCheck(models.Model):
status = models.CharField(choices=STATUS_CHOICES, default='nd')
image = models.ImageField(upload_to='task_check', null=True)
notes = models.TextField(max_length=500)
task = models.ForeignKey(Task)
property_check = models.ForeignKey(Propertycheck)
class Propertycheck(models.Model):
property = models.ForeignKey(Property, models.DO_NOTHING)
name = models.CharField(max_length=150)
date = models.DateField(default=timezone.now)
next_visit = models.DateField()
staff = models.ForeignKey(User, max_length=25)
notes = models.TextField(max_length=500, default='')
My english ain't the best and I wasn't sure about the best title for my question.
A property has many property checks;
This describes only half of the relationship's cardinality - you also need to specify how many properties a property check can belong to. In this case the answer seems rather obvious (I can't see a case where a same property check would belong to more than one property), BUT unless you have a real and deep working knowledge of the domain, you should STILL ask your customer - sometimes "obvious" things are actually wrong ;-)
But if we consider that "a property has many property checks" AND "a property check belongs to one single property", we have a one to many relationship. At the db schema level, this is materialized by a foreign key on the "one" side in the "many" side, ie PropertyCheck must have a fk on Property.
This is logical when you remember that in the relational model, fields are atomic values (one single value in each field). You couldn't store a list of related PropertyCheck ids in Property, but you can store a single Property id in each PropertyCheck.
This is also logical when you think of the constraints - a Property can actually have "zero to many" related property checks (you can have a property that has never been "checked" so far), but a PropertyCheck MUST have a related property (it wouldn't make sense to have a property check without property, would it ?). If property checks ids where stored as a list in Property, you could still create property checks without property (and you would have consistency issues too if a property check was deleted and the property's list of property checks not updated).
So, to make a long story short: for a one to many relationship, the fk resides on the "many" side and points to the "one" side.
A property check has a list of tasks;
Are you sure this one is right ? It seems to me that you're confusing the user's view of the application with the database schema.
Sure, what the user views when he's on the "property check" page is a list of tasks to perform (and a checkbox etc for each task) - but this doesn't mean the tasks belong to the property check. If that was the case, the admin would have to create a new list of tasks for each property check... As fad as I understand the domain, the point is that there's a list of tasks for each property, and that the system builds a list of (not yet checked) task checks for each property check. Which FWIW is already what you started to design.
So (assuming I got the problem right), your rule is actually "each property has a list of tasks". Now we have the other cardinality to sort out: does a task belong to one single property, or can the same task be shared by many properties ?
We already covered the first case (cf above). In the second case - which is actually more likely since there are certainly quite a few tasks that will be the same for most properties -, you have a many to many relationship. Those are materialized by a relationship table which has a fk on each side of the relationship, with a unicity constraint on the pair of fks (you don't want to have the same task listed twice for a same property). Note that with Django's ORM, you don't need to explicitely declare a model for this (unless of course you need to add some other field to the relationship, but so far I don't see a need for this here) - just declare a many2many field on any side of the relationship (doesn't really matter) and the ORM will create the intermediary table for you.
Then you have a relationship between property check and task check. Here it's a simple one to many relationship - a property check has many task checks, a task check belongs to one single property check. The only constraint here is that those task checks's task must belong to the same property as the property check's property (yes, it's a bit confused when written that way xD). To say it more simply: the task list of a property is used as a blueprint to create the tasks check list for a property check.
IOW you have:
a task belongs to one or many property
a property has many tasks
a property has many property checks
a property check belongs to one single property
a task check references one single task
a task has many task checks
a task check's task must be one of the tasks of the task check's property check's property (duh!)
Admin must be capable to add tasks and categories;
This is a requirement indeed, but it's not related to what interest us here since this is handled at code level (permissions), not at the db schema level.
Tasks belong to one category;
and a category can have many tasks - one to many relationship, cf above.
Property checks are made by a staff member;
and a staff member can do many property checks - one to many relationship, cf above.
The task list is the same to every property;
Ah, this one is interesting. If this is true, it means that you actually don't need any relationship between Task and Property.
But that's still something I'd double-check with the customer - from experience, customers tend to only think of the general case when they explain the domain, then when they start testing the software a whole lot of corner cases appear out of the blue, and you suddenly realize you will have to rewrite half or more of your schema and code. I actually had the case on one of the very first application I was involved in - not as a developper actually, I was just one of the app's users, and the first thing I had to do with the app revealed such shortcomings, leading to a full month of additional development (which the company that employed me had to pay for since they had signed on the - wrong - requirements). Needless to say the persons responsible for this costly mistake were either blamed or, for one, just plain fired.
Every task must have a status (Ex.: completed state);
This one is wrong too. The status belongs to the task check, not to the task.
Ok, so the models you posted are not too far off. As I already mentionned in a comment, you have some one to many relationships wrong (fk on the wrong side of the relationship) but with the explanations above you should be able to sort this out. You may also want to double check some of the rules with the customer and adjust your models accordingly.
A couple other things now:
First, unless you're working with a legacy database (which is obviously not the case here), you'd be better leaving the model fields db_column attribute alone - the ORM will use the model field's name as db column name, and that's most often the best default - at least you don't have to check your models.py file for column names when you want to do raw SQL queries. Note that for foreign keys, the model's attribute will yield the related model instance, but will create a "fieldname_id" column.
Second point: if a textfield or charfield is not required, do NOT use "null=True" - else you'd have two possible values indicating "no data", either SQL "NULL" or an empty string. Better to only have one of them, in this case the empty string, so remove the "null=True" and use "default=''" instead. Also, for free text (the "notes" field for example), you may want to use a textfield instead of a charfield. This avoids placing useless contraints on the maximum length (that you can bet the users WILL ask you to extend), and will also be translated by Django's ModelForms to a proper html "text" widget instead of a (single line) html "input".
Third point: "blank=False" and "null=False" are already the defaults - a field is required unless specified otherwise - so explicitely passing them for required fields only adds "code noise". The most readable code is no code at all ;-)
Hope that clears up things for you, if not feel free to ask for details / explanations in a comment.

What is the best way to implement persistent data model in Django?

What I need is basically a database model with version control. So that every time a record is modified/deleted, the data isn't lost, and the change can be undone.
I've been trying to implement it myself with something like this:
from django.db import models
class AbstractPersistentModel(models.Model):
time_created = models.DateTimeField(auto_now_add=True)
time_changed = models.DateTimeField(null=True, default=None)
time_deleted = models.DateTimeField(null=True, default=None)
class Meta:
abstract = True
Then every model would inherit from AbstractPersistentModel.
Problem is, if I override save() and delete() to make sure they don't actually touch the existing data, I'll still be left with the original object, and not the new version.
After trying to come up with a clean, safe and easy-to-use solution for some hours, I gave up.
Is there some way to implement this functionality that isn't overwhelming?
It seems common enough problem that I thought it would be built into Django itself, or at least there'd be a well documented package for this, but I couldn't find any.
When I hear version control for models and Django, I immediately think of django-reversion.
Then, if you want to access the versions of an instance, and not the actual instance, simply use the Version model.
from reversion.models import Version
versions = Version.objects.get_for_object(instance)
I feel you can work around your issue not by modifying your models but by modifying the logic that access them.
So, you could have two models for your same object: one that can be your staging area, in which you store values as the ones you mention, such as time_created, time_modified, and modifying_user, or others. From there, in the code for your views you go through that table and select the records you want/need according to your design and store in your definitive table.

Detect if a model has changed before calling save in Django

I have a database model that is being updated based on changes in remote data (via an HTML scraper).
I want to maintain a field called changed - a timestamp denoting when the last time that model's values changed from what they were previously (note that this is different from auto_now as these fields are updated every time a model's save method is called).
Here is my question:
In a model's save method, is there a straightforward way to detect if a model instance's current values are different from the values in the database? Or, are there any alternative methods to easily maintain a changed timestamp?
If you save your instance through a form, you can check form.has_changed().
http://code.activestate.com/pypm/django-dirtyfields/
Tracks dirty/changed fields on a django model instance.
Sounds to me like what you want is Signals: http://docs.djangoproject.com/en/1.2/topics/signals/
You could use a post_save signal to update a related field in another model to store the previous value. Then on the next go-round you'd have something to compare.
You might try computing a checksum of the record values when you save them. Then when you read it later, recompute the checksum and see if it has changed. Perhaps the crc32 function in the Python zlib standard module. (I'm not sure what kind of performance this would have. So you may want to investigate that.)
This library has tracks FK lookups.
https://github.com/mmilkin/django_dirty_bits

Django: Overriding verbose_name for AutoField without dropping the model

I am using 0.97-pre-SVN-unknown release of Django.
I have a model for which I have not given any primary_key. Django, consequently, automatically provides an AutoField that is called "id". Everything's fine with that. But now, I have to change the "verbose_name" of that AutoField to something other than "id". I cannot override the "id" field the usual way, because that would require dropping/resetting the entire model and its data (which is strictly not an option). I cannot find another way around it. Does what I want even possible to achieve? If you may suggest any alternatives that would get me away with what I want without having to drop the model/table, I'd be happy.
Hmm... and what about explicitly write id field in the model definition? Like this for example:
class Entry(models.Model):
id = models.AutoField(verbose_name="custom name")
# and other fields...
It doesn't require any underlying database changes.
Look into the command-line options for manage.py; there's a command to dump all of the model data to JSON, and another command to load it back in from JSON. You can export all of your model data, add your new field to the model, then import your data back in. Just make sure that you set the db_column option to 'id' so you don't break your existing data.
Edit: Specifically, you want the commands dumpdata and loaddata.

Categories

Resources