Form to delete specific attributes in Django - django

Sorry for the noobish question, but I am trying to make a simple stock management website with Django and I could not get this part to work.
I could not get the part where I register a certain amount of crates of soda and then when it gets taken away from the stock I want the web app to register it however amount less.
My model is as follows:
class Drink(models.Model):
category = models.CharField(max_length=100)
name = models.CharField(max_length=200, unique=True)
crate = models.IntegerField()
So if the stock manager registers 25 crates (crate) a certain drink (name) and then after some time takes 20 of the crates out for use, I want it to be able to register that 20 crates were taken out and that there are now 5 left. I want to do this on the front-end. I used this form to register a Drink object:
class CrateForm(forms.ModelForm):
class Meta:
model = Drink
fields = ["name", "category", "crate",]
labels = {'name': "Name", "crate": "Crate",}
So I guess my question is: how do I create a form that allows me to subtract whatever amount of crates I want to take out for use, and then registers the remaining amount back. It’s kind of like the CRUD stuff where it lets me update that specific field crate.
PS: it should also give me an error when I try to take out 60 crates when I only have 20 crates in the stock.
Like I said I am just getting started on Django and I am stuck here for good. Any ideas??

One of many ways: use an ordinary form.
class SoldCrateForm( forms.Form):
quantity_sold = forms.IntegerField( ...)
in a FormView, do the work in the form_valid method. A secondary question is how to know which Drink you are operating on. You could select it in the same form, or if it's already known you could pass it in the URL. I'll assume the latter, that it's been parsed in an URL definition as drink:
def form_valid(self, form):
drink = Drink.objects.get( pk = self.kwargs['drink'] )
stock = drink.crate
sold = form.cleaned_data['quantity_sold']
if sold > stock:
form.add_error('quantity_sold',
f'There are only {stock} crates in stock')
return self.form_invalid( self, form)
drink.crate = drink.crate - sold
drink.save()
return super().form_valid( self, form)

Related

Is it possible to link multiple models to one fiel in django?

Let's say I have these models:
class Material(models.Model):
name = models.CharField([...])
class Consumable(models.Model):
name = models.CharField([...])
restores = models.IntegerField([...])
class Weapon(models.Model):
name = models.CharField([...])
damage = models.IntegerField([...])
# And then I have an 'inventory', like this one:
class Inventory(models.Model):
user = models.ForeignKey([...]) # to which user you want to link the item
item = models.ForeignKey([...]]) # which item
quantity = models.IntegerField([...]) # how many of it
I want to be able to have all Material, Consumable, and Weapon models listed in the 'item' field, so when you want to add an item as an inline, you would see all 3 models' objects.
Something like
# instead of this
item = models.ForeignKey(Consumable) # which item
# want something like this
item = models.ForeignKey(Consumable and Material and Weapon) # which item
# this wouldn't work ofc...
Is there a way to collect all 3 of them and pass them to the 'item' field, without the need of restarting the server? (when making a "choices" list that queries from a model you must restart the server to see the newly added objects, I don't want that.)
I also want to stick to the built-in admin of Django since it provided everything I need for the past couple of months, but I am open to any ideas.
I could be wrong but I think you are making this more complex than it needs to be. Instead of doing separate classes for materials (type of material) and consumable (type of product), you can have that built in the last class as model field as category or bolean fields.
class Products(models.Model):
material_type =
consumable = boolean for yes no or you can do multiple choice field
Then for items you can query the number of items based on material_type or consumable model fields (see query filters for for more).
all_items = Products.model.all()
consumable_items = Products.model.filter(your filter logic goes here)
Hope this helps!

Django best practice models question (from a beginner)

I want to create a model in Django that can describes a garden with rows for plants. Every plant needs some room to grow and i want to describe how many plants would fit in a row - I am a little bit stuck on how to best describe this in Django:
from django.db import models
from django.contrib.auth.models import User
class Plant(models.Model):
name = models.CharField('Plantname', max_length=120)
size = models.PositiveIntegerField("area around plant in cm")
qty = models.PositiveIntegerField("number of plants")
color = models.CharField("color of blossom", max_length=20)
class Patch(models.Model):
FERT = "fertilized"
BIO = "biological"
METHODS = ((FERT, "Fertilized"), (BIO, "Biological"))
type = models.Charfield("kind of patch", max_length=20, choices=METHODS)
qty = models.PositiveIntegerField("number of patches")
size = models.PositiveIntegerField("length of patch in cm")
class task(models.Model):
task_id = models.PositiveIntegerField('Task ID')
person = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
patches = models.ManyToManyField(Patch)
plants = models.ManyToManyField(Plant)
Now I create:
two example patches with 300 and 400cm length
two example plants with 20 and 15cm length
and I want to assign a task to a person that has the number of patches and plants he needs to work on.
So when a task is created, I need to:
ask for the size and number of the patches
Choose the type of plant
Calculate max. amount of plants possible
ask for the number of plants and set it max(plants) if number > max(plants)
create a task with the total quantity of patches and plants
can someone please help me out :)
Your models look fine. You'll have to ask for user input using Django Forms. You can probably use a ModelForm for your Task model, then override the save()
method to add your business logic.
Also, you should rename class task to class Task (or better still class FarmingTask since 'task' is a keyword used in several software libraries/languages and might conflict at a later time.)

