Django Admin won't save TextFields as NULL, unlike CharFields - django-models

good_field = models.CharField(max_length=256, null=True, default=None, blank=True, unique=True)
bad_field = models.TextField(null=True, default=None, blank=True, unique=True)
The good_field can be saved as blank and will end up as a NULL in the DB (which is important because of the unique=True but the bad_field gets saved as '' which violates the unique constraint.
Seems this was fixed for CharFields several years ago but for some reason not fixed for TextFields. Is it possible to fix this for TextFields too or was their some architectural reason it was only fixed for CharFields.
I tried fixing it in the model, but the admin form is doing the unique testing (instead of letting the DB do that work) and my model level patching never gets a chance.
Is there a way to remove the unique validation from the admin form and let the DB do it's job?

Related

How to set unique_together for a user field

I am learning Django. I am creating app where I have a model Employer.
In a database, I want to keep only one record for fields user and website.
I tried to use unique_together in my model but during migration I got the following error:
django.db.utils.IntegrityError: UNIQUE constraint failed: employer_employer.user_id, employer_employer.website
Can you please advice me what is a problem? Maybe this is not a good way how to do it?
Thanks!
class Employer(models.Model):
USER = settings.AUTH_USER_MODEL
user = models.ForeignKey(USER, default=1, on_delete=models.CASCADE)
company_name = models.CharField(max_length=200)
company_size = models.IntegerField(default=0)
website = models.CharField(max_length=200)
class Meta:
unique_together = ('user', 'website')
I tried to use unique_together in my model but during migration I got the following error: django.db.utils.IntegrityError: UNIQUE constraint failed: employer_employer.user_id, employer_employer.website
This means the migration is perfectly fine. It means there is already data in the database that violates the constraint, so you will first need to go through the fact that there are Employer objects in the database with the same user and the same website.
You can find such Users effectively with:
from django.db.models import Count
Employee.objects.values('user', 'website').annotate(count=Count('pk')).filter(
count__gt=1
)
then you will have to fix these Employer records.
Note: As the documentation on unique_together [Django-doc] says, the unique_together constraint will likely become deprecated. The documentation advises to use the UniqueConstraint [Django-doc] from Django's constraint
framework.

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 design choice

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.

how to create, syncdb, and access django model dynamically?

I defined an expense model for an expense application,
class Expense(models.Model):
pub_date = models.DateTimeField()
amount = models.IntegerField()
memo = models.TextField()
and I would like to create lost of separate tables to maintain data for different users, such as
james_expense_table for james
william_expense_table for william
....
balabala_expense_table for balabala
They are exactly same behavior, like parallel objects. The only difference is the prefix. So that, i can easily extend the application with more features.
So how can I achieve this?
I've read some abstract model stuff from django web. But in fact, they are static, hard coded in the *.py files, not what i want.
And one more question, for a static model (hard code in *.py file), it can use "manage.py syncdb" command to sync the module fields to the table fields, so how can do this for the dynamic case?
What you want is probably to use a ForeignKey so that you can link your table to different users:
class Expense(models.Model):
pub_date = models.DateTimeField()
amount = models.IntegerField()
memo = models.TextField()
user = models.ForeignKey(MyUserField)
Obviously you need to have a MyUserField implemented and imported.
You can then access the user from the Expense table
my_expense.user
Or the Expense table from the user using:
my_user.expense_set.all()
You then don't require to run syncdb for every new user, and it's not statically hard-coded in the file.

Use database view in Django

I saw the question can i use a database view as a model in django and tried it in my app, but that didn't work.
I created a view named "vi\_topics" manually and it had "id" column but I kept getting an error, even if I added "id" field explicitly, saying
"no such column: vi_topics.id"
Here is the definition of my model named Vitopic:
from django.db import models
class Vitopic(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author_name = models.CharField(max_length=200)
author_email = models.CharField(max_length=200)
view_count = models.IntegerField(default=0)
replay_count = models.IntegerField(default=0)
tags = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'vi_topics'
Note: I use sqlite3.
Try this:
http://docs.djangoproject.com/en/dev/ref/models/options/#managed
managed
Options.managed
New in Django 1.1: Please, see the release notes
Defaults to True, meaning Django will create the appropriate database tables in syncdb and remove them as part of a reset management command. That is, Django manages the database tables' lifecycles.
If False, no database table creation or deletion operations will be performed for this model. This is useful if the model represents an existing table or a database view that has been created by some other means. This is the only difference when managed is False. All other aspects of model handling are exactly the same as normal. This includes
Adding an automatic primary key field to the model if you don't declare it. To avoid confusion for later code readers, it's recommended to specify all the columns from the database table you are modeling when using unmanaged models.
If a model with managed=False contains a ManyToManyField that points to another unmanaged model, then the intermediate table for the many-to-many join will also not be created. However, a the intermediary table between one managed and one unmanaged model will be created.
If you need to change this default behavior, create the intermediary table as an explicit model (with managed set as needed) and use the ManyToManyField.through attribute to make the relation use your custom model.
For tests involving models with managed=False, it's up to you to ensure the correct tables are created as part of the test setup.
id = models.IntegerField(primary_key=True)

Resources