Django database design choice - database

I have a table of Users who are permissioned to edit one of a collection of other tables (each which has a last_modified field to indicate the last time it was changed). I have another table that tracks each change as it is made (I have a better way to track history/versioning, but this is meant more for posting a rolling list of updates to the user)
class WhatsNew(models.Model):
author = models.ForeignKey(User)
model_update = models.CharField("Database Table", max_length=100)
object_id = models.IntegerField("Object ID")
object_name = models.CharField("Object Name", max_length=100)
changed = models.TextField("Fields Updated", blank=True, null=True)
pub_date = models.DateTimeField("Date/Time of Update", auto_now_add=True)
I want the user to be able to see all of the edits they have made. I would do this by querying the above table, filtering on the author. But in addition, I want the user to see a list of the edits they made grouped by id. So for instance, if user 12345 edited object 2-1, then 3-2, then 2-1 again, then 4-4, I want the user to be able to see the a list (2-1, 3-2, 4-4), the time they modified the object, and the time the object was modified by anyone.
Should I capture all of this data in a separate table or try to query it from the WhatsNew table? I think I should capture it in a new table to avoid a possibly expensive query, but I don't want to duplicate information that is already availble in the database.

Related

How to real time filter foreign key dropdown, based on previous foreign key dropdown selection in the model form?

I have 2 models, Jobs and Çompany. Both are taken as a foreign key to my current model Tracker. In the tracker CreateView form I am selecting the Company from the drropdown(Company model), also the Job Position(Job model).
The Job model also has a company field, which says for which company the job position is open.
Now, what I want is, in my tracker form, as soon as I select a company from the dropdown, I want only the Job openings of that company to be listed in the Job foreign key dropdown.
Let's say there are 3 job openings for Google, Engineer, Support and Developer. Currently my job position dropdown is displaying all the positons in the job model list. I want to filter them based on the company I select.
And the company also I'm chosing from the dropdown beside only, in the same form.
Is there a way, I can filter the dropdown real time?
Like having a dynamic foreign key dropdown which depends on my Company value chosen(dropdown again)?
class Tracker(models.Model):
company_applied = models.ForeignKey(Company, on_delete=models.CASCADE)
position_applied = models.ForeignKey(Jobb, on_delete=models.CASCADE)
class Jobb(models.Model):
position = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
def __str__(self):
return self.position_applied
class Company(models.Model):
company_name = models.CharField(max_length=100)
...
def __str__(self):
return self.company_name
How to achieve it? I searched a lot, I'm not able to find the exact words to search to get the solution.
Also I'm new to Django..

Django database fields for better queries

Hello I would like to ask a question for setting up some fields in my db. I have three models
models
class Customer(models.Model):
#fields
class Entry(models.Model):
#fields
customer = models.ForeignKey(Customer, related_name='entries')
class EntryHistory(models.Model):
#fields
entry = models.OneToOne(Entry, related_name='history')
I want to get all Entry histories for a specific customer. Isn't that
for entry in customer.entries:
try:
history.append(entry.history)
except entry.history.related.models.DoesNotExist:
pass(or continue?)
My thought search all customers entries and if they have a history added to the list. Would it be better if i just added a customer field in the EntryHistory?Would the query be quicker? This would be a frequent transaction in my project. But i know adding a customer in the EntryHistory model is redundant since I know who the customer is from the entry field. Should I be worried if e.g i have a lot of customers and a lot of entries for each?
I want to get all Entry histories for a specific customer.
customer = Customer.objects.get(pk=1)
EntryHistory.objects.filter(entry__customer=customer)
Django provides both forward and reverse lookups for foreign keys, so exploiting that you can go from EntryHistory -> Entry -> Customer

Database which each user sees differently - 'multiuser'/'multiview' database?

Is there an existing implementation or even a name for a type of database which allows multiple points of view? What I mean is for instance if one user changes an article's title then the change will only be visible to that particular user and everyone else will see the original title. If several users change it to the same new title then the new title becomes the 'master view', or the 'unfiltered view' of the database, initiated either by the database or from the application.
I'm coding in C# and am familiar with SQL and starting with MongoDB but the question is about the concept and whether abstractions, implementations, or design patterns of it exist.
If your "point of views" are completely separated, you could just use a new database for each user.
From your question it seems you want to have some degree of interconnectedness. Perhaps articles created by any user should be visible to everyone? Is it only changes after creation that should be private? How about updates from the original author?
I think you just need to specify the behavior you need, and design a database that can handle that.
One solution could be to use both the (article) id and the user id as the key for your tables. That way you can completely replace content for specific users. Let's say you want to find article 123, as seen by user 456, or if that user doesn't haven't edited it, as seen by user 789, or if that user haven't edited it, just pick any version:
SELECT * FROM articles WHERE id = 123 ORDER BY user_id = 456 DESC, user_id = 789 DESC LIMIT 1

App Engine: how would you... snapshotting entities

