Django get id from model - django

how can I get id from just created model so that it can be used in item_name column.
I was thinking about sth like this:
class Items(models.Model):
item_id = models.AutoField(primary_key=True)
item_name = models.CharField(
max_length=100, default="Item #{}".format(item_id)
)

you can use in default callable object, something, like function, but not the lambda:
set_name(obj):
return f'Item #{obj}' # this is not work for new object
class Items(models.Model):
# item_id = models.AutoField(primary_key=True) you dont need it, it will be created automatically
item_name = models.CharField(
max_length=100, default=set_name.format(item_id)
)
One problem - this is not work for new object, you always will receive None. But your item_name is static, that's why you can made a property, for example:
class Items(models.Model):
# item_id = models.AutoField(primary_key=True) you don't need it, it will be created automatically
name = models.CharField(
max_length=100, null=false, blank=true, default='')
#property
def item_name(self):
return f'{self.name or 'Item'} #{self.pk or "New object"}'
Other possibility is - to override __str__ or __repr__:
class Items(models.Model):
# item_id you don't need it, it will be created automatically
# item_name you don't need it too
def __str__(self):
return f'Item #{self.pk}'
def __repr__(self):
return f'{self}'
#property
def item_name(self):
return f'{self}'

Related

Django custom models.Manager queryset field undefined

I'm implementing a soft delete for class Animal. Following the example in the docs I created a custom manager for it, but the query field, 'Inactive_Date' is undefined. I tried putting the AnimalManager class def inside the Animal class def; no help.
Code from models.py:
class AnimalManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(Inactive_Date == None)
class Animal(models.Model):
Name = models.CharField(max_length=64, unique=True)
Inactive_Date = models.DateField(null=True, blank=True)
Animal_Type = models.ForeignKey(Animal_Type, null=True, on_delete=models.SET_NULL, default=None)
Comments = models.CharField(max_length=255, blank=True)
def __str__(self) -> str:
return (self.Name)
def delete(self):
self.Inactive_Date = datetime.datetime.today()
self.save()
objects = AnimalManager() # omits inactive animals
Seems like you have double equal sign on the filtering
return super().get_queryset().filter(Inactive_Date == None)
^^
But regardless, checking for NULL value can be done via __isnull
return super().get_queryset().filter(Inactive_Date__isnull=True)

Set primary key in Django

The title is not entirely accurate, but I do not know how to explain, so I took a screenshot of where my problem is, and I will try to explain what I am trying to achieve.
I have a vehicle model, and when I create a new vehicle object, the name of vehicles just says Vehicle object (1) How can I change my model, or serializer (or something else) so that will show some unique value of the object.
Here is my model:
class Vehicle(models.Model):
make = models.CharField(max_length=100, blank=True)
model = models.CharField(max_length=300, blank=True)
license_plate = models.CharField(max_length=7, blank=True)
vehicle_type = models.CharField(max_length=20, blank=True)
seats = models.IntegerField(default=4,
validators=[
MaxValueValidator(70),
MinValueValidator(4)],
)
year = models.IntegerField(_('year'), default=datetime.today().year - 10, validators=[
MinValueValidator(1975), max_value_current_year])
inspected = models.BooleanField(default=True)
# fuel_type
# fuel_price
created_at = models.DateTimeField(auto_now_add=True)
You can implement a __str__ method that returns a string, for example:
class Vehicle(models.Model):
# …
def __str__(self):
return f'{self.make} ({self.year})'
You can thus return any string, and that will be presented by default in the Django admin and the drop downs.

How to write and retrieve data from ManyToManyField inside overrided save() method?

