I am new to django, so please excuse if I am totally wrong.
I have a django installation in which some tables are manually imported from outside source. There is one table with large number of fields. In my current django I need to interact with only few of its fields.
Can I create a django model for that table with just the fields I need and will it work? Will it mess up migrations completely? How is such a situation usually handled in django?
You can use meta option db-table and managed
class ModelWithFewFields(models.Model):
# Fields declare here
class Meta:
db_table = 'Real_DB_TABLE_NAME'
managed = False
Related
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!
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.
I am developing a django application using Pinax Stripe(https://github.com/pinax/pinax-stripe). Pinax stripe is a bundled application which has a model called 'Plans'. Now in my application, I want to add some extra fields to the model 'Plans' in my application BUT without modifying the original pinax stripe application.
Something like this:
#models.py
from pinax-stripe.models import Plan
class UserProfile(models.Model):
#write the extra fields here
Is there any way I can do it and then register it with admin so i can add data to those fields in admin panel?
You can inherit the Plan models and add your own attributes:
from pinax-stripe.models import Plan
class MyPlan(Plan):
# add your attributes
pass
This works like normal inheritance in python, plus your custom attributes are migrated when you run a migration because the original pinax Plan is a subclass of models.Model.
However, be careful to not use attribute names that already exist in the pinax Plan model, since your new model will automatically take all the attibutes from Plan and Django cannot write migrations for duplicate fields.
You can simply subclass Plan and add whatever fields / methods you want:
from pinax-stripe.models import Plan
class UserProfile(Plan):
#write the extra fields here
I'd recommend you, use the OneToOne relationship like Django docs recommend to use in the User model
from pinax-stripe.models import Plan
class UserProfile(models.Model):
plan = models.OneToOneField(Plan , on_delete=models.CASCADE)
#write the extra fields here
You can download pinax folder from https://github.com/pinax/pinax-stripe into your app and edit models.py and admin.py files as per your requirement.
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.
I have these models:
class Company(models.Model):
name=models.CharField(max_length=100)
description=models.TextField()
#some more fields
class Product(models.Model):
name=models.CharField(max_length=100)
company=models.ForeignKey(Company)
#some more fields
class Category(models.Model):
parent=models.ForeignKey('self',null=True,blank=True)
name=models.CharField(max_length=100)
products=models.ManyToManyField(Product,null=True,blank=True)
#some more fields
as U can see each company has a list of product and each product belongs to some categories,I'm going to get the list of categories of each company using company pk,what's the best practice?should I define a database view?how can I do this?
Note:I've not ever used database view in django,I searched about it and that doesn't sound easy to me!
I always try to avoid using database views, stored procedures and in general stuff that 'lives' in the database itself rather than in the application code-base for the simple reason that it is very hard to maintain (and also you say good bye to database agnostic applications).
My advice here is to stick with django orm (which can do a lot) and only if you unable to get decent performances or if you need some advanced feature available through stored procedures/views only then to go for that solution.
Using views in django is quite easy.
Say you have 1 view to query, you create the view on the db then you write the model with fields matching the view' columns (name and type).
UPDATE:
You then need to set the table name as the view name in meta class definition.
After that you need to tell django not to write on that and to not try to create a table for the view model, luckily there is a conf for that:
class ViewModel(models.Model):
... view columns ...
class Meta():
db_table = 'view_name'
managed = False
I've no idea why you think you need a db view here. Generally, you don't use them with Django, since you do all the logic in Python via the ORM.
To get the list of categories for a company, you can just do:
categories = Category.objects.filter(products__company=my_company)
where my_company is the Company instance you're interested in.