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
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)
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.
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.
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
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.