I apologize for the novice question but my head is about to explode.
I am trying to learn Django and wanted to create something practical and that I could use. I settled with a small inventory system.
The problem I am having is figuring out the best way to have relationships between models for ideal db setup.
I have models for the following:
Depreciation Policy
Manufacturer
Customer/Owner
Asset Category (Server, laptop etc)
Asset Model (Macbook Pro, Proliant DL380 Gen 9 etc)
Asset Status (Archived, Deployed, Lost etc)
Asset Fields (Generic fields all assets would
have, model(FK), status(FK), purchase date etc.)
Cpu
Server
Network Card
Right now I have both Server & Network Card inheriting Asset Fields.
My goal was to have tables for each type of asset but still have one master table that can reference each asset type's table via a FK so that if I want to display all assets in the database I can just list one table and pull in the relevant information from their related tables instead of having to look through each asset's table.
I want something like:
Asset Table:
id(pk), model(fk), status(fk), serial Number, purchase date, cost, location, server_id/network_card_id(fk)
Server Table:
id(pk), customer, name, memory, cpu(fk), ilo_type, ilo_lic
Asset Model:
class Asset(models.Model):
# class Meta:
# abstract = True
assetTag = models.CharField(max_length=50, unique=True)
model = models.ForeignKey(AssetModel, on_delete=models.SET_NULL, null=True)
status = models.ForeignKey(AssetStatus, on_delete=models.SET_NULL, null=True)
serialNumber = models.CharField(max_length=50, unique=True)
purchaseDate = models.DateTimeField('Date order was placed', blank=True)
purchaseOrder = models.CharField(max_length=25, blank=True)
cost = models.DecimalField(default=0, max_digits=8, decimal_places=2, blank=True)
# location = models.CharField(max_length=25, blank=True, null=True)
def calculate_current_value(self, purchaseDate, cost):
purchase_price = float(cost)
months = self.model.depreciationPolicy.months
if months > 0:
days = months * 30
depreciation_per_day = (float(cost) / days)
days_owned = timezone.now() - purchaseDate
value_lost = days_owned.days * depreciation_per_day
current_asset_value = purchase_price - value_lost
return round(current_asset_value, 2)
def __str__(self):
return self.serialNumber
Server Model:
class Server(Asset):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
memory = models.IntegerField(default=0)
cpu = models.ForeignKey(Cpu, on_delete=models.SET_NULL, null=True)
ILOType = models.CharField(max_length=50, choices=(('Std', 'Standard'), ('Adv', 'Advanced')))
ILOUsername = models.CharField(max_length=50, null=True, blank=True)
ILOPassword = models.CharField(max_length=100, null=True, blank=True)
ILOLicense = models.CharField(max_length=50, null=True, blank=True)
def __str__(self):
return self.serialNumber
Network_Card Model:
class Nic(Asset):
macAddress = models.CharField(max_length=100, unique=True)
portCount = models.IntegerField(default=0)
portType = models.CharField(max_length=50, choices=(('Ethernet', 'Ethernet'), ('Fiber', 'Fiber')))
def __str__(self):
return self.name
The first thing I would recommend is for you to just forget about tables. You're not dealing with tables in Django, but with models, which are classes that represent the entities of your system. Models become tables later, but you don't have to concern yourself with them right now.
Second, model your classes carefully. Design a nice diagram representing their relationships. In your scenario, one class will contain references to other classes (a pivot class), so model that.
Also, take a moment to read the documentation. Django is a very neatly and thoroughly documented. Read carefully about models and squerysets. You will know everything you need to represent things inside your architecture.
Some hints:
When defining foreign fields, you'll have quite a few options, from ForeighKey(), ManyToManyField(), ManyToOneRel(), etc. Read about each and every one of the options, and chose the one that represents your reality most accurately.
ManyToMany() has an interesting behavior, which is: if you don't pass a table to it, it will create one for you, to act as a pivot. I prefer to create my middle tables, as it is more aligned with the Zen of Python.
When you want to return a coherent representation of your data, you'll have to work with querysets in order to enforce the relationships you have built into your models, much in the same way you'd do with a relational database, either by constructing a query, or designing a view.
Here's some nice links for you:
Fields: https://docs.djangoproject.com/en/1.10/ref/models/fields/
Querysets: https://docs.djangoproject.com/en/1.10/topics/db/queries/
The Zen of Python: https://www.python.org/dev/peps/pep-0020/
Further, I strongly recommend you to go take a look at Django Rest Framework as soon as you get a hold on the basic concepts of Django models. Here's the link: http://www.django-rest-framework.org/
And come back to me when you have more specific questions.
Happy coding!
I believe I have solved this issue.
the solution was to build it out as follows. Instead of the Server & Nic class inheriting the Asset class, I defined a 1:1 relationship with each of them and the Asset class.
asset = models.OneToOneField(Asset, on_delete=models.CASCADE, primary_key=True)
This allowed for the Asset table to track all assets, and the asset_id(PK) is both a foreign_key and a primary_key in Server & Nic.
Related
I'm trying to insert data retrieved by scraping into the DB created by the following models.
However, I realized that using django's bulk_create or the external library based on it, bulk_create_or_update, is likely to make the logic too complex. (I felt that orm should be used for simple CRUD, etc.)
So I'm thinking of using Row SQL to save the data, for both maintainability and speed.
I'm not familiar with sql at all, so I'd like to get some advice from you guys.
What SQL code is preferable to this?
Each page to be scraped has multiple pieces of information, and there are multiple pages in total. I'd like to scrape all the pages first, add them to a dictionary, and then save them in a batch using sql, but I don't know the best way to do this.
from django.db import models
from django.forms import CharField
# Create your models here.
# province
class Prefecture(models.Model):
name=models.CharField("都道府県名",max_length=10)
# city
class City(models.Model):
prefecture = models.ForeignKey(Prefecture, on_delete=models.CASCADE, related_name='city')
name=models.CharField("市区町村名",max_length=10)
# seller
class Client(models.Model):
prefecture = models.ForeignKey(Prefecture, on_delete=models.CASCADE, related_name='client',null=True,blank=True)
city = models.ForeignKey(City, on_delete=models.CASCADE, related_name='client',null=True,blank=True)
department = models.CharField("部局",max_length=100)
# detail
class Project(models.Model):
name = models.CharField("案件名",max_length=100)
serial_no = models.CharField("案件番号",max_length=100,null=True,blank=True)
client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='project')
# etc...
# file
class AttachedFile(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='attach_file')
name = models.CharField(max_length=100)
path = models.CharField(max_length=255)
# bid company
class Bidder(models.Model):
name = models.CharField("入札業者名",max_length=100)
prefecture = models.ForeignKey(Prefecture, on_delete=models.CASCADE, related_name='bidder',null=True,blank=True)
city = models.ForeignKey(City, on_delete=models.CASCADE, related_name='bidder',null=True,blank=True)
# etc...
# result
class BidResult(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='bid_result')
bidder = models.ForeignKey(Bidder, on_delete=models.CASCADE, related_name='bid_result')
I don't think you will have a drastic performance boost by using raw SQL instead of orm. Also, Orm can be used for complex operations, and operations such as bulk update and bulk create are not complex and as fast as normal raw SQL. Things may go slow with ORM when you try to fetch records into memory and then do the operations but in your case, it is updated and created which can be done easily using Django ORM. As far as using a function doing update_or_create, using an external library won't affect your performance but using raw SQL for marginal speed gains may impact your code maintainability as you already told, You are not much familiar with raw sql.
iam a beginner in the field. i currently doing a ecommerce website which sells samrtphone.
I want to add mulitple product images. In order to add the images
do i need more columns for every image.
How to add mutiple ram and price for product. Samrtphone have
mutiple ram according to
ram price varies.user can choose ram of the product. How to add
this in to my project using mysql. Do ineed more columns for
every ram.
in your models.py
add,
...
images = models.ManyToManyField("Image", blank=True)
varieties = models.ManyToManyField("Variety", blank=True)
...
class Image(models.Model):
caption = models.CharField(max_length=100, blank=True)
file = models.ImageField(upload_to="product_images/")
class Variety(models.Model):
ram = models.CharField(max_length=100)
price = models.IntegerField()
I gotta a school management web app. In my app teachers can create exams and then add grades to that. I've created a separate model for grades. This is my models right now:
class Grade(models.Model):
student = models.ForeignKey(
Student,
on_delete=models.CASCADE,
related_name="grade_user",
)
subject = models.ForeignKey(
Subject,
on_delete=models.CASCADE,
related_name="grade_subject",
)
grade = models.DecimalField(max_digits=6, decimal_places=2)
class Exam(models.Model):
...
grades = models.ManyToManyField(
Grade,
related_name="exam_grades",
blank=True,
)
Now I've created a form like following:
Teachers fill the fields and then using a single button this should be submitted. But the problem is that I don't know how to implement such implementation. I read somethings about formsets but I want the fields to be in a single column.
Is there any way to get this done?
I am seeking to create a relational database design in Django where one table has relationships with multiple models in the DB.
The sample models are excerpted below.
from __future__ import unicode_literals
from django.db import models
class State(models.Model):
state_name = models.CharField(max_length=100, unique=True)
class District(models.Model):
state_id = models.ForeignKey(State, on_delete=models.CASCADE)
district_name = models.CharField(max_length=100)
class County(models.Model):
county_id = models.ForeignKey(County, on_delete=models.CASCADE)
district_id = models.ForeignKey(District, on_delete=models.CASCADE)
county_name = models.CharField(max_length=100, unique=True)
class Kiosk(models.Model):
county_id = models.ForeignKey(County, on_delete=models.CASCADE)
kiosk_name = models.CharField(max_length=100)
kiosk_type = models.CharField(max_length=100)
kiosk_size = models.CharField(max_length=100)
class Operator(models.Model):
kiosk_id = models.ForeignKey(County, on_delete=models.CASCADE)
operator_name = models.CharField(max_length=100)
The overall goal is to register kiosks and their operators in the administrative territories. All relationships between the models are one-to-many. Administrative territories are hierarchical from the States-Counties-Townships which according to the schema design leads to one table having many foreign keys. For example Township(state_id, county_id) and Kiosk(state_id, county_id, township_id) and so forth.
If such a design is appropriate, then how would i model it in Django such that a single model like kiosk has 2 or 3 foreign keys relating to the other models?
If i attempt to add foreign keys as it appears in the County model i get the following error on applying migrations.
You are trying to add a non-nullable field 'region_id' to county without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
It is obviously not the way to do it and i am seeking guidance from anyone who might have a solution to this problem.
I am working in Django 1.10.
Thank you all.
I am putting together a video library in django. So far I have a few courses, each subgrouped to a topic, then each topic has 10-20 videos each.
I would like to provide ordering for each grouping of videos within a topic. So when a user goes through the lessons there is a specific sequence to the videos.
My challenge is how to store the ordering of videos in my database backend (mysql) and further how to look up and retrieve the order? I also want to have (previous) and (next) links so a user can easily click through the sequence.
At first I was thinking I would just have a "sequence" int field on my video model, then look that up and simply find the next or previous one. However, what if a number is skipped when entering the sequence? I'd like to enforce the numbering in each sequence too.
Here's some code so far:
class Video(models.Model):
title = models.CharField(max_length=200)
description = models.CharField(max_length=500, blank=True)
topic = models.ForeignKey('VideoTopic')
sequence = models.IntegerField(default=1, null=True, help_text="(Sequence within the topic)")
class VideoTopic(models.Model):
name = models.CharField(max_length=200, blank=True)
description = models.TextField(blank=True)
course = models.ForeignKey('course.Course')
While this somewhat fulfills the base requirements of sequencing, I don't see how to enforce the ordering, and I'm also having difficulty looking up my previous/next videos.
I'm thinking I need to store sequence in a separate table, but I can't quite conceive how this should be done. Something like:
class VideoSequence(models.Model)
topic = models.ForeignKey('VideoTopic')
sequence = models.IntegerField()
video = models.ForeignKey('Video')
If I use the above separate table, how can I go about looking up the sequence in django?
SIMPLE ANSWER:
https://github.com/iambrandontaylor/django-admin-sortable
LESS SIMPLE ANSWER:
The standard way to do this is what you already have, with a numeric ordering field. If you want to enforce consecutive order indices you could use a signal to 'reindex' the sequences each time one is changed.
from django.db.models.signals import post_save
def update_sequence(sender, instance=False, created, **kwargs):
qs = self.topic.video_set.all().order_by('sequence')
counter = 1
for video in qs:
video.sequence = counter
video.save()
counter += 1
post_save.connect(update_sequence, sender=Video)
Then to get the next/previous item in the sequence:
models.py:
class Video(models.Model):
....
class Meta:
order_by = 'sequence'
def get_next(self):
return self.__class__.filter(sequence__gt=self.sequence)[0]
def get_prev(self):
return self.__class__.filter(sequence__lt=self.sequence)[-1]