I need to write any data to ManyToManyField via Model's form in the template, but i get an error like "... needs to have a value for field "id" before this many-to-many relationship can be used.". It shows when I try to use self.service("service" is my ManyToManyField) in my overrided save() method. I know that ManyToManyField is not basic field and it returns something like queryset, but how can i manipulate data inside save() method, because "self.service" doesn't work.
# models.py
class Appointments(models.Model):
name = models.CharField(max_length=200, db_index=True, verbose_name='Имя, фамилия')
tel = models.CharField(max_length=200, db_index=True, verbose_name='Номер телефона')
e_mail = models.CharField(max_length=200, blank=True, db_index=True, verbose_name='E-mail')
car = models.ForeignKey('Cars', null=True, on_delete=models.PROTECT, verbose_name='Тип автомобиля')
num_car = models.CharField(max_length=200, null=True, db_index=True, verbose_name='Гос.номер автомобиля')
**service = models.ManyToManyField(Services, verbose_name='Тип услуги')**
date_created = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Дата публикации заявки')
date_service = models.DateField(db_index=True, verbose_name='Дата')
time_service = models.TimeField(db_index=True, help_text="Введите время в таком формате: 15:00", verbose_name='Время')
price = models.CharField(max_length=50, db_index=True, null=True, verbose_name='Цена')
def save(self, *args, **kwargs):
for i in Services_prices.objects.all():
ccar = i.car
sservice = i.service
for d in self.service:
if self.car == ccar and d == sservice:
self.price = i.price
break
elif ccar == None and d == sservice:
self.price = i.price
break
super().save(*args, **kwargs)
# forms.py
class AppointmentForm(forms.ModelForm):
service = forms.ModelMultipleChoiceField(queryset=Services.objects.all(), required=False, widget=forms.CheckboxSelectMultiple())
class Meta:
model = Appointments
fields = ('name', 'tel', 'e_mail', 'car', 'num_car', 'service', 'date_service', 'time_service')
In order to have a many_to_many relation between two objects, you need primary keys of the both objects. Before calling super's save, your model does not have a primary key yet.
In your overriden save method, call super first, (e.g.super().save(*args, **kwargs)) then do your stuff, then save again.

Django - replace "model object" by the value

I have a model Currency defines below:
class Currency(models.Model):
"""
Currency Model
Defines the attribute of Currency
"""
class Meta:
verbose_name = "Currency"
verbose_name_plural = "Currencies"
ordering = ['Currency_Name']
def __str__(self):
return self.Currency_Name
Currency_Date = models.DateTimeField(auto_now_add=True)
Currency_Date_Update = models.DateTimeField(auto_now=True)
Currency_Name = models.CharField(max_length=3, unique=True)
Is_Secondary_Ccy = models.CharField(max_length=1, choices=Y_N_BOOLEAN)
Primary_Currency = models.ForeignKey('self', on_delete=models.DO_NOTHING, null=True) # to refer to itself
Primary_Factor = models.IntegerField(default=1)
Currency_Name_Reuters = models.CharField(max_length=3)
The model is linked to itself by the column "Primary_Currency"
In my admin (image below) I can see the linked, but if i open the dropdown, the label is not user friendly "Currency object (0) etc..."
Can I have the value "Currency_Name" of the "Primary_Currency" ?
thanks for your help :)
Use __str__() method of model class,
class Currency(models.Model):
...
# your code
def __str__(self):
try:
return self.Primary_Currency.Currency_Name
except AttributeError:
return self.Currency_Name

django - use method on every object in queryset like filter '__in' custom manager

Hello I would like to implement method for player to take list of players (query set) and leave clan
I'm looking for something like:
Player.leave_clan([1,2,3])
Player.leave_clan([p1,p2,p3])
What I have tried is the method which takes list of account_ids [1,2,3] and then I use updated method on query, but here I have to pass only account IDs
def remove_leavers(self, leavers, clan):
players = Player.objects.filter(account_id__in=leavers)
players.update(clan=None,
previous_clan=clan)
and with my current models I could call something like:
leavers = Player.objects.filter(account_id__in=[1,2,3]
for player in leavers:
player.leave_clan()
But I do not think it's right way to do. I use following models down bellow, thank you for all suggestion and recommendations.
I think I need custom manager but I did not know how to write it even after reading the documentation.
from django.db import models
class Clan(models.Model):
clan_id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
tag = models.CharField(max_length=5)
def __str__(self):
return "{tag}".format(tag=self.tag)
#property
def members(self):
return Player.objects.filter(clan=self)
def kick_player(self, player):
player.leave_clan()
class Player(models.Model):
account_id = models.IntegerField(primary_key=True)
account_name = models.CharField(max_length=250)
clan = models.ForeignKey('Clan',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='current_clan')
previous_clan = models.ForeignKey('Clan',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='previous_clan')
def __str__(self):
return '{0} - {1}'.format(self.account_name, self.account_id)
def leave_clan(self):
self.previous_clan = self.clan
self.clan = None
self.save()
If you want to use a Manager you can do this :
class PlayerManager(models.Manager):
def leave_clan(self, players):
"""
Take a list of player. And removed them from their clan
"""
for player in players:
player.leave_clan()
class Player(models.Model):
account_id = models.IntegerField(primary_key=True)
account_name = models.CharField(max_length=250)
clan = models.ForeignKey('Clan',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='current_clan')
previous_clan = models.ForeignKey('Clan',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='previous_clan')
def __str__(self):
return '{0} - {1}'.format(self.account_name, self.account_id)
def leave_clan(self):
self.previous_clan = self.clan
self.clan = None
self.save()
How to use it
Player.objects.leave_clan(LIST_PLAYERS)
Hope it helps you.