Django model on_update=models.CASCADE related object reference - python

I have looked for django doc in their official site but i can't find the article about the on_update model function here in Related objects reference except for on_delete.
Here is an example code:
from django.db import models
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
Is there any version of on_update?
I have visited this Cascade on update and delete wih django but there is not a clear answer about the on_update
I am using mysql and define the relationship in the ERD and sync it to the db and tried running the python manage.py inspectdb to generate the django-model but it shows only models.DO_NOTHING.
Is there a better way to achieve this, if any?

It's normally adviseable to completely leave the primary key alone when setting up your Django models, as these are used by Django in a number of ways to maintain relationships between objects. Django will set them up and use them automatically.
Instead, create a separate field in your model to keep track of unique data:
class Reporter(models.Model):
emp_id = models.CharField(unique=True)
This way you can obtain the emp_id with reporter_object.emp_id and if you need it, you can still get the pk with reporter_object.id.
You can read about how it works it in the Django 1.9 Documentation

Related

How can I see data from an already made mysql database on Django?

I'm new to Django and I am trying to use a mysql database created and filled with data by someone else
I created a model with the same name as the table I want to get data from, my models is as follows
class Study(models.Model):
study_name = models.TextField(default='Unknown')
description = models.TextField(default='Unknown')
language = models.TextField(default='Unknown')
number_of_years = models.IntegerField(default='0')
database connected but when I go to admin I don't see the data there
Please help me with this
A step by step solution would be:
get the name of the table containing your data, I'll call it study_table
make sure you know how the table was defined so you can match it with django model definition. Connect to the database with a MySQL client and run the following query:
DESCRIBE study_table;
based on the table name, column types and column names, define your model to match everything. Django models do a lot of automated naming so you have force the naming to make sure your model matches your database. Principles are:
Specify the table name as a meta option.
Create fields with names matching column names and field types matching column types. Taking an example from your code, the field study_name should match a column with the same name in the table study_table.
class Study(models.Model):
study_name = models.TextField(default='Unknown')
description = models.TextField(default='Unknown')
language = models.TextField(default='Unknown')
number_of_years = models.IntegerField(default=0)
class Meta:
db_table = study_table
Side note: your IntegerField has a default as a string '0'.
making sure the app (I'll call it study_app) containing your model is enabled, the database is configure properly in your django settings, try to access data from the admin shell (python manage.py shell):
>>> from study_app.models import Study
>>> Study.objects.first()
This should return an answer, if it does not, your model doesn't match the database data.
to make accessing the data easier, create an admin page as suggested by #iklinac. You can now read, edit your data through your browser.
A few suggestions you could consider:
study_name should probably be a models.CharField(max_length=255) or similar
description should be allowed to be empty models.TextField(blank=True)
language should probably be a models.CharField with a choices option.
You should create ModelAdmin instance for your model
The ModelAdmin class is the representation of a model in the admin
interface. Usually, these are stored in a file named admin.py in your
application.
from django.contrib import admin
from myproject.myapp.models import Study
class StudyAdmin(admin.ModelAdmin):
pass
admin.site.register(Study, StudyAdmin)
If you have a MySQL database with tables of data that don't have models created yet, you can use the dumpdata command to automatically generate the models:
https://docs.djangoproject.com/en/3.0/ref/django-admin/#dumpdata
Then, you can register those models in the Django admin. dumpdata should only be used as a starting point, since they are auto-generated and won't contain many of Django's data integrity features.
Good luck!

How to generate indexes for related fields on Django models?

Say we're building a Django-based site that clones Medium.com's URL structure, where you have users and articles. We'd probably have this model:
class Article(models.Model):
user = models.ForeignKey(User)
slug = models.CharField()
We want to be able to build URLs that look like /<username>/<slug>/. Since we're going to have billions of articles and zillions of pageviews, we want to put an index on that model:
class Meta:
indexes = [
models.Index(fields=['user__username', 'slug'])
]
But this causes the makemigrations command to fail with the following error:
django.core.exceptions.FieldDoesNotExist: Article has no field named 'user__username'. The app cache isn't ready yet, so if this is an auto-created related field, it won't be available yet.
So, plain vanilla models.Index doesn't support relational lookups like a QuerySet does. How would I add an index like this? Let's assume PostgreSQL, if that's helpful.
It seems that you can't make multi-table index according to this answer.
So if it's not possible in the database, I don't see how can Django offer this feature...
What you can do to make your queries more efficients is an index using user_id and slug.
Django index meta class mainly provide declarative options for indexing table fields,
you can create an index using several field of a model or create different index for every fields of the model. you just don't have to provide user foriegnkey field name attribute which generate automatic user_id index migrations
migrations.AddIndex(
model_name='candidates',
index=models.Index(fields=['user'], name='candidates__user_id_569874_idx'),
),
you can also set the index name in the model meta, and db_tablspace as well if needed.

Changing default auth_user table name

i'm happy with django built in user/auth , i just want to add some fields to it and change table name (mostly the last one , i can use another table for custom fields )
so i searched around and apparently we can use subclass as suggested on Rename Django's auth_user table?
So i have to start a new app and use it's model to as a subclass for AbstractUser or there is another way? (After all i just want to use it's model and other parts of app are useless )
anyway i created a new project / started app called customuser and in its model i have this code
customuser/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class customuser(AbstractUser):
class Meta:
swappable = 'AUTH_USER_MODEL'
db_table = 'customuser'
i ran makemigrations AND migrate ... it's done successfully
but atill the tables with default name was created in database as you can see below ... am i missing something ?
To use a custom user model, you need to set the AUTH_USER_MODEL setting in your settings module.
Note that you don't need to set swappable = 'AUTH_USER_MODEL'. This is an undocumented and private attribute, and is probably better left untouched.
Quite frankly if you're still in the position to do it, i'd just start a new app. It says in the docs that this decision is best made before starting your project because its a pain in the ... its hard.
If you intend to set AUTH_USER_MODEL, you should set it before creating any migrations or running manage.py migrate for the first time.
The solution otherwise is to dumpdata from the database, and manually tweak it so any reference to the user class in your dump file is replaced with your new user class. then you need to create some migrations to change the schema.
So it is doable. its just much simpler to start from a fresh project.
Django allows you to override the default User model by providing a value for the AUTH_USER_MODEL setting that references a custom model
AUTH_USER_MODEL = 'myapp.MyUser'
This dotted pair describes the name of the Django app (which must be in your INSTALLED_APPS), and the name of the Django model that you wish to use as your user model.
A full example of an admin-compliant custom user app can be found on the Django Project website.

