Create dynamic model field in Django? - django

In my models.py my model store contains name, brand_name fields
Now,I want to create new field called brand_type in store model dynamically from Django admin,how can I do this?
Can we change schema of model using SchemaEditor? How?

you can't create model's fields via admin panel
you must create fields in models.py
admin panel is only a convinient way to manipulate your database, but not modifiyng its tables

It requires migration while the server is running. Create brand_type field under your model and set blank=True

In your models.py
class Store(models.Model):
name = ...
brand_name = ...
brand_type = models.CharField(max_length = 40, blank= True, null =true)
In your console
./manage.py makemigrations
./manage.py migrate
Extra Stuff:
If you are interested in Text Choices
or
If you wanna make it more dynamic based on your use case,
create a model called BrandType and link it in Store using
brand_type = models.ForeignKey(BrandType,on_delete=models.PROTECT)
models.py
class BrandType(models.Model):
name = ...
some_other fields=
#... Store model follows
admin.py
# other stuff
from .models import BrandType
admin.site.register(BrandType)
Take away: It is not advisable to modify your models.py file using admin directly it will cause integrity issues and there are better ways to achieve your desired functionality.

Related

How to setup a flexible django models

I'm new to django. What I'm trying to achieve is when the ProductType combobox is changed, the fields changes to its specific fields then the users inputs using those field and entered to the database. My problem is how to create a flexible model that would accept extra fields
from django.db import models
class Product(models.Model):
"""SKU"""
stock = models.IntegerField(default=None)
class ProductType(models.Model):
product_field = models.ForeignKey(ProductFields, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
class ProductFields(models.Model):
"""Fields of ProductType"""
Here's an DB example I'm trying to achieve See Image
SQL database is not suitable for that purpose.
Look for non-SQL databases for ex. Firebase

Django make certain fields read-only for a certain element of a Model

My model looks like this:
class Article(models.Model):
title = models.CharField(blank=False, null=False, max_length=200, verbose_name="title")
description = RichTextUploadingField(blank=False, null=False, verbose_name="description")
Is it possible to:
1.
Create an article with a default title='Terms and conditions' which will be read-only in django-admin, but a description that can be modified in the django-admin?
2.
If I already have the article created, use the django shell to make the attribute read-only, like so?
python manage.py shell
from articles.models import Article
terms = Article.object.get(title='Terms and conditions')
terms.title.readonly = True
This option throws an error:
AttributeError: 'str' object has no attribute 'readonly'
Looks like what you are looking for is the readonly_fields when defining the Admin Model. Check the Django docs on the ModelAdmin.readonly_fields attribute
In your case, define the following in admin.py:
from .models import Article
class ArticleAdmin(admin.ModelAdmin):
readonly_fields=('title',)
admin.site.register(Article, ArticleAdmin)
Good luck!
You can do it in two steps:
Make the field read only in the admin using Model.Admin.readonly_fields: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields
Use signals to fill the title before saving it, add a pre save hook where you set the default value of the title: https://docs.djangoproject.com/en/2.1/ref/signals/#pre-save

Django rest framework api with existing mysql database

How can I create a Django REST Framework API that connects to an already existing MySQL tables instead of creating them through modela.py. My models.py shows something like this:
class Author(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
def __str__(self):
return f'{self.first_name} {self.last_name}'
Instead of this, I need to take data directly from existing tables in MySQL.
For that you need to define same class name as your table name with meta char field
like for example
RandomTable(id INT(10),name varchar(10)) is your existing mysql table then the models.py for it will be
class AppnameRandomTable(models.Model)
id = models.CharField(db_column="id") #name of column of existing db
inside that you will need to write the fields of your existing table name in meta section
class Meta:
db_table = "RandomTable" #your existing mysql table name
time saving hack just create a class in models.py and on terminal run "python manage.py inspectdb" you will automatically get all the column names from there.
You can just copy and paste names from there , because for reading and writing on columns you need to define their variables in your class even if the table is existing mysql table
python manage.py inspectdb > models.py
If you run that command it will create a models.py in the project's root directory. Once you've done that you can either move it directly into the project or create a models folder and break it down into areas of concern from there. You will likely have to do the work of adding related_name = 'foo' to a lot of fields that have relationships with other models. That can be time-consuming but it works.

Hide Model Property from Django admin and set Its Value Manually

I want to hide a column from django admin and set its value from session.
In simple words i want to set a property of a model from session and don't want a field in admin for that column.
Can someone help me?
You can mark the field as read-only but still have it visible in the admin, or completely exclude it.
class MyModel(models.Model):
field1 = models.CharField(max_length=20) # this is editable
field2 = models.CharField(max_length=20, editable=False) # this is not
or
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
exclude = ['field2']
If you're using a custom model form in the admin, just don't include the field in the fields attribute.
As far as I remember there are a lot of ways to do this, with the fields attribute on Meta you can hide or select which fields to show.
check This example

Django admin: search for foreign key objects rather than <select>?

My model looks like this:
class Asset(models.Model):
serial_number = models.CharField(max_length=100, unique=True)
asset_tag = models.CharField(max_length=100, unique=True)
class WorkOrder(models.Model):
asset = models.ForeignKey(Asset)
Essentially, a work order is submitted and then an admin assigns an asset to the work order. The asset_tag field is a barcode that we can scan in. When editing the work order in the Django admin, by default the asset field is displayed as a <select> widget. What we want to be able to do is have a search field so that we can scan the asset tag and then search for the right asset in the DB to associate with the work order.
I know you can customize the Django admin foreign key to a hard coded query, but I can't figure out how to get it so it does a search based on a field on the admin page.
Did you take a look at raw_id_fields?
It should be pretty to close to what you're after.
If you are using Django >= 2.0, you can take advantage of a feature called autocomplete_fields. You must define search_fields on the related object’s ModelAdmin because the autocomplete search uses it.
Since you have a ForeignKey relationship to Asset in WorkOrder, in the admin.py of your app add the following:
from django.contrib import admin
#admin.register(Asset)
class AssetAdmin(admin.ModelAdmin):
search_fields = ["serial_number", "asset_tag"]
#admin.register(WorkOrder)
class WorkOrderAdmin(admin.ModelAdmin):
autocomplete_fields = ["asset"]
Add the fields you want to use for searching to search_fields, and add define autocomplete_fields as shown in the code above.
Now you can use the autocomplete_fields from django 2.0.
It's quite neat.