Django Model - CharField as concatenation of other fields

I'm learning Django and looking for a best practice:
Imagine I have a model for a mobile phone device:
class Device(models.Model):
vendor = models.CharField(max_length=100)
line = models.CharField(max_length=100, blank=True)
model = models.CharField(max_length=100)
Let's say I create an object like this:
Device.objects.create(vendor = "Apple",
line = "iPhone",
model = "SE"
)
or without "line":
Device.objects.create(vendor = "Xiaomi",
model = "Mi 6"
)
Then I'd like to track sales in my shop for every device, so I create a model for a "Deal" (I track only the deal date and the device sold, device as a ForeignKey):
class Deal(models.Model):
device = models.ForeignKey(Device, on_delete=models.CASCADE)
deal_date = models.DateTimeField(default=None)
Question:
What is the best way to create a "Deal" object, if I want to query "Device" by its full, concatenated name, e.g. "Apple iPhone SE" or "Xiaomi Mi 6"?
I've found something similar in Django database entry created by concatenation of two fields , however not sure if it's the right path in my case.
My best guess is something like this (where "name" is a concatenated field):
de = Device.objects.get(name = "Apple iPhone SE")
Deal.objects.create(device = de,
deal_date = datetime(2018, 4, 26, 15, 28)
)
What is the correct way to do this task? Many thanks for your help!
Thanks for your advice guys, searching a little bit more I've found an answer appropriate in my case:
what I did is I tweaked save() method, which now populates a field automatically as a concatenation of 3 other fields.
#propertywas usefull in this case too
Supposing that you var name contains your text search criteria, and usign your data models, you could use annotation to create a field to each object returned by your query set, and then filter using this field
You could try some as follow (it is not tested)
import datetime
from django.db.models import F
from your.app.models import Deal, Device
# supposing is in your view, but like sounds as a model method
def my_view(request, *args, **kwargs)
name = request.POST.get('name')
device_qs = Decive.objects.all().annotate(text_concatenated='{} {} {}'.format(F('vendor'), F('line'), F('model'))).filter(text_concatenated=name)
try:
device = device_qs.get()
except Device.DoesNotExist:
# to manage the scenario when doesn't exist any match
# here you manage this situation
pass
except Device.MultipleObjectsReturned:
# to manage the scenario when various devices have the same 'text concatenated', i dont know, maybe data model should be improved
# here you manage this situation
device = device_qs.first()
deal = Deal.objects.create(device=device, deal_date=datetime.datetime.now())
# build your response and return it

Database design under Django

I have a probably quite basic question: I am currently setting up a database for students and their marks in my courses. I currently have two main classes in my models.py: Student (containing their name, id, email address etc) and Course (containing an id, the year it is running in and the assessment information - for example "Essay" "40%" "Presentation" "10%" "Exam" "50%"). And, of course, Student has a ManyToMany field so that I can assign students to courses and vice versa. I have to be able to add and modify these things.
Now, obviously, I would like to be able to add the marks for the students in the different assignments (which are different from course to course). As I am very unexperienced in database programming, I was hoping one of you could give me a tip how to set this up within my models.
Thanks,
Tobi
Perhaps the way to go about it is to have a separate class for assignment, something like this.
class Assignment(models.Model):
ASSIGNMENT_TYPES = (
('essay', "Essay"),
...
)
ASSIGNMENT_GRADES = (
('a+', "A+"),
('a', "A"),
...
)
student = models.ForeignKey("Student")
course = models.ForeignKey("Course")
assignment_type = models.CharField(choices=ASSIGNMENT_TYPES, max_length=15, default='essay')
progress = models.IntegerField()
grade = models.CharField(choices=ASSIGNMENT_GRADES, max_length=3, default="a+")
This way you have one assignment connected to one student and one course. It can be modified relatively easy if you have multiple students per one assignment, by adding another class (for example StudentGroup) and including it in the model.
Hope that this helps :)
Create a model called "Assessments", which has a foreign key to Course. In addition ,create a field called "Assessment Type", another called "Assessment Result" and a final one called "Assesment Date". Should look like this:
ASSESSMENTS = (('E','Essay'),('P','Presentation'))
class Assessment(models.MOdel):
course = models.ForeignKey('Course')
assessment = models.CharField(choices=ASESSMENTS)
result = models.CharField(max_length=250)
taken_on = models.DateField()
overall_result = models.BooleanField()
is_complete = models.BooleanField()
Each time there is an exam, you fill in a record in this table for each assessment taken. You can use the overall result as a flag to see if the student has passed or failed, and the is_complete to see if there are any exams pending for a course.
You should look at models.py file of classcomm,
a content management system written in Django for delivering and managing Courses on the Web.
It has following Models
Department
Course
Instructor
Mentor
Enrollment
Assignment
DueDateOverride
Submission
Grade
ExtraCredit
Information
Resource
Announcement
You may not need such a complex relationship for you case, but it's wort looking into it's models design.
You can find more details on homepage of this project.