Django: Is there a way to retrieve ORM for past migration states?

Suppose you had a Django model:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
And you migrate it to:
from django.db import models
class Person(models.Model):
both_names = models.CharField(max_length=30)
You might write a data migration for this case (or mine, not the above, but similar and not cogent to the question) and you would definitely want to test it.
I used call_command('migrate', app, state) to roll the database back to the old state and then I thought I'd just use a historic ORM of Person to instantiate some Person objects, then do the migration, then make some assertions to check if my data migration went properly.
In South, you would just call up the old ORM by Migration. How does one do this in Django 1.8?
I'm basing my strategy on this documentation: https://micknelson.wordpress.com/2013/03/01/testing-django-migrations/
And I'm hoping to find the implementation for Django's historic-models: https://docs.djangoproject.com/en/1.8/topics/migrations/#historical-models
To restate the question - How would I get the 'old' state of Person, such that I would create a person like so: Person(first_name='bob', last_name='jones') - for testing purposes.
The public API doesn't provide any means to get historical models outside of a migration. However, you can get it using the following code:
from django.db import connection
from django.db.migrations.loader import MigrationLoader
loader = MigrationLoader(connection)
state = loader.project_state(loader.applied_migrations)
apps = state.apps
apps is the same object that is passed to the function in a RunPython operation. You can get a historical model for the currently applied migrations using apps.get_model('<app_label>', '<ModelName>').
This should work in 1.8 and 1.9. It may or may not work in future versions, though I see little reason why this part of the API should change anytime soon.
For Django 3.0 and 3.1 , the solution is mostly the same as the answer from #knbk , except the input argument to project_state() is simply a tuple like ('<APP_LABEL>', '<MIGRATION_NAME>') instead of entire applied_migrations dictionary.
you can get the state from initial migration to the specific committed migration of specified application, by directly specifying <APP_LABEL> or <MIGRATION_NAME> like this :
from django.db import connection
from django.db.migrations.loader import MigrationLoader
loader = MigrationLoader(connection)
state = loader.project_state(('your_app_label', '0023_alter_some_fields'))
apps = state.apps
Note that the code above cannot be used when running migration commands (e.g. makemigrations, sqlmigrate, migrate), otherwise it will cause recursive callstack error.

Django postgresql foreign key

I have this models.py
from django.db import models
from django.contrib.auth.models import User
class Service(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=800, blank=False)
service = models.CharField(max_length=2000, blank=False)
def __unicode__(self):
return self.name
class ServiceCheck(models.Model):
service = models.ForeignKey(Service)
check_status = models.CharField(max_length=80)
check_time = models.DateTimeField()
When i run syncdb against postgresql it ends up with error:
~/dev-md> sudo python manage.py syncdb
Creating tables ...
Creating table monitor_service
Creating table monitor_servicecheck
DatabaseError: Hash/Modulo distribution column does not refer to hash/modulo distribution column in referenced table.
Code looks okay upon first glance. I suspect it's a database related issue.
As the max_lengths provided are pretty huge, try reducing the max_lengths to something <= 255 or use a TextField instead of a CharField.
Failing this, try renaming the field service in Service and/or ServiceCheck.
The issue you're hitting is actually related to how Postgres-XC/StormDB (or now Postgres-XL, where I hit this issue) handle partitioning of tables between different datanodes.
Basically, the issue is that the database engine can't guarantee the constraints on foreign keys or on unique constraints. Per an old article on the StormDB site about a previous version Django and Postgres-XC/StormDB, you can do this by setting loose_constraints=true on the database. In a modern version of Django (1.6 or later), the equivalent seems to be setting db_constraint=False on a ForeignKey as per Django's model field docs (which I can't link to directly as I don't have enough rep).
Another solution for if you're more concerned about availability and not performance is to replicate the data, which means that you won't have the problem, because all of the datanodes have the same data.
I don't know of any way to do this directly in Django, but you can modify your table creation to use DISTRIBUTE BY REPLICATION as detailed in the CREATE TABLE docs.

Categories