Let's say you have two kinds, Message and Contact, related by a
db.ListProperty of keys on Message. A user creates a message, adds
some contacts as recipients, and emails the message. Later, the user
deletes one of the contact entities that was a recipient of the
message. Our application should delete the appropriate Contact
entity, but we want to preserve the original recipient list for the
message that was sent for the user's records. In essence, we want a
snapshot of the message entity at the time it was sent. If we naively
delete the contact entity, though, we lose snapshot integrity; if not,
we are left with an invalid key.
How would you handle this situation,
either in controller logic or model changes?
class User(db.Model):
email = db.EmailProperty(required=True)
class Contact(db.Model):
email = db.EmailProperty(required=True)
user = db.ReferenceProperty(User, collection_name='contacts')
class Message(db.Model):
recipients = db.ListProperty(db.Key) # contacts
sender = db.ReferenceProperty(User, collection_name='messages')
body = db.TextProperty()
is_emailed = db.BooleanProperty(default=False)
I would add a boolean field "deleted" (or something spiffier, such as the date and time of deletion) to the Contact model -- so that contacts are never physically deleted, but rather only "logically" deleted when that field is set. (This also lets you offer other cool features such as "show my old now-deleted contacts", "undelete" functionality, etc, if you wish).
This is a common approach in all storage systems that are required to maintain historical integrity (and/or similar requirements such as "auditability").
In cases where the sheer amount of logically deleted entities is threatening to damage system performance, the classic alternative is to have a separate, identical model "DeletedContacts", but foreign key constraints require more work, e.g. the Message class would have to have both recipients and deleted_recipients fiels if you needed foreign key integrity (but using just keys, as you're doing, this extra work would not be needed).
I doubt the average user will delete such a huge percentage of their contacts as to warrant the optimization explained in the last paragraph, so in this case I'd go with the simple "deleted" field.
Alternately, you could refactor your Contact model by moving the email address into the key name and setting the user as the parent entity. Your recipients property would change to a string list of raw email addresses. This gives you a static list of email recipients without having to fetch a set of corresponding entities for each one, or requiring that such entities still exist. If you want to fetch the contact entities, you can easily construct their keys from the user and the recipient address.
One limitation here is that the email address on an existing contact entity cannot be changed, but I think you have that problem anyway. Changing a contact address with your existing model would retroactively change the recipients of a sent message, which we know is a problem.

Any simple approaches for managing customer data change requests for global reference files?

For the first time, I am developing in an environment in which there is a central repository for a number of different industry standard reference data tables and many different customers who need to select records from these industry standard reference data tables to fill in foreign key information for their customer specific records.
Because these industry standard reference files are utilized by all customers, I want to reserve Create/Update/Delete access to these records for global product administrators. However, I would like to implement a (semi-)automated interface by which specific customers could request record additions, deletions or modifications to any of the industry standard reference files that are shared among all customers.
I know I need something like a "data change request" table specifying:
user id,
user request datetime,
request type (insert, modify, delete),
a user entered text explanation of the change request,
the user request's current status (pending, declined, completed),
admin resolution datetime,
admin id,
an admin entered text description of the resolution,
etc.
What I can't figure out is how to elegantly handle the fact that these data change requests could apply to dozens of different tables with differing table column definitions. I would like to give the customer users making these data change requests a convenient way to enter their proposed record additions/modifications directly into CRUD screens that look very much like the reference table CRUD screens they don't have write/delete permissions for (with an additional text explanation and perhaps request priority field). I would also like to give the global admins a tool that allows them to view all the outstanding data change requests for the users they oversee sorted by date requested or user/date requested. Upon selecting a data change request record off the list, the admin would be directed to another CRUD screen that would be populated with the fields the customer users requested for the new/modified industry standard reference table record along with customer's text explanation, the request status and the text resolution explanation field. At this point the admin could accept/edit/reject the requested change and if accepted the affected industry standard reference file would be automatically updated with the appropriate fields and the data change request record's status, text resolution explanation and resolution datetime would all also be appropriately updated.
However, I want to keep the actual production reference tables as simple as possible and free from these extraneous and typically null customer change request fields. I'd also like the data change request file to aggregate all data change requests across all the reference tables yet somehow "point to" the specific reference table and primary key in question for modification & deletion requests or the specific reference table and associated customer user entered field values in question for record creation requests.
Does anybody have any ideas of how to design something like this effectively? Is there a cleaner, simpler way I am missing?
Option 1
If preserving the base tables is important then I would create a "change details" table as a child to your change request table. I'm envisioning something like
ChangeID
TableName
TableKeyValue
FieldName
ProposedValue
Add/Change/Delete Indicator
So you'd have a row in this table for every proposed field change. The challenge in this scenario is maintaining the mapping of TableName and FieldName values to the actual tables and fields. If your database structure if fairly static then this may not be an issue.
Option 2
Add a ChangeID field to each of your base tables. When a change is proposed add a record to the base table with the ChangeID populated. So as an example if you have a Company table, for a single company you could have multiple records:
CompanyCode ChangeID CompanyName CompanyAddress
----------- -------- ----------- --------------
COMP1 My Company Boston <-- The "live" record
COMP1 1 New Name Boston <-- A proposed change
When the admin commits the change the existing live record is deleted or archived and the ChangeID value is removed from the proposed record making it the live record. It may be a little tricky to handle proposed deletions with this option. This option also has the potential for impacting performance of selecting live data for normal usage. However it does save you the hassle of maintaining a list of table names and field names somewhere in your code.
I'm sure others will have some opinions!

Resources