Figuring out how to design my model and using "through"

I'm trying to figure out how to design my model. I've been going over the documentation, and it ultimately seems like I should be using the "through" attribute, but I just can't figure out how to get it to work how I want.
If someone could take a look and point out what I'm missing, that would be really helpful. I have pasted my model below.
This is what I am trying to do:
1) Have a list of server types
2) Each server type will need to have different parts available to that specific server type
3) The asset has a FK to the servermodel, which has a M2M to the parts specific to that server type.
My question is, how can each "Asset" store meta data for each "Part" specific to that "Asset"? For example, each "Asset" should have it's own last_used data for the part that's assigned to it.
Thanks! :)
class Part(models.Model):
part_description = models.CharField(max_length=30,unique=1)
last_used = models.CharField(max_length=30)
def __unicode__(self):
return self.part_description
class ServerModel(models.Model):
server_model = models.CharField(max_length=30,unique=1)
parts = models.ManyToManyField(Part)
def __unicode__(self):
return self.server_model
class Asset(models.Model):
server_model = models.ForeignKey(ServerModel)
serial_number = models.CharField(max_length=10,unique=1)
def __unicode__(self):
return self.server_model.server_model
EDIT:
Thank you for the help!
I may have not explained myself clearly, though. It's probably my confusing model names.
Example:
ServerModel stores the type of server being used, say "Dell Server 2000".
The "Dell Server 2000" should be assigned specific parts:
"RAM"
"HARD DISK"
"CDROM"
Then, I should be able to create 10x Assets with a FK to the ServerModel. Now, each of these assets should be able to mark when the "RAM" part was last used for this specific asset.
I'm not sure I exactly understand what you want to do, but basically you can solve that with a "through" model, as you expected:
import datetime
class Part(models.Model):
name = models.CharField(max_length=30,unique=1)
class ServerModel(models.Model):
server_model = models.CharField(max_length=30,unique=1)
parts = models.ManyToManyField(Part,through='Asset')
class Asset(models.Model):
server_model = models.ForeignKey(ServerModel)
part = models.ForeignKey(Part)
serial_number = models.CharField(max_length=10,unique=1)
used = models.DateTimeField(default=datetime.datetime.now())
First thing to notice is the relation of the parts to the servermodel using the "through"-model: that way for each Part instance assigned to the "parts"-property of a ServerModel instance a new Asset instance is created (Phew - hope that doesn't sound too complicated). At the time of creation the "used"-property of the Asset instance is set to the current date and time (thats what default=datetime.datetime.now() does).
If you do that, you can then just query the database for the last asset containing your part. That queryset can then be sorted by the "used" property of the Asset model, which is the date when the Asset instance has been created.
ServerModel.objects.filter(parts__name='ThePartYouAreLookingFor').order_by('asset__used')
I'm not absolutely sure if the queryset is correct, so if someone finds huge nonsense in it, feel free to edit ;)
edit:
The models above do not exactly that. But you do not even need a through model for what you want:
class ServerModel(models.Model):
server_model = models.CharField(max_length=30,unique=1)
parts = models.ManyToManyField(Part)
class Asset(models.Model):
server_model = models.ForeignKey(ServerModel)
parts = models.ForeignKey(Part)
serial_number = models.CharField(max_length=10,unique=1)
used = models.DateTimeField(default=datetime.datetime.now())
Basically you can just add assets and then query all assets that have a RAM in parts.
Asset.objects.filter(parts__contains='RAM').order_by('used')
Get the date of the first (or last) result of that queryset and you have the date of the last usage of your 'RAM'-part.